]> gitweb.pimeys.fr Git - config-20-100.git/blobdiff - .bashrc
[procmail] Tri des ML : nom-ml.domain.list*e*s.tld est géré aussi
[config-20-100.git] / .bashrc
diff --git a/.bashrc b/.bashrc
index 3d1c3d27d6f3f2416db77df48fd206b738bf0be0..522e3f1c976e68dc210d82158a667bd873371537 100644 (file)
--- a/.bashrc
+++ b/.bashrc
@@ -5,7 +5,7 @@
 # Licence : WTFPL
 
 # Les sections commentées par #~# sont des features qui ne sont pas activées
-# par défaut. Sentez-vous libre de les décommenter pour les utiliser. 
+# par défaut. Sentez-vous libre de les décommenter pour les utiliser.
 
 #------------------------------------------------------------------------------
 
@@ -36,7 +36,6 @@ fi
 # ils seront chargés par la ligne suivante
 [ -d ~/.bash_completion.d/ ] && for f in ~/.bash_completion.d/*; do source $f; done
 
-
 # +-----+
 # | VCS |
 # +-----+
@@ -44,52 +43,383 @@ fi
 # Définition de fonction pour pouvoir afficher dans le prompt
 # des infos quand on est dans un dépôt versionné
 
-find_up () {
-    path="$1"
-    shift 1
-    while [[ "`readlink -f -- \"$path\"`" != "/" ]];
-    do
-        find "$path"  -maxdepth 1 -mindepth 1 "$@"
-        path=${path}/..
-    done
+# Checks if the command provided is in the commands list and is
+# executable
+check_command(){
+    [[ -n ${commands[$1]} ]] && [ -x ${commands[$1]} ] && return 0
+    return 1
 }
 
-get_vcs_info () {
-    # Donne les infos sur le dépôt VCS courant.
-    local LBRANCH LTYPE BRANCH TYPE DIR
-    declare -a DIR
-    declare -A TYPE
-    declare -A BRANCH
-    DIR[0]=".git"
-    DIR[1]=".hg"
-    DIR[2]="_darcs"
-    DIR[3]=".svn"
-    TYPE[.git]="git"
-    TYPE[.hg]="mercurial"
-    TYPE[_darcs]="darcs"
-    TYPE[.svn]="svn"
-    BRANCH[.git]='git branch 2>/dev/null | sed -r "s/^[^*].*$//" | paste -s -d "" | sed -r "s/^[*] //"'
-    BRANCH[.hg]='hg branch 2>/dev/null'
-    BRANCH[_darcs]="darcs show repo 2>/dev/null| egrep '^ *Cache' | sed 's@.*/\([^/]*\),.*@\1@'"
-    BRANCH[.svn]="svn info 2>/dev/null | head -n 6 | tail -n 1"
-
-    DIR=$(eval "find_up \"$PWD\" -name \"\"$(printf -- ' -o -name "%s"' "${DIR[@]}") | head -n 1")
-    if [ -n "$DIR" ]; then
-        DIR=$(basename "$DIR")
-        LBRANCH=$(eval "${BRANCH[$DIR]}")
-        LTYPE="${TYPE[$DIR]}"
-        if [ "$color_prompt" = yes ]; then
-            VCS_info="${nocolor_prompt}${vcs_symbols_color}(${vcs_type_color}$LTYPE${vcs_symbols_color})-${vcs_symbols_color}[${vcs_branch_color}$LBRANCH${vcs_symbols_color}]${nocolor_prompt}"
+# If name should be overwritten (eg for git-svn), do it.
+vcs_adjust(){
+    [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
+    return 0
+}
+
+# Formats two VCS_info messages, one with colors, and one without
+vcs_formats(){
+    local action=$1 branch=$2 base=$3 rev=$4
+    local msg
+    local -i i
+
+    # printf is for readability (it's easier to find %s)
+    msg="(%s)${MINUS_CHAR}[%s/%s"
+    msg=$(printf $msg $vcs ${base/*\/} $branch)
+
+    # If there is a revnumber, print it
+    if [ ! -z ${rev} ]; then
+        msg="${msg}:%s"
+        msg=$(printf $msg $rev)
+    fi
+
+    # Print the current cvs action state
+    if [ ! -z ${action} ] ; then
+        msg="${msg}|%s"
+        msg=$(printf $msg $action)
+    fi
+    msg="${msg}]${MINUS_CHAR}"
+
+    msgs[1]=$msg
+
+    # Same shit with colors
+    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"
+    msg=$(printf $msg $vcs ${base/*\/} $branch)
+    if [ ! -z ${rev} ]; then
+        msg="${msg}${vcs_colon_color}:${vcs_rev_color}%s"
+        msg=$(printf $msg $rev)
+    fi
+    if [[ ! -z ${action} ]] ; then
+        msg="${msg}${nocolor_prompt}|${vcs_action_color}%s"
+        msg=$(printf $msg $action)
+    fi
+    msg="${msg}${vcs_symbols_color}]${line_color_prompt}${MINUS_CHAR}"
+    msgs[0]=$msg
+
+    return 0
+}
+
+# Uses -P option for cd in order to resolve symlinks
+vcs_realpath(){
+    (
+        cd -P $1 2>/dev/null && pwd
+    )
+}
+
+# Feature to detect a special dir, at the top of
+# the current repo
+detect_by_dir(){
+    local dirname=$1
+    local basedir="." realbasedir
+
+    realbasedir="$(vcs_realpath ${basedir})"
+    while [[ ${realbasedir} != '/' ]]; do
+        [[ -r ${realbasedir} ]] || return 1
+
+        # Tries to find detect_need_file (eg formats) in the dir
+        if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
+            [[ -d ${basedir}/${dirname} ]] && \
+            [[ -e ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
+                break
         else
-            VCS_info="($LTYPE)-[$LBRANCH]"
+            [[ -d ${basedir}/${dirname} ]] && break
+        fi
+
+        basedir=${basedir}/..
+        realbasedir="$(vcs_realpath ${basedir})"
+    done
+
+    [[ ${realbasedir} == "/" ]] && return 1
+    vcs_comm[basedir]=${realbasedir}
+    return 0
+}
+
+# Git is powerfull
+git_detect(){
+    if check_command git && git rev-parse --is-inside-work-tree &> /dev/null; then
+        vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
+        if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
+        elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
+        return 0
+    fi
+    return 1
+}
+
+# Mercurial isn't
+hg_detect(){
+    check_command hg || return 1
+    vcs_comm[detect_need_file]=store
+    detect_by_dir '.hg'
+    return $?
+}
+
+# .svn in each directories
+svn_detect() {
+    check_command svn || return 1
+    [[ -d ".svn" ]] && return 0
+    return 1
+}
+
+bzr_detect(){
+    check_command bzr || return 1
+    vcs_comm[detect_need_file]=branch/format
+    detect_by_dir '.bzr'
+    return $?
+}
+
+cdv_detect(){
+    check_command cdv || return 1
+    vcs_comm[detect_need_file]=format
+    detect_by_dir '.cdv'
+    return $?
+}
+
+cvs_detect(){
+    check_command svn || return 1
+    [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
+    return 1
+}
+
+darcs_detect(){
+    check_command darcs || return 1
+    # darcs diff seems a good choice since big diff is not the
+    # common state
+    darcs diff 2> /dev/null || return 1
+    vcs_comm[basedir]=$(darcs show repo |awk '{if($1 == "Root:") print $2}')
+    return 0
+}
+
+# Find git's branch
+git_getbranch (){
+    local gitbranch gitdir=$1 tmp actiondir
+    local gitsymref='git symbolic-ref HEAD'
+
+    # In certain circumstances, we have to take into account
+    # actions
+    actiondir=''
+    for tmp in "${gitdir}/rebase-apply" \
+               "${gitdir}/rebase"       \
+               "${gitdir}/../.dotest"; do
+        if [[ -d ${tmp} ]]; then
+            actiondir=${tmp}
+            break
         fi
-        VCS_size=$((${#LTYPE}+${#LBRANCH}+5))
+    done
+    if [[ -n ${actiondir} ]]; then
+        gitbranch="$(${gitsymref} 2> /dev/null)"
+        [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \
+            && gitbranch="$(< ${actiondir}/head-name)"
+
+    # MERGE_HEAD state
+    elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
+        gitbranch="$(eval $gitsymref 2> /dev/null)"
+        [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)"
+
+    # rebase
+    elif [[ -d "${gitdir}/rebase-merge" ]] ; then
+        gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
+
+    # dotest
+    elif [[ -d "${gitdir}/.dotest-merge" ]] ; then
+        gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
+
+    # Normal case
     else
-        VCS_info=""
-        VCS_size=0
+        gitbranch="$(eval $gitsymref 2> /dev/null)"
+
+        # shit happens
+        if [[ $? -ne 0 ]] ; then
+            gitbranch="refs/tags/$(git describe --exact-match HEAD 2>/dev/null)"
+
+            # big shit happens
+            if [[ $? -ne 0 ]] ; then
+                gitbranch=$(< $gitdir/HEAD)
+                gitbranch="${gitbranch:0:7}..."
+            fi
+        fi
+    fi
+
+    # keep only the last part of gitbranch
+    printf '%s' "${gitbranch#refs/[^/]*/}"
+    return 0
+}
+
+git_getaction(){
+    local gitaction='' gitdir=$1
+    local tmp
+
+    for tmp in "${gitdir}/rebase-apply" \
+               "${gitdir}/rebase"       \
+               "${gitdir}/../.dotest" ; do
+        if [[ -d ${tmp} ]] ; then
+            if   [[ -f "${tmp}/rebasing" ]] ; then
+                gitaction="rebase"
+            elif [[ -f "${tmp}/applying" ]] ; then
+                gitaction="am"
+            else
+                gitaction="am/rebase"
+            fi
+            printf '%s' ${gitaction}
+            return 0
+        fi
+    done
+
+    for tmp in "${gitdir}/rebase-merge/interactive" \
+               "${gitdir}/.dotest-merge/interactive" ; do
+        if [[ -f "${tmp}" ]] ; then
+            printf '%s' "rebase-i"
+            return 0
+        fi
+    done
+
+    for tmp in "${gitdir}/rebase-merge" \
+               "${gitdir}/.dotest-merge" ; do
+        if [[ -d "${tmp}" ]] ; then
+            printf '%s' "rebase-m"
+            return 0
+        fi
+    done
+
+    if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
+        printf '%s' "merge"
+        return 0
+    fi
+
+    if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
+        printf '%s' "bisect"
+        return 0
+    fi
+    return 1
+}
+
+git_get_data(){
+    local gitdir gitbase gitbranch gitaction
+
+    gitdir=${vcs_comm[gitdir]}
+    gitbranch="$(git_getbranch ${gitdir})"
+
+    if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
+        return 1
     fi
+
+    vcs_adjust
+    gitaction="$(git_getaction ${gitdir})"
+    gitprefix=$(git rev-parse --show-prefix)
+    gitbase=${PWD%/${gitprefix%/}}
+    vcs_formats "${gitaction}" "${gitbranch}" "${gitbase}" ''
+    return 0
+}
+
+hg_get_data(){
+    local hgbranch hgbase file
+
+    hgbase=${vcs_comm[basedir]}
+
+    # Check if hg branch is efficient
+    hgbranch=$(hg branch)
+
+    vcs_formats '' "${hgbranch}" "${hgbase}" ''
+    return 0
+}
+
+svn_get_data(){
+    local svnbase svnbranch
+    local -a svninfo
+
+    svnbase="."
+    while [[ -d "${svnbase}/../.svn" ]]; do
+        svnbase="${svnbase}/.."
+    done
+    svnbase="$(vcs_realpath ${svnbase})"
+    svnrev=$(svn info | awk '{if($1 == "Révision :") print $2}')
+    svnbranch=$(svn info | awk '{if($1 == "URL :") print $2}'|awk -F "/" '{ print $NF }')
+
+    vcs_formats '' "${svnbranch}" "${svnbase}" "${svnrev}"
+    return 0
 }
 
+bzr_get_data(){
+    local bzrbase bzrrev bzrbranch bzrinfo
+
+    bzrbase=$(bzr info|awk '{if ($1 == "branch" && $2 == "root:") print $3}')
+    bzrbase="$(vcs_realpath ${bzrbase})"
+    bzrinfo=$(bzr version-info|awk '{if ($1 == "branch-nick:"||$1 == "revno:") print $2}')
+    bzrrev=$(echo $bzrinfo|awk '{print $1}')
+    bzrbranch=$(echo $bzrinfo|awk '{print $2}')
+
+    vcs_formats '' "${bzrbranch}" "${bzrbase}" "${bzrrev}"
+    return 0
+}
+
+cdv_get_data(){
+    local cdvbase
+
+    cdvbase=${vcs_comm[basedir]}
+    vcs_formats '' "${cdvbase/*\/}" "${cdvbase}" ''
+    return 0
+}
+
+cvs_get_data(){
+    local cvsbranch cvsbase basename
+
+    cvsbase="."
+    while [[ -d "${cvsbase}/../CVS" ]]; do
+        cvsbase="${cvsbase}/.."
+    done
+    cvsbase="$(vcs_realpath ${cvsbase})"
+    cvsbranch=$(< ./CVS/Repository)
+    basename=${cvsbase/*\/}
+    cvsbranch=${cvsbranch#${basename}/}
+
+    [[ -z ${cvsbranch} ]] && cvsbranch=${basename}
+    vcs_formats '' "${cvsbranch}" "${cvsbase}" ''
+    return 0
+}
+
+darcs_get_data(){
+    local darcsbase
+
+    darcsbase=${vcs_comm[basedir]}
+    vcs_formats '' "${darcsbase/*\/}" "${darcsbase}" ''
+    return 0
+}
+
+vcs_info(){
+    local -i found
+    local -ax msgs
+    local -Ax vcs_comm commands
+    local -x vcs
+    local -a vcss
+    local -A disabled
+
+    vcs="init"
+    vcss=(git hg darcs svn bzr cvs cdv)
+    disabled[cdv]=1
+    disabled[cvs]=1
+    disabled[bzr]=1
+    for i in $(seq 0 $(( ${#vcss[*]} - 1 ))); do
+        if [[ disabled[${vcss[$i]}] -eq 1 ]]; then
+            continue
+        fi
+        commands[${vcss[$i]}]=$( (which ${vcss[$i]} 2>/dev/null >&2 && which ${vcss[i]})||echo true);
+    done;
+
+    found=0
+    for vcs in ${vcss[*]}; do
+        if [[ disabled[${vcs}] -eq 1 ]]; then
+            continue
+        fi
+        ${vcs}_detect && found=1 && break
+    done
+
+    (( found == 1 )) && ${vcs}_get_data
+
+    if [ ${color_prompt} = "yes" ]; then
+        VCS_info=${msgs[0]}
+    else
+        VCS_info=${msgs[1]}
+    fi
+    VCS_size=${#msgs[1]}
+}
 
 # Pour avoir le bon umask en fonction du dossier où on se trouve
 # L'umask définit avec quel droits un fichier est créé.
@@ -146,30 +476,6 @@ blanc_prompt="\[${blanc}\]"
 blanc_thin_prompt="\[${blanc_thin}\]"
 nocolor_prompt="\[${nocolor}\]"
 
-if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
-    # support de la couleur
-    color_prompt=yes
-    # Couleurs dans "user@host $"
-    username_color=${rouge_prompt}
-    host_color=${bleu_prompt}
-    symbols_color=${vert_prompt}
-    # Couleur de la ligne séparatrice de prompt
-    line_color=${cyan}
-    line_color_prompt=${cyan_prompt}
-    # Couleur du path actuel
-    pwd_color=${jaune_prompt}
-    # Couleur de la date (à chaque affichage du prompt)
-    date_color=${violet_prompt}
-    # Couleur de la date au premier affichage (à l'ouverture du terminal)
-    announce_date_color=${blanc}
-    # Couleur d'affichage de vcs_info
-    vcs_symbols_color=${violet_thin_prompt}
-    vcs_type_color=${jaune_thin_prompt}
-    vcs_branch_color=${vert_thin_prompt}
-else
-    # pas de support de la couleur
-    color_prompt=no
-fi
 
 # Est-ce qu'on veut que le prompt affiche les information sur l'éventuel dépôt
 # versionné dans lequel on se trouve
@@ -210,7 +516,7 @@ function prompt_command
     # À décommenter si on veut afficher des infos
     # quand on se trouve dans un dépôt versionné
     if [ "$display_vcs_info" = yes ]; then
-        get_vcs_info
+        vcs_info
     fi
     
     # Chemin courant, en faisant attention à la largeur de la fenêtre
@@ -242,16 +548,46 @@ function prompt_command
         # Attention "\\\$" devient \$, c'est-à-dire # pour root, $ pour les autres
         PROMPT="${username_color}\u${symbols_color}@${host_color}\h ${symbols_color}\\\$ ${nocolor_prompt}"
         # On fusionne tout ça
-        PS1=$TITLE${line_color_prompt}$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR$VCS_info${line_color_prompt}$POST_DIR$ERR'\n'$PROMPT
+        PS1=$TITLE${line_color_prompt}$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR${line_color_prompt}$POST_DIR$VCS_info$ERR'\n'$PROMPT
     else
         DIR="< "$DIR" >"
         ERR='[ $? ]'$MINUS_CHAR
         DATE="( \D{%H:%M:%S} )"
         PROMPT="\u@\h \\\$ "
-        PS1=$TITLE$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR$VCS_info$POST_DIR$ERR'\n'$PROMPT
+        PS1=$TITLE$MINUS_CHAR$DATE$MINUS_CHAR$DIR$MINUS_CHAR$POST_DIR$VCS_info$ERR'\n'$PROMPT
     fi
 }
 
+if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
+    # support de la couleur
+    color_prompt=yes
+    # Couleurs dans "user@host $"
+    username_color=${rouge_prompt}
+    host_color=${bleu_prompt}
+    symbols_color=${vert_prompt}
+    # Couleur de la ligne séparatrice de prompt
+    line_color=${cyan}
+    line_color_prompt=${cyan_prompt}
+    # Couleur du path actuel
+    pwd_color=${jaune_prompt}
+    # Couleur de la date (à chaque affichage du prompt)
+    date_color=${violet_prompt}
+    # Couleur de la date au premier affichage (à l'ouverture du terminal)
+    announce_date_color=${blanc}
+    # Couleur d'affichage de vcs_info
+    vcs_symbols_color=${violet_thin_prompt}
+    vcs_type_color=${jaune_thin_prompt}
+    vcs_branch_color=${vert_thin_prompt}
+    vcs_repo_color=${vert_thin_prompt}
+    vcs_action_color=${rouge_thin_prompt}
+    vcs_sep_color=${jaune_thin_prompt}
+    vcs_rev_color=${jaune_thin_prompt}
+    vcs_colon_color=${rouge_thin_prompt}
+else
+    # pas de support de la couleur
+    color_prompt=no
+fi
+
 # On change le titre de la fenêtre dynamiquement si on est sous X
 if [[ $TERM = "xterm" ]]; then
     TITLE='\[\e];\u@\h:\w\a\]'
@@ -259,7 +595,7 @@ else
     TITLE=''
 fi
 
-# On régénère le prompt après chaque commande
+# On régénére le prompt après chaque commande
 PROMPT_COMMAND=prompt_command
 
 # +-------------------+
@@ -294,19 +630,27 @@ function welcome_message ()
 ### ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ###
 ### Attention à ce que vous avez édité dans cette section ###
 
+
 # +---------------------------------------+
 # | Gestion de l'historique des commandes |
 # +---------------------------------------+
 
+# On spécifie explicitement le fichier d'historique.
+# En effet, si on jongle entre bash et zsh, per exemple,
+# comme ils n'utilisent pas le même format pour stocker le timestamp
+# des commandes, on se retrouve avec des comportements non souhaités
+# si on ne change pas le fichier d'historique entre les deux.
+export HISTFILE=~/.bash_history
+
 # On ne sauve pas les lignes dupliquées qui se suivent dans l'historique
 # ainsi que les commandes qui commencent par une espace
 export HISTCONTROL=ignoreboth
 
 # Nombre de lignes d'historique à garder
-export HISTSIZE=
+export HISTSIZE="10000"
 
 # la même chose dans le fichier d'historique
-export HISTFILESIZE=
+export HISTFILESIZE="100000"
 
 # Mémoriser le timestamp d'exécution de la commande
 export HISTTIMEFORMAT='%F %T - '
@@ -332,6 +676,17 @@ export EDITOR='/usr/bin/nano'
 # Ajouter ~/bin, /sbin et /usr/sbin à son PATH
 PATH=~/bin:$PATH:/sbin:/usr/sbin
 
+# Décommentez les lignes suivantes et peuplez-les correctement si
+# vous avez besoin de commiter en tant que root *et* que votre
+# /etc/sudoers contient bien la directive
+# Defaults env_keep += "<les variables en question>"
+export GIT_AUTHOR_NAME="$(git config user.name)"
+export GIT_AUTHOR_EMAIL="$(git config user.email)"
+
+# +----------+
+# | Sourcing |
+# +----------+
+
 # Chargement des alias
 if [ -f ~/.bash_aliases ]; then
     . ~/.bash_aliases
@@ -344,6 +699,11 @@ if [ -f ~/.bash_aliases_local ]; then
     . ~/.bash_aliases_local
 fi
 
+
+# +-----+
+# | End |
+# +-----+
+
 # On n'exécute le welcome_message que à ce moment, parce que la customisation
-# local a pu changer des couleurs
+# locale a pu changer des couleurs
 welcome_message