lotsa changes (oh yay, we love good commit msgs)
[zsh.git] / .zsh / functions / prompt_ganneff_setup
1 # -*- mode:sh -*-
2
3 # This prompt is based on work of other people.
4 #
5 # The prompt itself is based on various others:
6 # - The "design" is taken from Phil!'s ZSH prompt, as found on
7 # http://aperiodic.net/phil/prompt/
8 #
9 # - The technic using zstyle is inspired by the prompt as used by
10 # the grml-live system <http://grml.org>, see
11 # http://git.grml.org/?p=grml-etc-core.git;a=summary for details
12 # on theirs.
13 # A good number of their support functions are also taken, though
14 # they got renamed from grml_* to ganneff_* to have a single namespace
15 # here.
16 #
17 # - The winch function as seen in the prompt theme "bart", delivered
18 # with zsh
19
20 prompt_ganneff_help () {
21 cat <<__EOF0__
22 prompt ganneff
23
24 This is the prompt as used by (who would have guessed) Ganneff. By
25 default it is a two-line prompt. You can find its latest version at
26 http://git.ganneff.de/cgi-bin/gitweb.cgi?p=zsh.git;a=summary
27
28 The prompt itself is based on various others:
29 - The "design" is taken from Phil!'s ZSH prompt, as found on
30 http://aperiodic.net/phil/prompt/
31
32 - The technic using zstyle is inspired by the prompt as used by
33 the grml-live system <http://grml.org>, see
34 http://git.grml.org/?p=grml-etc-core.git;a=summary for details
35 on theirs.
36
37 The prompt integrates with zsh's prompt themes system and uses the
38 zstyle system for its configuration. It is configurable as much as
39 seems to make sense. In particular, these aspects are customisable:
40
41 - The items used in the prompt and their order (e.g. you can
42 remove \`user' from the list of activated items, which will
43 cause the user name to be omitted from the prompt string).
44
45 - The attributes used with the items are customisable via strings
46 used before and after the actual item.
47
48 - An itemset for "small terminals" can be provided. That is, if the
49 length of the upper line exceeds the terminal width, various
50 items get removed from the prompt to (hopefully) make it still
51 look good. Obviously this only works down to a limit.
52
53 The available items are: at, battery, change-root, date, history,
54 host, jobs, newline, path, percent, rc, rc-always, shell-level,
55 time, user, vcs, ulcorner, llcorner, urcorner, lrcorner, line, pts,
56 openbracket, closebracket, pipe, space, flexline
57
58 Most of those should be self-explanatory, some may need more:
59 line - Draws a single line character
60 XYcorner - Draws a corner. The chars to replace XY are
61 X=u for upper, l for lower
62 Y=l for left, r for right
63 flexline - Same as line, but flexible length to fill remaining space
64 Only works in a two-line prompt in the upper line, that
65 is, a newline MUST appear in the setup!
66
67 The actual configuration is done via zsh's \`zstyle' mechanism. The
68 context, that is used while looking up styles is:
69
70 ':prompt:ganneff:<left-or-right>:<full-or-small>:<subcontext>'
71
72 Here <left-or-right> is either \`left' or \`right', signifying whether the
73 style should affect the left or the right prompt. <full-or-small> is
74 either \`full' or \`small' and only valid in the item selection,
75 signifying wether the item list should affect the full length or
76 the "small terminal" prompt. As "small terminal" prompt does not
77 display the right side prompt, <full-or-small> has no effect on the
78 right side prompt.
79 <subcontext> is either \`setup' or 'items:<item>', where \`<item>'
80 is one of the available items.
81
82 The styles available under ':prompt:ganneff:':
83
84 - vcs_info (boolean): If \`true' (the default), use \`vcs_info'.
85
86 - set_vcs_info_defaults (boolean): If \`true' (the default),
87 various vcs_info settings will be done. If unset or \`false'
88 it is assumed that the user has already done this.
89
90 The default setup is:
91 zstyle ':vcs_info:*' max-exports 1
92 zstyle ':vcs_info:*' use-prompt-escapes
93 zstyle ':vcs_info:*' use_simple
94 zstyle ':vcs_info:*' stagedstr "!"
95 zstyle ':vcs_info:*' unstagedstr "?"
96 zstyle ':vcs_info:*' check-for-changes true
97 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat \
98 "\${PR_YELLOW}%b%{\${PR_RED}%}:\${PR_YELLOW}%r\${PR_NO_COLOR}"
99 zstyle ':vcs_info:*' formats \
100 "(\${PR_YELLOW}%s\${PR_NO_COLOR})-[\${PR_GREEN}%b\${PR_NO_COLOR}]%m%u%c "
101 zstyle ':vcs_info:*' actionformats \
102 "(\${PR_YELLOW}%s\${PR_NO_COLOR})-[\${PR_GREEN}%b\${PR_NO_COLOR}-\${PR_RED}(%a)\${PR_NO_COLOR}]%m%u%c "
103
104 - colors (boolean): If \`true' (the default), use colors. b/w
105 otherwise.
106
107 - nicelines (boolean): If \`true' (the default), use special
108 magic to draw nice lines and corners. Might not work on every
109 terminal. If false, draws using plain ascii characters.
110
111 - battery (string): If \`none' then no battery function at all.
112 If either \`ibam' or \`acpi' then use those tools to gather
113 the current battery level.
114
115 - use-rprompt (boolean): If \`true' (the default), print the
116 right side prompt.
117
118 - items (list): The list of items used in the prompt. If \`vcs' is
119 present in the list, the theme's code invokes \`vcs_info'
120 accordingly. Default (left): rc change-root user at host path vcs
121 percent; Default (right): sad-smiley
122
123 Available styles in 'items:<item>' are: pre, post. These are strings that
124 are inserted before (pre) and after (post) the item in question. Thus, the
125 following would cause the user name to be printed in red instead of the
126 default blue:
127
128 zstyle ':prompt:ganneff:*:items:user' pre '\${PR_RED}'
129
130 Note, that the \`post' style may remain at its default value, because its
131 default value is '\${PR_NO_COLOR}', which turns the foreground text
132 attribute off (which is exactly, what is still required with the new
133 \`pre' value).
134
135 Possible values for the colors: \${PR_XXX} and \${PR_BOLD_XXX} with
136 XXX replaced with one of: RED GREEN YELLOW BLUE MAGENTA CYAN WHITE
137 \${PR_NO_COLOR} resets color.
138 Using the \${PR_XXX} values instead of zsh's internal \%F{xxx} allows
139 the style to turn off colors to work.
140 __EOF0__
141 }
142
143 prompt_ganneff_setup () {
144 emulate -L zsh
145 setopt nolocaltraps
146
147 # See if we can and should use extended characters to look nicer.
148 if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]] \
149 && [[ "$TERM" != "linux" ]]; then
150 typeset -A altchar
151 set -A altchar ${(s..)terminfo[acsc]}
152 # Some stuff to help us draw nice lines
153 PR_SET_CHARSET="%{$terminfo[enacs]%}"
154 PR_SHIFT_IN="%{$terminfo[smacs]%}"
155 PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
156 PR_HBAR=${altchar[q]:--}
157 PR_ULCORNER=${altchar[l]:--}
158 PR_LLCORNER=${altchar[m]:--}
159 PR_LRCORNER=${altchar[j]:--}
160 PR_URCORNER=${altchar[k]:--}
161 else
162 PR_SET_CHARSET=""
163 PR_SHIFT_IN=""
164 PR_SHIFT_OUT=""
165 PR_HBAR="-"
166 PR_ULCORNER=""
167 PR_LLCORNER=""
168 PR_LRCORNER=""
169 PR_URCORNER=""
170 fi
171
172 if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
173 if [[ -n "${BLUE}" ]] && [[ -n "${YELLOW}" ]]; then
174 # Two defined, so we assume someone already defined themself
175 # the colors. We just use them and not setup our own.
176 for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
177 eval PR_$color="%{${(P)color}%}"
178 eval PR_BOLD_$color="%{$terminfo[bold]${(LP)color}%}"
179 done
180 PR_NO_COLOR="%{${reset_color}%}"
181 else
182 # Seems like colors are not defined, so set them up
183 docolors
184 fi
185 else
186 PR_BLUE=''
187 PR_RED=''
188 PR_GREEN=''
189 PR_CYAN=''
190 PR_WHITE=''
191 PR_MAGENTA=''
192 PR_YELLOW=''
193 PR_NO_COLOR="%{${reset_color}%}"
194 fi
195
196 # Easy things first.
197 # The secondary prompt, printed when the shell needs more
198 # information to complete a command. %_ displays any shell constructs
199 # or quotation marks which are currently being processed.
200 if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
201 PS2='${PR_CYAN}${PR_SHIFT_IN}${PR_HBAR}${PR_BLUE}${PR_HBAR}${PR_SHIFT_OUT}\
202 (${PR_GREEN}%_${PR_BLUE})\
203 ${PR_SHIFT_IN}${PR_HBAR}${PR_CYAN}${PR_HBAR}${PR_SHIFT_OUT}${PR_NO_COLOR} '
204 else
205 PS2='-(%_)- '
206 fi
207 # selection prompt used within a select loop.
208 PS3='?# '
209 # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
210 PS4='+%N:%i:%_> '
211
212 if zstyle -t ':prompt:ganneff' vcs_info && \
213 is439 && autoload -Uz vcs_info && vcs_info; then
214 if zstyle -t ':prompt:ganneff' set_vcs_info_defaults; then
215 # gather version control information for inclusion in a prompt
216 # we will only be using one variable, so let the code know now.
217 zstyle ':vcs_info:*' max-exports 1
218 zstyle ':vcs_info:*' use-prompt-escapes
219 zstyle ':vcs_info:*' use_simple
220 zstyle ':vcs_info:*' stagedstr "!"
221 zstyle ':vcs_info:*' unstagedstr "?"
222 zstyle ':vcs_info:*' check-for-changes true
223
224 # change vcs_info formats for the prompt
225 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "${PR_YELLOW}%b%{${PR_RED}%}:${PR_YELLOW}%r${PR_NO_COLOR}"
226 zstyle ':vcs_info:*' formats "(${PR_YELLOW}%s${PR_NO_COLOR})-[${PR_GREEN}%b${PR_NO_COLOR}]%m%u%c "
227 zstyle ':vcs_info:*' actionformats "(${PR_YELLOW}%s${PR_NO_COLOR})-[${PR_GREEN}%b${PR_NO_COLOR}-${PR_RED}(%a)${PR_NO_COLOR}]%m%u%c "
228 fi
229 fi
230
231 # These maps define default tokens and pre-/post-decoration for items to be
232 # used within the themes. All defaults may be customised in a context sensitive
233 # matter by using zsh's `zstyle' mechanism.
234 typeset -gA ganneff_prompt_pre_default \
235 ganneff_prompt_post_default \
236 ganneff_prompt_token_default
237
238 ganneff_prompt_pre_default=(
239 at ''
240 battery ' '
241 change-root ''
242 date '${PR_BLUE}'
243 history '${PR_GREEN}'
244 host '${PR_RED}'
245 jobs '${PR_CYAN}'
246 newline ''
247 path '${PR_MAGENTA}'
248 percent ''
249 rc '${PR_RED}'
250 rc-always ''
251 shell-level '${PR_RED}'
252 time '${PR_BLUE}'
253 user '${PR_BLUE}'
254 vcs ''
255 ulcorner '${PR_SHIFT_IN}'
256 llcorner '${PR_SHIFT_IN}'
257 urcorner '${PR_SHIFT_IN}'
258 lrcorner '${PR_SHIFT_IN}'
259 line '${PR_SHIFT_IN}'
260 pts ''
261 openbracket ''
262 closebracket ''
263 pipe ''
264 space ''
265 flexline '${PR_SHIFT_IN}'
266 )
267
268 ganneff_prompt_post_default=(
269 at ''
270 battery ''
271 change-root ''
272 date '${PR_NO_COLOR}'
273 history '${PR_NO_COLOR}'
274 host '${PR_NO_COLOR}'
275 jobs '${PR_NO_COLOR}'
276 newline ''
277 path '${PR_NO_COLOR}'
278 percent ''
279 rc '${PR_NO_COLOR}'
280 rc-always ''
281 shell-level '${PR_NO_COLOR}'
282 time '${PR_NO_COLOR}'
283 user '${PR_NO_COLOR}'
284 vcs ''
285 ulcorner '${PR_SHIFT_OUT}'
286 llcorner '${PR_SHIFT_OUT}'
287 urcorner '${PR_SHIFT_OUT}'
288 lrcorner '${PR_SHIFT_OUT}'
289 line '${PR_SHIFT_OUT}'
290 pts ''
291 openbracket ''
292 closebracket ''
293 pipe ''
294 space ''
295 flexline '${PR_SHIFT_OUT}'
296 )
297
298 ganneff_prompt_token_default=(
299 at '@'
300 battery 'PERCENT'
301 change-root 'debian_chroot'
302 date '%D{%Y-%m-%d}'
303 history '{#%!}'
304 host '%m'
305 jobs '[%j running job(s)] '
306 newline $'\n'
307 path '%40<..<%~%<<'
308 percent '% # '
309 rc '%(?..%? )'
310 rc-always '%?'
311 shell-level '%(2L.%L.)'
312 time '%D{%H:%M:%S}'
313 user '%n'
314 vcs '0'
315 ulcorner '${PR_ULCORNER}'
316 llcorner '${PR_LLCORNER}'
317 urcorner '${PR_URCORNER}'
318 lrcorner '${PR_LRCORNER}'
319 line '${PR_HBAR}'
320 pts ':%y'
321 openbracket '('
322 closebracket ')'
323 pipe '|'
324 space ' '
325 flexline 'PR_FLEXLINE'
326 )
327
328 PR_FLEXLINE=""
329 add-zsh-hook precmd prompt_ganneff_precmd
330 # Call the winch function once to ensure the length gets calculated
331 # correctly
332 prompt_ganneff_winch
333 local pr_battery
334 zstyle -s ':prompt:ganneff' battery pr_battery
335 if [[ $pr_battery != "none" ]]; then
336 add-zsh-hook precmd prompt_ganneff_battery
337 prompt_ganneff_battery
338 fi
339
340 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}
341 prompt_ganneff_winch"
342 }
343
344 prompt_ganneff_precmd () {
345 emulate -L zsh
346 setopt nolocaltraps
347
348 zstyle -t ':prompt:ganneff' vcs_info && vcs_info
349 local -a left_items right_items
350 left_items=(ulcorner line openbracket user at host pts closebracket line history flexline
351 openbracket path closebracket line urcorner newline
352 llcorner line rc openbracket time closebracket line vcs line change-root pipe space)
353 PR_PS1=""; nomore=0
354 ganneff_prompt_addto PS1 full "${left_items[@]}"
355 if zstyle -T ":prompt:ganneff:right:setup" use-rprompt; then
356 right_items=(space pipe line openbracket date closebracket line lrcorner)
357 ganneff_prompt_addto RPS1 full "${right_items[@]}"
358 fi
359
360 # Now a kind-of-hack to reduce the prompt when we run out of space.
361 promptsize=${#PR_PS1}
362 if [[ ${promptsize} -lt ${TERMWIDTH} ]]; then
363 # the q here should be ${PR_HBAR}, but for some reason zsh didn't like me,
364 # so meh
365 if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]] \
366 && [[ "$TERM" != "linux" ]]; then
367 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..q.)}"
368 else
369 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..-.)}"
370 fi
371 else
372 # Small size prompt is needed
373 left_items=(ulcorner line openbracket user at host closebracket line openbracket path closebracket newline
374 llcorner line rc openbracket time closebracket line vcs line pipe space)
375 ganneff_prompt_addto PS1 small "${left_items[@]}"
376 # And with a small prompt, we don't show the right size at all.
377 RPS1=""
378 fi
379 }
380
381 prompt_ganneff_length () {
382 (( TERMWIDTH = ${COLUMNS} - 1 ))
383 }
384
385 prompt_ganneff_winch () {
386 emulate -L zsh
387 setopt nolocaltraps noksharrays unset
388
389 # Delete ourself from TRAPWINCH if not using our precmd insert.
390 [[ $precmd_functions = *prompt_ganneff_precmd* ]] && prompt_ganneff_length ||
391 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}"
392 }
393
394 ganneff_typeset_and_wrap () {
395 emulate -L zsh
396 local target="$1"
397 local new="$2"
398 local left="$3"
399 local right="$4"
400
401 if (( ${+parameters[$new]} )); then
402 typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
403 fi
404 }
405
406 ganneff_prompt_addto () {
407 emulate -L zsh
408 local target="$1"
409 local size="$2"
410 local lr it apre apost new v
411 local -a items
412 shift
413 shift
414
415 [[ $target == PS1 ]] && lr=left || lr=right
416 zstyle -a ":prompt:ganneff:${lr}:${size}:setup" items items || items=( "$@" )
417 typeset -g "${target}="
418 for it in "${items[@]}"; do
419 zstyle -s ":prompt:ganneff:${lr}:items:$it" pre apre \
420 || apre=${ganneff_prompt_pre_default[$it]}
421 zstyle -s ":prompt:ganneff:${lr}:items:$it" post apost \
422 || apost=${ganneff_prompt_post_default[$it]}
423 zstyle -s ":prompt:ganneff:${lr}:items:$it" token new \
424 || new=${ganneff_prompt_token_default[$it]}
425 typeset -g "${target}=${(P)target}${apre}"
426 # Store the expanded value in PR_PS1, as we use that for length calculations
427 [[ $it == "newline" ]] && nomore=1
428 if [[ $nomore -eq 0 ]] && [[ $it != "flexline" ]] && PR_PS1+=${(e%)new}
429 case $it in
430 battery)
431 ganneff_typeset_and_wrap $target $new '' ''
432 ;;
433 change-root)
434 ganneff_typeset_and_wrap $target $new '(' ')'
435 ;;
436 flexline)
437 typeset -g "${target}=${(P)target}\${${new}}"
438 ;;
439 ganneff-chroot)
440 if [[ -n ${(P)new} ]]; then
441 typeset -g "${target}=${(P)target}(CHROOT)"
442 fi
443 ;;
444 vcs)
445 v="vcs_info_msg_${new}_"
446 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
447 typeset -g "${target}=${(P)target}${(P)v}"
448 fi
449 ;;
450 *) typeset -g "${target}=${(P)target}${new}" ;;
451 esac
452 typeset -g "${target}=${(P)target}${apost}"
453 done
454 }
455
456 prompt_ganneff_battery() {
457 zstyle -s ':prompt:ganneff' battery pr_battery
458 case $pr_battery in
459 ibam)
460 local ACPIDATA=$(ibam --percentbattery 2>/dev/null || echo "")
461 PERCENT=${${ACPIDATA[(f)1]}[(w)-2]}
462 ;;
463 acpi)
464 PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
465 ;;
466 *)
467 PERCENT=""
468 ;;
469 esac
470
471 if [[ -z "$PERCENT" ]] ; then
472 PERCENT="No battery or $pr_battery not present "
473 else
474 if [[ "$PERCENT" -lt 20 ]] ; then
475 PERCENT="warning: ${PERCENT}%%"
476 else
477 PERCENT="${PERCENT}%%"
478 fi
479 fi
480 }
481
482 prompt_ganneff_setup "$@"