X-Git-Url: https://git.alrj.org/?p=zsh.d.git;a=blobdiff_plain;f=S60_git;h=1061cf575a0a04d47412070ac157bdf7cc2b71fa;hp=9eb816b48017acdf0dff2d600b32d10540cd1e3e;hb=HEAD;hpb=fd2bbfe8cef59fc62f63238be58fab505cc69818 diff --git a/S60_git b/S60_git index 9eb816b..1061cf5 100644 --- a/S60_git +++ b/S60_git @@ -1,55 +1,136 @@ #! /usr/bin/zsh -export __ZSH_GIT_BASEDIR="" -export __ZSH_GIT_BRANCH="" -export __ZSH_GIT_SUBDIR="" -export __ZSH_GIT_STATE="" -export __ZSH_GIT_VARS_INVALID=1 +# Those can be used, for instance to construct the prompt: +__ZSH_GIT_BASEDIR="" +__ZSH_GIT_SUBDIR="" +__ZSH_GIT_BRANCH="" +__ZSH_GIT_ACTION="" +__ZSH_GIT_STATUS="" + +__ZSH_GIT_VARS_INVALID=1 +__ZSH_GIT_STATUS_INVALID=1 + + +git_chpwd() { + # On cd, invalidate git status in prompt + __ZSH_GIT_VARS_INVALID=1 + __ZSH_GIT_BASEDIR="" +} + + +git_preexec() { + # On git command, invalidate git status in prompt + case "$1" in + git*) + __ZSH_GIT_VARS_INVALID=1 + ;; + esac + + # *any* command could invalidate the repository status (new file, ...) + __ZSH_GIT_STATUS_INVALID=1 +} + +git_get_status() { + # Return only git status + local gitstat gitstatus + + gitstat=$(LANG=C git status 2> /dev/null | grep '\(Untracked\|Changes\|Changed but not updated:\)') + # 'fix for mcedit parser + gitstatus="" + + if [[ $(echo ${gitstat} | grep -c "^Changes to be committed:$") > 0 ]]; then + gitstatus='✚' + fi + + if [[ $(echo ${gitstat} | grep -c "^Changed but not updated:$") > 0 || \ + $(echo ${gitstat} | grep -c "^Changes not staged for commit:$") > 0 ]]; then + gitstatus="${gitstatus}✹" + fi + + if [[ $(echo ${gitstat} | grep -c "^Untracked files:$") > 0 ]]; then + gitstatus="${gitstatus}★" + fi + + if [[ -z $gitstatus ]]; then + gitstatus="%{${fg_bold[green]}%}✔%{$reset_color%}" + else + gitstatus="%{${fg_bold[yellow]}%}$gitstatus%{$reset_color%}" + fi + + echo $gitstatus +} + git_parse() { + local git_dir ref base_dir sub_dir action branch gitstat gitstatus + + # If nothing has been invalidated + if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "0" ]]; then + return + fi + + # If only status has been invalidated + if [[ "${__ZSH_GIT_VARS_INVALID}" == "0" && "${__ZSH_GIT_STATUS_INVALID}" == "1" ]]; then + __ZSH_GIT_STATUS=$(git_get_status) + __ZSH_GIT_STATUS_INVALID=0 + return + fi - psvar=() - local git_dir ref base_dir sub_dir action branch + + # Git prompt variables are invalid. Update them. git_dir=$(git rev-parse --git-dir 2> /dev/null) || return - base_dir=${$(readlink -f "$git_dir/..")/$HOME/'~'} + if [[ "$(git rev-parse --is-bare-repository)" == "true" ]]; then + base_dir=${$(readlink -f "$git_dir")/$HOME/'~'} + sub_dir=${$(pwd)#$(readlink -f "$git_dir")} + else + base_dir=${$(readlink -f "$git_dir/..")/$HOME/'~'} + sub_dir=${$(pwd)#$(readlink -f "$git_dir/..")} + fi - sub_dir=$(git rev-parse --show-prefix) - sub_dir=${sub_dir%/} + sub_dir=${sub_dir#/} ref=$(git symbolic-ref HEAD 2> /dev/null) || return - psvar[3]="" + action="" if [ -d "$git_dir/../.dotest" ]; then if [ -f "$git_dir/../.dotest/rebasing" ]; then - psvar[3]="-rebase" + action="-rebase" elif [ -f "$git_dir/../.dotest/applying" ]; then - psvar[3]="-am" + action="-am" else - psvar[3]="-am-rebase" + action="-am-rebase" fi branch="$ref" elif [ -f "$git_dir/.dotest-merge/interactive" ]; then - psvar[3]="-rebase-i" + action="-rebase-i" branch="$(cat "$git_dir/.dotest-merge/head-name")" elif [ -d "$git_dir/.dotest-merge" ]; then - psvar[3]="-rebase-m" + action="-rebase-m" branch="$(cat "$git_dir/.dotest-merge/head-name")" elif [ -f "$git_dir/MERGE_HEAD" ]; then - psvar[3]="-merge" + action="-merge" branch="$ref" else - test -f "$git_dir/BISECT_LOG" && psvar[3]="bisect" + test -f "$git_dir/BISECT_LOG" && action="-bisect" branch="$(git symbolic-ref HEAD 2>/dev/null)" || \ branch="$(git describe --exact-match HEAD 2>/dev/null)" || \ branch="$(cut -c1-7 "$git_dir/HEAD")..." fi - # Got here, we're in git - psvar[4]=${branch#refs/heads/} - psvar[5]=${base_dir} - psvar[6]=${sub_dir} + + __ZSH_GIT_BASEDIR="${base_dir}" + __ZSH_GIT_SUBDIR="${sub_dir}" + __ZSH_GIT_BRANCH="${branch#refs/heads/}" + __ZSH_GIT_ACTION="${action}" + __ZSH_GIT_STATUS=`git_get_status` + + __ZSH_GIT_VARS_INVALID=0 + __ZSH_GIT_STATUS_INVALID=0 } + +chpwd_functions+='git_chpwd' +preexec_functions+='git_preexec' precmd_functions+='git_parse'