]> git.madduck.net Git - etc/git.git/blob - .zsh/zshrc/parts.d/50-git

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

configure sensible editor
[etc/git.git] / .zsh / zshrc / parts.d / 50-git
1 #
2 # Git shell integration
3 #
4 # Copyright © 2018 martin f. krafft <madduck@madduck.net>
5 # Released under the terms of the Artistic Licence 2.0
6 #
7 # Source repository: http://git.madduck.net/v/etc/zsh.git
8 #
9
10 __is_git_repo()
11 {
12   emulate -L zsh
13   git rev-parse --is-inside-work-tree >/dev/null 2>&1
14 }
15
16 __git_get_reporoot()
17 {
18   emulate -L zsh
19   # return the full path to the root of the current git repository
20   [ -d "$GIT_DIR" ] && echo "$GIT_DIR" && return 0
21   local dir; dir="$PWD/$(git rev-parse --show-cdup)"
22   # do not use --show-toplevel because it resolves symlinks
23   echo $dir:a
24 }
25
26 __git_get_branch()
27 {
28   emulate -L zsh
29   # use oh-my-zsh prompt info function if it exists
30   $(command -v git_prompt_info) && return
31
32   # return the name of the git branch we're on
33   local ref gitdir
34   gitdir="$(git rev-parse --git-dir)"
35   ref=$(git --git-dir="$gitdir" symbolic-ref -q HEAD 2>/dev/null \
36      || git --git-dir="$gitdir" name-rev --name-only HEAD 2>/dev/null) || return 1
37   echo "${ref#refs/heads/}"
38 }
39
40 __git_set_prompt_variable() {
41   __is_git_repo || return
42
43   local reporoot="$(__git_get_reporoot)" ||
44     { zerror "could not determine git repository root"; return 1 }
45   local branch="$(__git_get_branch)" ||
46     { zerror "could not determine git branch"; return 1 }
47   if [ -n "$VCSH_REPO_NAME" ]; then
48     # if vcsh is used to get a subshell, then the repo root is the home
49     # directory, but we want to indicate the vcsh context too:
50     eval set -- $(__vcs_get_prompt_path_components "$HOME" "$branch")
51     set -- "vcsh:$VCSH_REPO_NAME" "$2" "$1${3:+/$3}"
52   else
53     eval set -- $(__vcs_get_prompt_path_components "$reporoot" "$branch")
54     if [ -d "$GIT_DIR" ]; then
55       set -- "${(D)GIT_DIR}" "$2" "${${1#$_D}%/}"
56     fi
57   fi
58   psvar[4]="$1${2:+|%B$2%b|}${3:-}"
59 }
60 add-zsh-hook chpwd __git_set_prompt_variable
61 __git_set_prompt_variable
62
63 __update_git_prompt_vars_if_git_ran() {
64   case "$(history $(($HISTCMD - 1)))" in
65     *git*) __git_set_prompt_variable
66   esac
67 }
68 add-zsh-hook precmd __update_git_prompt_vars_if_git_ran
69
70 __git_print_preprompt()
71 {
72   [[ $? -eq 0 ]] || return
73   emulate -L zsh
74   __is_git_repo || return
75   [ "$(git config --get core.bare)" = false ] || return
76   __on_networkfs && return
77
78   local COLUMNS=${COLUMNS:-80}
79   local LINES=${LINES:-25}
80
81   function output() {
82     emulate -L zsh
83     local title="$@"
84     local output; output=(${(f)"$(cat)"})
85
86     [[ ${#output} -ge 1 ]] || return
87
88     local statl="$(echo ${output[-1]} | sed -re 's@^\s*([0-9]+)[^,]+(, ([0-9]+) [^(]+\(([-+])\))(, ([0-9]+) [^(]+\(([-+])\))?@\1/\4\3/\7\6@')"
89
90     if [[ ${output[-2]## } = '...' ]]; then
91       print "${title} (${statl%/}, abbrev.):"
92       print "${(F)output[1,-3]}"
93       print " …"
94     else
95       print "${title} (${statl%/}):"
96       print "${(F)output[1,-2]}"
97     fi
98   }
99
100   function gitdiffstat() {
101     emulate -L zsh
102     local common_options="--stat=$((COLUMNS/2-1)),$((COLUMNS/4-2)),$(($LINES/3)) --relative"
103     eval git diff $common_options "$@" 2>/dev/null
104   }
105
106   local cached; cached=(${(f)"$(gitdiffstat --cached | output cached)"})
107   local changed; changed=(${(f)"$(gitdiffstat | output changed)"})
108
109   local max=${#changed}
110   [[ $max -lt ${#cached} ]] && max=${#cached}
111
112   ((max == 0)) && return
113
114   local width=$(((COLUMNS-3)/2))
115
116   if (( ${#cached} > 0 && ${#changed} > 0 )); then
117     local i
118     for (( i=1 ; i <= max ; i++ )) do
119       printf "%-${width}s │ %-${width}s\n" "${cached[$i]}" "${changed[$i]}"
120     done
121   else
122     print ${(F)cached}${(F)changed}
123   fi
124 }
125 add-zsh-hook precmd __git_print_preprompt
126
127 # vim:ft=zsh