]> git.madduck.net Git - etc/git.git/blobdiff - .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:

Update Git shell integration
[etc/git.git] / .zsh / zshrc / parts.d / 50-git
diff --git a/.zsh/zshrc/parts.d/50-git b/.zsh/zshrc/parts.d/50-git
new file mode 100644 (file)
index 0000000..da11bf8
--- /dev/null
@@ -0,0 +1,120 @@
+#
+# Git shell integration
+#
+# Copyright © 2018 martin f. krafft <madduck@madduck.net>
+# Released under the terms of the Artistic Licence 2.0
+#
+# Source repository: http://git.madduck.net/v/etc/zsh.git
+#
+
+__is_git_repo()
+{
+  emulate -L zsh
+  git rev-parse --is-inside-work-tree >/dev/null 2>&1
+}
+
+__git_get_reporoot()
+{
+  emulate -L zsh
+  # return the full path to the root of the current git repository
+  [ -d "$GIT_DIR" ] && echo "$GIT_DIR" && return 0
+  local dir; dir="$PWD/$(git rev-parse --show-cdup)"
+  # do not use --show-toplevel because it resolves symlinks
+  echo $dir:a
+}
+
+__git_get_branch()
+{
+  emulate -L zsh
+  # use oh-my-zsh prompt info function if it exists
+  $(command -v git_prompt_info) && return
+
+  # return the name of the git branch we're on
+  local ref gitdir
+  gitdir="$(git rev-parse --git-dir)"
+  ref=$(git --git-dir="$gitdir" symbolic-ref -q HEAD 2>/dev/null \
+     || git --git-dir="$gitdir" name-rev --name-only HEAD 2>/dev/null) || return 1
+  echo "${ref#refs/heads/}"
+}
+
+__git_set_prompt_variable() {
+  __is_git_repo || return
+
+  local reporoot="$(__git_get_reporoot)" ||
+    { zerror "could not determine git repository root"; return 1 }
+  local branch="$(__git_get_branch)" ||
+    { zerror "could not determine git branch"; return 1 }
+  if [ -n "$VCSH_REPO_NAME" ]; then
+    # if vcsh is used to get a subshell, then the repo root is the home
+    # directory, but we want to indicate the vcsh context too:
+    eval set -- $(__vcs_get_prompt_path_components "$HOME" "$branch")
+    set -- "vcsh:$VCSH_REPO_NAME" "$2" "$1${3:+/$3}"
+  else
+    eval set -- $(__vcs_get_prompt_path_components "$reporoot" "$branch")
+    if [ -d "$GIT_DIR" ]; then
+      set -- "${(D)GIT_DIR}" "$2" "${${1#$_D}%/}"
+    fi
+  fi
+  psvar[4]="$1${2:+|%B$2%b|}${3:-}"
+}
+add-zsh-hook chpwd __git_set_prompt_variable
+__git_set_prompt_variable
+
+__git_print_preprompt()
+{
+  [[ $? -eq 0 ]] || return
+  emulate -L zsh
+  __is_git_repo || return
+  [ "$(git config --get core.bare)" = false ] || return
+  __on_networkfs && return
+
+  local COLUMNS=${COLUMNS:-80}
+  local LINES=${LINES:-25}
+
+  function output() {
+    emulate -L zsh
+    local title="$@"
+    local output; output=(${(f)"$(cat)"})
+
+    [[ ${#output} -ge 1 ]] || return
+
+    local statl="$(echo ${output[-1]} | sed -re 's@^\s*([0-9]+)[^,]+(, ([0-9]+) [^(]+\(([-+])\))(, ([0-9]+) [^(]+\(([-+])\))?@\1/\4\3/\7\6@')"
+
+    if [[ ${output[-2]## } = '...' ]]; then
+      print "${title} (${statl%/}, abbrev.):"
+      print "${(F)output[1,-3]}"
+      print " …"
+    else
+      print "${title} (${statl%/}):"
+      print "${(F)output[1,-2]}"
+    fi
+  }
+
+  function gitdiffstat() {
+    emulate -L zsh
+    local common_options="--stat=$((COLUMNS/2-1)),$((COLUMNS/4-2)),$(($LINES/3)) --relative"
+    eval git diff $common_options "$@" 2>/dev/null
+  }
+
+  local cached; cached=(${(f)"$(gitdiffstat --cached | output cached)"})
+  local changed; changed=(${(f)"$(gitdiffstat | output changed)"})
+
+  local max=${#changed}
+  [[ $max -lt ${#cached} ]] && max=${#cached}
+
+  ((max == 0)) && return
+
+  local width=$(((COLUMNS-3)/2))
+
+  if (( ${#cached} > 0 && ${#changed} > 0 )); then
+    local i
+    for (( i=1 ; i <= max ; i++ )) do
+      printf "%-${width}s │ %-${width}s\n" "${cached[$i]}" "${changed[$i]}"
+    done
+  else
+    print ${(F)cached}${(F)changed}
+  fi
+}
+add-zsh-hook precmd __git_print_preprompt
+
+# vim:ft=zsh