]> git.madduck.net Git - etc/zsh.git/blob - .zsh/themes/prompt_madduck_setup

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:

move Git prompt handling to theme
[etc/zsh.git] / .zsh / themes / prompt_madduck_setup
1 #
2 # My zsh prompt theme
3 #
4 # Copyright © 1994–2017 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 # vcs stuff shamelessly based on http://glandium.org/blog/?p=170
10 #
11
12 zstyle -m :madduck:prompt:default path-maxlen '*' \
13   || zstyle :madduck:prompt:default path-maxlen 25
14 zstyle -m :madduck:prompt:default path-minlen '*' \
15   || zstyle :madduck:prompt:default path-minlen 10
16 for i in {1..9}; do
17   zstyle -m :madduck:prompt:default psvar${i}-style-pre '*' \
18     || zstyle :madduck:prompt:default psvar${i}-style-pre ''
19   zstyle -m :madduck:prompt:default psvar${i}-style-post '*' \
20     || zstyle :madduck:prompt:default psvar${i}-style-post ''
21 done
22
23 __on_networkfs()
24 {
25   emulate -L zsh
26   case $(df -T . | sed -rne '$s,^[^[:space:]]+[[:space:]]+([^[:space:]]+).*,\1,p') in
27     (cifs|nfs) return 0;;
28   esac
29   return 1
30 }
31
32 __get_prompt_path_len() {
33   emulate -L zsh
34   local result
35   zstyle -s ":madduck:prompt:$PWD" path-${1}len result
36   [ -z "$result" ] && zstyle -s ':madduck:prompt:default' path-${1}len result
37   echo "$result"
38 }
39
40 __get_prompt_psvar_style() {
41   emulate -L zsh
42   local result
43   zstyle -s ":madduck:prompt:$PWD" psvar${1}-style-${2} result
44   [ -z "$result" ] && zstyle -s ':madduck:prompt:default' psvar${1}-style-${2} result
45   echo "$result"
46 }
47
48 # define defaults for the $psvar array, which will actually be emptied later,
49 # but $PS1 then contains these as default values for each psvar element, i.e.
50 # we can override psvar[1] later, but we don't have to
51 psvar[1]='%(2L.+.)'
52 psvar[2]="$DEBIAN_CHROOT"
53   zstyle :madduck:prompt:default psvar2-style-pre '%S'
54   zstyle :madduck:prompt:default psvar2-style-post '%s@'
55 psvar[3]='%m'
56   zstyle :madduck:prompt:default psvar3-style-pre '%B'
57   zstyle :madduck:prompt:default psvar3-style-post '%b:'
58
59 function __set_prompt_pwd() {
60   psvar[4]="%$(__get_prompt_path_len max)<…<%~%<<"
61 }
62 # make this an early hook so that it's always set unless overridden
63 # by a later handler
64 add-zsh-hook chpwd __set_prompt_pwd && __set_prompt_pwd
65
66 psvar[9]='%# '
67
68 local function make_ps1() {
69   local pre post psv
70   for i in {1..9}; do
71     pre="\$(__get_prompt_psvar_style $i pre)"
72     post="\$(__get_prompt_psvar_style $i post)"
73     psv="${psvar[$i]}"
74     echo -n "%(${i}V;${pre}\${psvar[$i]}${post};${psv:+${pre}${psv}${post}})"
75   done
76 }
77 PS1=$(make_ps1)
78 unfunction make_ps1
79 psvar=()
80 PS2="%{$fg[red]%}%_>%{$reset_color%}"
81
82 local function make_rps1() {
83   # First, a comment character and parens
84   echo -n '#('
85
86   # Next, if the returncode was non-zero, make it stand-out
87   # and include a trailing space
88   echo -n "%(0?..%{$fg[red]%}%S%?%s%{$reset_color%} )"
89
90   # If there are background jobs, print their number, followed by
91   # '@':
92   echo -n '%(1j.%j@.)'
93
94   # and then the terminal line we're using
95   echo -n '%l'
96
97   # this concludes the first part, but there's more
98   echo -n ') '
99
100   # the timestamp will finish it off:
101   echo -n '%D{%d %H:%M:%S.%.}'
102   echo
103 }
104 typeset -g RPS1="$(make_rps1)"
105 unfunction make_rps1
106
107
108
109
110 __vcs_get_prompt_path_components()
111 {
112   emulate -L zsh
113   # return formatted path components (prefix branch postfix) given
114   # the repository root and the branch.
115
116   local MAXLEN MINLEN
117   MAXLEN=$(__get_prompt_path_len max)
118   MINLEN=$(__get_prompt_path_len min)
119
120   # shortcut: if there are no arguments, return a default prompt
121   if [ -z "${1:-}" ]; then
122     pwdnamed="${(%):-%${MAXLEN}<…<%~%<<}"
123     echo "$pwdnamed"
124     return
125   fi
126
127   local reporoot branch
128   reporoot="${1%%/}"
129   branch="$2"
130
131   # replace named directories in the PWD, we need thi for the proper component
132   # count later
133   local pwdnamed
134   pwdnamed="${(%):-%~}"
135
136   # store paths in arrays for component count calculation
137   typeset -la apwd apwdnamed areporoot
138   apwd=(${(s:/:)PWD})
139   apwdnamed=(${(s:/:)pwdnamed})
140   areporoot=(${(s:/:)reporoot})
141
142   # get the number of leading and trailing path components. Since we're using
143   # %~ later and then /home/madduck suddenly becomes ~, which is 1, not
144   # 2 components, we calculate the leading component count by using the named
145   # path and the number of post components
146   local precomps postcomps
147   postcomps=$(($#apwd - $#areporoot))
148   precomps=$(($#apwdnamed - $postcomps))
149
150   local postfix
151   (( $postcomps > 0 )) && postfix="${(%):-%${postcomps}~}"
152
153   # we don't want the prompt to get too long, so keep the total prompt length
154   # under $MAXLEN, but ensure that the prefix is not shorter
155   # than $MINLEN, no matter what
156   local prelen minlen prefix
157   prelen=$((${MAXLEN} - $#branch - $#postfix))
158   minlen=${MINLEN}
159   (( $prelen < $minlen )) && prelen=$minlen
160   prefix="${(%):-%${prelen}<…<%-${precomps}~%<<}"
161
162   echo "'$prefix'" "'$branch'" "'$postfix'"
163 }
164
165 __vcs_set_prompt_variables()
166 {
167   emulate -L zsh
168   # set psvar[1..3] depending on repo type, or just psvar[1] if no repo found
169   local reporoot branch repotype
170   repotype="${1:-$(__vcs_get_repo_type)}"
171
172   case "$repotype" in
173     git)
174       reporoot="$(__git_get_reporoot)" ||
175         { zerror "could not determine git repository root"; return 1 }
176       branch="$(__git_get_branch)" ||
177         { zerror "could not determine git branch"; return 1 }
178       if [ -n "$VCSH_REPO_NAME" ]; then
179         # if vcsh is used to get a subshell, then the repo root is the home
180         # directory, but we want to indicate the vcsh context too:
181         eval set -- $(__vcs_get_prompt_path_components "$HOME" "$branch")
182         set -- "vcsh:$VCSH_REPO_NAME" "$2" "$1${3:+/$3}"
183       else
184         eval set -- $(__vcs_get_prompt_path_components "$reporoot" "$branch")
185         if [ -d "$GIT_DIR" ]; then
186           set -- "${(D)GIT_DIR}" "$2" "${${1#$_D}%/}"
187         fi
188       fi
189       ;;
190     hg)
191       reporoot="$(__hg_get_reporoot)" ||
192         { zerror "could not determine hg repository root"; return 1 }
193       branch="$(__hg_get_branch)" ||
194         { zerror "could not determine hg branch"; return 1 }
195       eval set -- $(__vcs_get_prompt_path_components "$reporoot" "$branch")
196       ;;
197     bzr)
198       reporoot="$(__bzr_get_reporoot)" ||
199         { zerror "could not determine bzr repository root"; return 1 }
200       branch="$(__bzr_get_branch)" ||
201         { zerror "could not determine bzr branch"; return 1 }
202       eval set -- $(__vcs_get_prompt_path_components "$reporoot" "$branch")
203       ;;
204     *)
205       case "$repotype" in
206         NONE|netfs) :;;
207         *) warn "$repotype repositories not (yet) supported in the prompt";;
208       esac
209       local MAXLEN MINLEN
210       MAXLEN=$(__get_prompt_path_len max)
211       local p="%${MAXLEN}<…<%~%<<"
212       #TODO find a better way so we don't have to nuke $psvar, but since the
213       #     %(nv.true.false) check for prompts checks element count, not
214       #     content, that's all we get for now
215       psvar=("${(%)p}")
216       return
217   esac
218
219   psvar[1,3]=($1 $2 $3)
220 }
221
222 if false && ! is_root; then
223   # too dangerous to be run as root
224   autoload -U add-zsh-hook
225
226   _update_vcs_prompt_vars_if_vcs_ran() {
227     local vcs="$(__vcs_get_repo_type)"
228     case "$vcs/$(history $(($HISTCMD - 1)))" in
229       # $vcs appeared in last command, so be sure to update
230       NONE/*) :;;
231       netfs/*) :;;
232       */*${vcs}*) __vcs_set_prompt_variables "$vcs"
233     esac
234   }
235   add-zsh-hook precmd _update_vcs_prompt_vars_if_vcs_ran
236
237   _update_vcs_prompt_vars() {
238     __vcs_set_prompt_variables
239   }
240   add-zsh-hook chpwd _update_vcs_prompt_vars
241
242   # call it once
243   _update_vcs_prompt_vars
244 fi
245
246 # vim:ft=zsh