1 # .bashrc générique mis à votre disposition
2 # par les gentils membres actifs du Cr@ns
3 # Vous pouvez l'utiliser, le redistribuer, le modifier à votre convenance.
4 # Des questions, des suggestions : {nounou,ca}@lists.crans.org
7 # Les sections commentées par #~# sont des features qui ne sont pas activées
8 # par défaut. Sentez-vous libre de les décommenter pour les utiliser.
10 #------------------------------------------------------------------------------
12 # Pour les shells non interactif (sous emacs, avec rcp, ...)
13 # on ne charge pas le .bashrc
14 [ -z "$PS1" -o "$TERM" = dumb ] && return
16 # Hack pour que $COLUMNS contienne le nombre de colonne du terminal
17 # Sinon, le prompt kikoo risque de déborder/être trop court
21 # +-------------------------+
22 # | Customizations diverses |
23 # +-------------------------+
25 # Utilisation de lesspipe comme PAGER si il est présent
26 [[ -x /usr/bin/lesspipe ]] && eval "$(lesspipe)"
28 # Couleur pour certaines commandes (ls, …)
29 if [ -x /usr/bin/dircolors ]; then
30 test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
34 [ -f /etc/bash_completion ] && . /etc/bash_completion
35 # Placez vos fichiers de bash-complétion custom dans ~/.bash_completion.d/
36 # ils seront chargés par la ligne suivante
37 [ -d ~/.bash_completion.d/ ] && for f in ~/.bash_completion.d/*; do source $f; done
43 # Définition de fonction pour pouvoir afficher dans le prompt
44 # des infos quand on est dans un dépôt versionné
46 # Checks if the command provided is in the commands list and is
49 [[ -n ${commands[$1]} ]] && [ -x ${commands[$1]} ] && return 0
53 # If name should be overwritten (eg for git-svn), do it.
55 [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
59 # Formats two VCS_info messages, one with colors, and one without
61 local action=$1 branch=$2 base=$3 rev=$4
65 # printf is for readability (it's easier to find %s)
66 msg="(%s)${MINUS_CHAR}[%s/%s"
67 msg=$(printf $msg $vcs ${base/*\/} $branch)
69 # If there is a revnumber, print it
70 if [ ! -z ${rev} ]; then
72 msg=$(printf $msg $rev)
75 # Print the current cvs action state
76 if [ ! -z ${action} ] ; then
78 msg=$(printf $msg $action)
80 msg="${msg}]${MINUS_CHAR}"
84 # Same shit with colors
85 msg="${nocolor_prompt}${vcs_symbols_color}(${vcs_type_color}%s${vcs_symbols_color})${vcs_sep_color}${MINUS_CHAR}${vcs_symbols_color}[${vcs_repo_color}%s${vcs_sep_color}/${vcs_branch_color}%s"
86 msg=$(printf $msg $vcs ${base/*\/} $branch)
87 if [ ! -z ${rev} ]; then
88 msg="${msg}${vcs_colon_color}:${vcs_rev_color}%s"
89 msg=$(printf $msg $rev)
91 if [[ ! -z ${action} ]] ; then
92 msg="${msg}${nocolor_prompt}|${vcs_action_color}%s"
93 msg=$(printf $msg $action)
95 msg="${msg}${vcs_symbols_color}]${nocolor_prompt}${MINUS_CHAR}"
101 # Uses -P option for cd in order to resolve symlinks
104 cd -P $1 2>/dev/null && pwd
108 # Feature to detect a special dir, at the top of
112 local basedir="." realbasedir
114 realbasedir="$(vcs_realpath ${basedir})"
115 while [[ ${realbasedir} != '/' ]]; do
116 [[ -r ${realbasedir} ]] || return 1
118 # Tries to find detect_need_file (eg formats) in the dir
119 if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
120 [[ -d ${basedir}/${dirname} ]] && \
121 [[ -e ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
124 [[ -d ${basedir}/${dirname} ]] && break
127 basedir=${basedir}/..
128 realbasedir="$(vcs_realpath ${basedir})"
131 [[ ${realbasedir} == "/" ]] && return 1
132 vcs_comm[basedir]=${realbasedir}
138 if check_command git && git rev-parse --is-inside-work-tree &> /dev/null; then
139 vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
140 if [[ -d ${vcs_comm[gitdir]}/svn ]] ; then vcs_comm[overwrite_name]='git-svn'
141 elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
149 check_command hg || return 1
150 vcs_comm[detect_need_file]=store
156 # TODO - Not working : imported from zsh but not post treated
162 check_command svk || return 1
163 [[ -f ~/.svk/config ]] || return 1
165 # This detection function is a bit different from the others.
166 # We need to read svk's config file to detect a svk repository
167 # in the first place. Therefore, we'll just proceed and read
168 # the other information, too. This is more then any of the
169 # other detections do but this takes only one file open for
170 # svk at most. VCS_INFO_svk_get_data() get simpler, too. :-)
171 while IFS= read -r line ; do
172 if [[ -n ${vcs_comm[basedir]} ]] ; then
174 [[ ${line} == depotpath:* ]] && vcs_comm[branch]=${line##*/}
175 [[ ${line} == revision:* ]] && vcs_comm[revision]=${line##*[[:space:]]##}
176 [[ -n ${vcs_comm[branch]} ]] && [[ -n ${vcs_comm[revision]} ]] && break
179 (( fhash > 0 )) && [[ ${line} == ' '[^[:space:]]*:* ]] && break
180 [[ ${line} == ' hash:'* ]] && fhash=1 && continue
181 (( fhash == 0 )) && continue
182 [[ ${PWD}/ == ${${line## ##}%:*}/* ]] && vcs_comm[basedir]=${${line## ##}%:*}
185 [[ -n ${vcs_comm[basedir]} ]] && \
186 [[ -n ${vcs_comm[branch]} ]] && \
187 [[ -n ${vcs_comm[revision]} ]] && return 0
191 # .svn in each directories
193 check_command svn || return 1
194 [[ -d ".svn" ]] && return 0
199 check_command bzr || return 1
200 vcs_comm[detect_need_file]=branch/format
206 check_command cdv || return 1
207 vcs_comm[detect_need_file]=format
213 check_command svn || return 1
214 [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
219 check_command darcs || return 1
220 vcs_comm[detect_need_file]=format
221 detect_by_dir '_darcs'
227 local gitbranch gitdir=$1 tmp actiondir
228 local gitsymref='git symbolic-ref HEAD'
230 # In certain circumstances, we have to take into account
233 for tmp in "${gitdir}/rebase-apply" \
235 "${gitdir}/../.dotest"; do
236 if [[ -d ${tmp} ]]; then
241 if [[ -n ${actiondir} ]]; then
242 gitbranch="$(${gitsymref} 2> /dev/null)"
243 [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \
244 && gitbranch="$(< ${actiondir}/head-name)"
247 elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
248 gitbranch="$(eval $gitsymref 2> /dev/null)"
249 [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)"
252 elif [[ -d "${gitdir}/rebase-merge" ]] ; then
253 gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
256 elif [[ -d "${gitdir}/.dotest-merge" ]] ; then
257 gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
261 gitbranch="$(eval $gitsymref 2> /dev/null)"
264 if [[ $? -ne 0 ]] ; then
265 gitbranch="refs/tags/$(git describe --exact-match HEAD 2>/dev/null)"
268 if [[ $? -ne 0 ]] ; then
269 gitbranch=$(< $gitdir/HEAD)
270 gitbranch="${gitbranch:0:7}..."
275 # keep only the last part of gitbranch
276 printf '%s' "${gitbranch#refs/[^/]*/}"
281 local gitaction='' gitdir=$1
284 for tmp in "${gitdir}/rebase-apply" \
286 "${gitdir}/../.dotest" ; do
287 if [[ -d ${tmp} ]] ; then
288 if [[ -f "${tmp}/rebasing" ]] ; then
290 elif [[ -f "${tmp}/applying" ]] ; then
293 gitaction="am/rebase"
295 printf '%s' ${gitaction}
300 for tmp in "${gitdir}/rebase-merge/interactive" \
301 "${gitdir}/.dotest-merge/interactive" ; do
302 if [[ -f "${tmp}" ]] ; then
303 printf '%s' "rebase-i"
308 for tmp in "${gitdir}/rebase-merge" \
309 "${gitdir}/.dotest-merge" ; do
310 if [[ -d "${tmp}" ]] ; then
311 printf '%s' "rebase-m"
316 if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
321 if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
329 local gitdir gitbase gitbranch gitaction
331 gitdir=${vcs_comm[gitdir]}
332 gitbranch="$(git_getbranch ${gitdir})"
334 if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
339 gitaction="$(git_getaction ${gitdir})"
340 gitprefix=$(git rev-parse --show-prefix)
341 gitbase=${PWD%/${gitprefix%/}}
342 vcs_formats "${gitaction}" "${gitbranch}" "${gitbase}" ''
347 local hgbranch hgbase file
349 hgbase=${vcs_comm[basedir]}
351 file="${hgbase}/.hg/branch"
352 if [[ -r ${file} ]] ; then
353 hgbranch=$(< ${file})
358 vcs_formats '' "${hgbranch}" "${hgbase}" ''
363 local svkbranch svkbase
365 svkbase=${vcs_comm[basedir]}
366 svkbranch=${vcs_comm[branch]}
367 svkrevision=${vcs_comm[revision]}
368 vcs_formats '' "${svkbranch}" "${svkbase}" "${svkrevision}"
373 local svnbase svnbranch
377 while [[ -d "${svnbase}/../.svn" ]]; do
378 svnbase="${svnbase}/.."
380 svnbase="$(vcs_realpath ${svnbase})"
381 svnrev=$(svn info | awk '{if($1 == "Révision :") print $2}')
382 svnbranch=$(svn info | awk '{if($1 == "URL :") print $2}'|awk -F "/" '{ print $NF }')
384 vcs_formats '' "${svnbranch}" "${svnbase}" "${svnrev}"
392 bzrbase=$(bzr info|awk '{if ($1 == "branch" && $2 == "root:") print $3}')
393 bzrbranch=$(bzr version-info|awk '{if ($1 == "branch-nick:") print $2}')
394 bzrrev=$(bzr version-info|awk '{if ($1 == "revno:") print $2}')
395 bzrbase="$(vcs_realpath ${bzrbase})"
398 vcs_formats '' "${bzrbr}" "${bzrbase}" "${bzrrev}"
405 cdvbase=${vcs_comm[basedir]}
406 vcs_formats '' "${cdvbase/*\/}" "${cdvbase}" ''
411 local cvsbranch cvsbase basename
414 while [[ -d "${cvsbase}/../CVS" ]]; do
415 cvsbase="${cvsbase}/.."
417 cvsbase="$(vcs_realpath ${cvsbase})"
418 cvsbranch=$(< ./CVS/Repository)
419 basename=${cvsbase/*\/}
420 cvsbranch=${cvsbranch#${basename}/}
422 [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
423 vcs_formats '' "${cvsbranch}" "${cvsbase}" ''
430 darcsbase=${vcs_comm[basedir]}
431 vcs_formats '' "${darcsbase/*\/}" "${darcsbase}" ''
438 local -Ax vcs_comm commands
443 vcss=(git hg bzr darcs svk svn cvs cdv)
444 for i in $(seq 0 $(( ${#vcss[*]} - 1 ))); do
445 commands[${vcss[$i]}]=$(which ${vcss[$i]});
449 for vcs in ${vcss[*]}; do
450 ${vcs}_detect && found=1 && break
453 (( found == 1 )) && ${vcs}_get_data
455 if [ ${color_prompt} = "yes" ]; then
463 # Pour avoir le bon umask en fonction du dossier où on se trouve
464 # L'umask définit avec quel droits un fichier est créé.
465 # Quand on écrit dans un dossier et qu'on veut que, par défaut,
466 # d'autres personnes puissent modifier les fichiers, il faut changer l'umask.
467 # Rien de spécial n'arrivera si vous n'avez pas le fichier .umaskrc
471 if [ -f ~/.umaskrc ]; then
472 umask $(/usr/bin/awk 'BEGIN {pwd=ENVIRON["PWD"]"/"; a=length(pwd); cmax=0} {if($1==pwd) {MASK=$2;exit}; c=length($1); if(c>a) {next}; if(substr(pwd,0,c+1)==$1 && c > cmax) {cmax=c; MASK=$2}} END {print MASK}' ~/.umaskrc) >/dev/null
477 ### Attention à ce que vous éditez dans cette section ###
478 ### v v v v v v v v v v ###
479 # +----------------------+
480 # | Génération du prompt |
481 # +----------------------+
483 # Définition des couleurs
484 # Pour les utiliser dans le prompt,
485 # les couleurs doivent être entourés de \[ et \] pour délimiter les caractères
490 violet_thin='\e[0;35m'
492 jaune_thin='\e[0;33m'
494 rouge_thin='\e[0;31m'
500 blanc_thin='\e[0;37m'
502 cyan_prompt="\[${cyan}\]"
503 cyan_thin_prompt="\[${cyan_thin}\]"
504 violet_prompt="\[${violet}\]"
505 violet_thin_prompt="\[${violet_thin}\]"
506 jaune_prompt="\[${jaune}\]"
507 jaune_thin_prompt="\[${jaune_thin}\]"
508 rouge_prompt="\[${rouge}\]"
509 rouge_thin_prompt="\[${rouge_thin}\]"
510 vert_prompt="\[${vert}\]"
511 vert_thin_prompt="\[${vert_thin}\]"
512 bleu_prompt="\[${bleu}\]"
513 bleu_thin_prompt="\[${bleu_thin}\]"
514 blanc_prompt="\[${blanc}\]"
515 blanc_thin_prompt="\[${blanc_thin}\]"
516 nocolor_prompt="\[${nocolor}\]"
519 # Est-ce qu'on veut que le prompt affiche les information sur l'éventuel dépôt
520 # versionné dans lequel on se trouve
521 #~# # Changez cette variable en "yes" pour l'afficher
525 # Génération de la ligne de "-"
526 function gen_minus_line
531 # Pas la peine de refaire le travail tant qu'on ne change
532 # pas le nombre de colonnes.
533 SAVE_COLUMNS=$COLUMNS
535 for ((i = COLUMNS-23; i>0; i--)); do
536 MINUS_LINE=$MINUS_CHAR$MINUS_LINE
540 # Génération du prompt après chaque commande
541 function prompt_command
543 local pwd ERR DATE PROMPT DIR POST_DIR
544 # Cette fonction génère un prompt sur deux lignes
545 # ayant cette allure :
546 # ─( 12:59:05 )─< ~ >───────────────────────────────────────────────────────[ 0 ]─
549 # Attention aux hacks (échappement, interprétation des variables)
550 # pour que les couleurs (et leurs tailles)
551 # soient évaluées au moment de l'affichage du prompt
552 # Si le terminal a été redimensionné, on régénère la ligne de tirets
553 (( SAVE_COLUMNS == COLUMNS )) || gen_minus_line
555 # À décommenter si on veut afficher des infos
556 # quand on se trouve dans un dépôt versionné
557 if [ "$display_vcs_info" = yes ]; then
561 # Chemin courant, en faisant attention à la largeur de la fenêtre
562 pwd=${PWD/#$HOME/'~'}
563 if (( ${#pwd} + ${VCS_size} + 27 > COLUMNS )); then
564 if (( COLUMNS >= 33 )); then
565 DIR='..'${pwd:${#pwd}+${VCS_size}+30-COLUMNS}
566 POST_DIR='${MINUS_LINE:0:4-${#?}}'
573 POST_DIR='${MINUS_LINE:'${#pwd}+${VCS_size}+1'+${#?}}'
576 # Génération des différents morceaux du prompt, avec ou sans la couleur
577 if [ "$color_prompt" = yes ]; then
578 DIR="< ${pwd_color}"$DIR"${line_color_prompt} >"
579 # On affiche le code de retour en "no color" si c'est 0, en rouge sinon
580 # Ceci n'est pas customizable à coup de variable,
581 # il faut changer $((31+($?==0)*6)) si vous y tenez vraiment et que vous comprenez ce que vous faites
582 ERR='[ \[\e[1;$((31+($?==0)*6))m\]$?'${line_color_prompt}' ]'$MINUS_CHAR
583 # Affichage de l'heure courante
584 # pratique pour savoir quand on a tapé la commande précédente
585 DATE="( ${date_color}\D{%H:%M:%S}${line_color_prompt} )"
586 # Deuxième ligne du prompt "user@host $"
587 # Attention "\\\$" devient \$, c'est-à-dire # pour root, $ pour les autres
588 PROMPT="${username_color}\u${symbols_color}@${host_color}\h ${symbols_color}\\\$ ${nocolor_prompt}"
589 # On fusionne tout ça
590 PS1=$TITLE${line_color_prompt}$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR$VCS_info${line_color_prompt}$POST_DIR$ERR'\n'$PROMPT
593 ERR='[ $? ]'$MINUS_CHAR
594 DATE="( \D{%H:%M:%S} )"
596 PS1=$TITLE$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR$VCS_info$POST_DIR$ERR'\n'$PROMPT
600 if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
601 # support de la couleur
603 # Couleurs dans "user@host $"
604 username_color=${rouge_prompt}
605 host_color=${bleu_prompt}
606 symbols_color=${vert_prompt}
607 # Couleur de la ligne séparatrice de prompt
609 line_color_prompt=${cyan_prompt}
610 # Couleur du path actuel
611 pwd_color=${jaune_prompt}
612 # Couleur de la date (à chaque affichage du prompt)
613 date_color=${violet_prompt}
614 # Couleur de la date au premier affichage (à l'ouverture du terminal)
615 announce_date_color=${blanc}
616 # Couleur d'affichage de vcs_info
617 vcs_symbols_color=${violet_thin_prompt}
618 vcs_type_color=${jaune_thin_prompt}
619 vcs_branch_color=${vert_thin_prompt}
620 vcs_repo_color=${vert_thin_prompt}
621 vcs_action_color=${rouge_thin_prompt}
622 vcs_sep_color=${jaune_thin_prompt}
623 vcs_rev_color=${jaune_thin_prompt}
624 vcs_colon_color=${rouge_thin_prompt}
626 # pas de support de la couleur
630 # On change le titre de la fenêtre dynamiquement si on est sous X
631 if [[ $TERM = "xterm" ]]; then
632 TITLE='\[\e];\u@\h:\w\a\]'
637 # On régénère le prompt après chaque commande
638 PROMPT_COMMAND=prompt_command
640 # +-------------------+
641 # | Messages au début |
642 # +-------------------+
644 function welcome_message ()
646 # Si on supporte l'utf-8 et qu'on n'est pas dans un screen,
647 # on affiche un joli cadre avec la date.
648 # On utilise aussi un caractère plus sympa pour faire les lignes de tirets
649 if [[ $(uname) == Linux && ( $(locale charmap) == UTF-8 && $TERM != screen ) ]]; then
652 date=$(/bin/date +"%R, %A %d %B %Y")
653 # ${redate} sert à connaître la taille de la chaine $date,
654 # mais sans se planter sur le nombre d'octet/nombre de caractères
656 redate=${redate//û/u}
657 if [ "$color_prompt" = yes ]; then
658 echo -e "${line_color}┬─${redate//?/─}─┬${MINUS_LINE:${#date}-19}\n│ ${announce_date_color}$date ${line_color}│\n└─${redate//?/─}─┘\e[0m\n"
660 echo -e "┬─${redate//?/─}──┬${MINUS_LINE:${#date}-18}\n│ $date │\n└─${redate//?/─}──┘\n"
663 # Sinon, on se contente d'une ligne de tirets
669 ### ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ###
670 ### Attention à ce que vous avez édité dans cette section ###
673 # +---------------------------------------+
674 # | Gestion de l'historique des commandes |
675 # +---------------------------------------+
677 # On ne sauve pas les lignes dupliquées qui se suivent dans l'historique
678 # ainsi que les commandes qui commencent par une espace
679 export HISTCONTROL=ignoreboth
681 # Nombre de lignes d'historique à garder
684 # la même chose dans le fichier d'historique
685 export HISTFILESIZE=5000
687 # Mémoriser le timestamp d'exécution de la commande
688 export HISTTIMEFORMAT='%F %T - '
690 # pour sauvegarder les commandes de plusieurs lignes (\ ) en une seule
692 # pour enregistrer tout de suite les commandes dans l'historique
693 # et non pas à la fermeture du shell
701 # Pour éviter un troll, aucune ligne de cette section n'est décommentée.
702 # Choisissez la vôtre.
703 #~# export EDITOR='/usr/bin/nano'
704 #~# export EDITOR='/usr/bin/vim'
705 #~# export EDITOR='/usr/bin/emacs'
706 #~# export EDITOR='/usr/bin/jed'
708 # Ajouter ~/bin, /sbin et /usr/sbin à son PATH
709 PATH=~/bin:$PATH:/sbin:/usr/sbin
711 #~# # Décommentez les lignes suivantes et peuplez-les correctement si
712 #~# # vous avez besoin de commiter en tant que root *et* que votre
713 #~# # /etc/sudoers contient bien la directive
714 #~# # Defaults env_keep += "<les variables en question>"
715 #~# export GIT_AUTHOR_NAME="$(git config user.name)"
716 #~# export GIT_AUTHOR_EMAIL="$(git config user.email)"
722 # Chargement des alias
723 if [ -f ~/.bash_aliases ]; then
727 # Fichier locaux (utile quand on clone sa config sur plusieurs machines)
728 [[ -f ~/.bashrc.local ]] && . ~/.bashrc.local
730 if [ -f ~/.bash_aliases_local ]; then
731 . ~/.bash_aliases_local
739 # On n'exécute le welcome_message que à ce moment, parce que la customisation
740 # local a pu changer des couleurs