Add colon item, no color, token :
[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 tech 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 Should they not fit your need, there is an easy way to have the
68 prompt include basically anything you want. Just define your own
69 items. For that you simply define them inside the
70 ':prompt:ganneff:extra:' namespace.
71
72 Example: To have the prompt include the value of the variable
73 \$FOOBAR, in red and have the variable updated by the function
74 jj_foobar, use the following:
75
76 zstyle ':prompt:ganneff:extra:foobar' pre '${PR_RED}'
77 zstyle ':prompt:ganneff:extra:foobar' post '${PR_NO_COLOR}'
78 zstyle ':prompt:ganneff:extra:foobar' token '$FOOBAR'
79 zstyle ':prompt:ganneff:extra:foobar' precmd jj_foobar
80
81 Now you can add the token \`foobar' to the list of items and voila,
82 your own stuff appears.
83
84 Note that the function part only works in zsh 4.3.5 or later (I've
85 been to lazy to replace add-zsh-hook with something for the older
86 versions).
87
88
89 The configuration of the predefined items can also be changed using
90 zsh's \`zstyle' mechanism. The context, that is used while looking
91 up styles is:
92
93 ':prompt:ganneff:<left-or-right>:<full-or-small>:<subcontext>'
94
95 Here <left-or-right> is either \`left' or \`right', signifying
96 whether the style should affect the left or the right prompt.
97
98 <full-or-small> is either \`full' or \`small' and only valid in the
99 item selection, signifying wether the item list should affect the
100 full length or the "small terminal" prompt. As "small terminal"
101 prompt does not display the right side prompt, <full-or-small> has
102 no effect on the right side prompt.
103
104 <subcontext> is either \`setup' or 'items:<item>', where \`<item>'
105 is one of the available items.
106
107 The styles/settings available under ':prompt:ganneff:':
108
109 - vcs_info (boolean): If \`true' (the default), use \`vcs_info'.
110
111 - set_vcs_info_defaults (boolean): If \`true' (the default),
112 various vcs_info settings will be done. If unset or \`false'
113 it is assumed that the user has already done this.
114
115 The default setup is:
116 zstyle ':vcs_info:*' max-exports 1
117 zstyle ':vcs_info:*' use-prompt-escapes
118 zstyle ':vcs_info:*' use_simple
119 zstyle ':vcs_info:*' stagedstr "!"
120 zstyle ':vcs_info:*' unstagedstr "?"
121 zstyle ':vcs_info:*' check-for-changes true
122 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat \
123 "\${PR_YELLOW}%b%{\${PR_RED}%}:\${PR_YELLOW}%r\${PR_NO_COLOR}"
124 zstyle ':vcs_info:*' formats \
125 "(\${PR_YELLOW}%s\${PR_NO_COLOR})-[\${PR_GREEN}%b\${PR_NO_COLOR}]%m%u%c "
126 zstyle ':vcs_info:*' actionformats \
127 "(\${PR_YELLOW}%s\${PR_NO_COLOR})-[\${PR_GREEN}%b\${PR_NO_COLOR}-\${PR_RED}(%a)\${PR_NO_COLOR}]%m%u%c "
128
129 - colors (boolean): If \`true' (the default), use colors. b/w
130 otherwise.
131
132 - nicelines (boolean): If \`true' (the default), use special
133 magic to draw nice lines and corners. Might not work on every
134 terminal. If false, draws using plain ascii characters.
135 Linux console also seems to identify itself as if it could,
136 but then doesn't do drawing right (not in our way at least).
137
138 - battery (string): If \`none' then no battery function at all.
139 If either \`ibam' or \`acpi' then use those tools to gather
140 the current battery level.
141
142 - use-rprompt (boolean): If \`true' (the default), print the
143 right side prompt.
144
145 - items (list): The list of items used in the prompt. If \`vcs' is
146 present in the list, the theme's code invokes \`vcs_info'
147 accordingly. Default (left): rc change-root user at host path vcs
148 percent; Default (right): sad-smiley
149
150 Note that both, nicelines and colors are forced to false in case the
151 TERM variable is set to dumb.
152
153 Available styles in 'items:<item>' are: pre, post, token and precmd.
154 Pre and Post are strings that are inserted before (pre) and after
155 (post) the item in question. Token is the token itself that gets
156 inserted into PS1. Thus, the following would cause the
157 user name to be printed in red instead of the default blue:
158
159 zstyle ':prompt:ganneff:*:items:user' pre '\${PR_RED}'
160
161 and
162
163 zstyle ':prompt:ganneff:*:items:date' token '%D{%Y-%m-%d [d:%j/w:%V]}'
164
165 will output a very different date token compared with the default
166 definition of '%D{%Y-%m-%d}'.
167
168 Note, that in the above example the \`post' style may remain at its
169 default value, because its default value is '\${PR_NO_COLOR}', which
170 turns the foreground text attribute off (which is exactly, what is
171 still required with the new \`pre' value).
172
173 Possible values for the colors: \${PR_XXX} and \${PR_BOLD_XXX} with
174 XXX replaced with one of: RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK.
175 \${PR_NO_COLOR} resets color.
176 Using the \${PR_XXX} values instead of zsh's internal \%F{xxx} allows
177 the usage of the colors style to turn of prompt colors easily.
178
179 Last note: You really want to have "setopt promptsubst", otherwise you
180 won't like this prompt.
181 __EOF0__
182 }
183
184 prompt_ganneff_setup () {
185 emulate -L zsh
186 setopt nolocaltraps
187
188 # We forcefully overwrite colors and nicelines setting for a dumb
189 # terminal.
190 if [[ "$TERM" == "dumb" ]]; then
191 zstyle ':prompt:ganneff' colors false
192 zstyle ':prompt:ganneff' nicelines false
193 fi
194
195 # See if we can and should use extended characters to look nicer.
196 if zstyle -t ':prompt:ganneff' nicelines; then
197 typeset -A altchar
198 set -A altchar ${(s..)terminfo[acsc]}
199 # Some stuff to help us draw nice lines
200 PR_SET_CHARSET="%{$terminfo[enacs]%}"
201 PR_SHIFT_IN="%{$terminfo[smacs]%}"
202 PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
203 PR_HBAR=${altchar[q]:--}
204 PR_ULCORNER=${altchar[l]:--}
205 PR_LLCORNER=${altchar[m]:--}
206 PR_LRCORNER=${altchar[j]:--}
207 PR_URCORNER=${altchar[k]:--}
208 else
209 PR_SET_CHARSET=""
210 PR_SHIFT_IN=""
211 PR_SHIFT_OUT=""
212 PR_HBAR="-"
213 PR_ULCORNER=""
214 PR_LLCORNER=""
215 PR_LRCORNER=""
216 PR_URCORNER=""
217 fi
218
219 if zstyle -t ':prompt:ganneff' colors; then
220 if [[ -n "${BLUE}" ]] && [[ -n "${YELLOW}" ]]; then
221 # Two defined, so we assume someone already defined themself
222 # the colors. We just use them and not setup our own.
223 for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK GREY; do
224 eval PR_$color='%{${(P)color}%}'
225 eval PR_BOLD_$color='%{$terminfo[bold]${(LP)color}%}'
226 done
227 PR_NO_COLOR="%{${reset_color}%}"
228 else
229 # Seems like colors are not defined, so set them up
230 # This duplicates docolors from 01_Terminfo.zsh, but is here to have
231 # prompt_ganneff_setup not require anything else from my dotfiles
232 if autoload -Uz colors && colors 2>/dev/null ; then
233 for COLOR in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK GREY; do
234 eval PR_$COLOR='%{$fg_no_bold[${(L)COLOR}]%}'
235 eval PR_BOLD_$COLOR='%{$fg_bold[${(L)COLOR}]%}'
236 done
237 eval PR_NO_COLOR='%{$reset_color%}'
238 else
239 PR_BLUE=$'%{\e[1;34m%}'
240 PR_RED=$'%{\e[1;31m%}'
241 PR_GREEN=$'%{\e[1;32m%}'
242 PR_CYAN=$'%{\e[1;36m%}'
243 PR_WHITE=$'%{\e[1;37m%}'
244 PR_MAGENTA=$'%{\e[1;35m%}'
245 PR_YELLOW=$'%{\e[1;33m%}'
246 PR_NO_COLOR=$'%{\e[0m%}'
247 fi
248 fi
249 else
250 PR_BLUE=''
251 PR_RED=''
252 PR_GREEN=''
253 PR_CYAN=''
254 PR_WHITE=''
255 PR_MAGENTA=''
256 PR_YELLOW=''
257 PR_NO_COLOR="%{${reset_color}%}"
258 fi
259
260 # Easy things first.
261 # The secondary prompt, printed when the shell needs more
262 # information to complete a command. %_ displays any shell constructs
263 # or quotation marks which are currently being processed.
264 if zstyle -t ':prompt:ganneff' nicelines; then
265 PS2='${PR_CYAN}${PR_SHIFT_IN}${PR_HBAR}${PR_BLUE}${PR_HBAR}${PR_SHIFT_OUT}\
266 (${PR_GREEN}%_${PR_BLUE})\
267 ${PR_SHIFT_IN}${PR_HBAR}${PR_CYAN}${PR_HBAR}${PR_SHIFT_OUT}${PR_NO_COLOR} '
268 else
269 PS2='-(%_)- '
270 fi
271 # selection prompt used within a select loop.
272 PS3='?# '
273 # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
274 PS4='+%N:%i:%_> '
275
276 if zstyle -t ':prompt:ganneff' vcs_info && \
277 is439 && autoload -Uz vcs_info && vcs_info; then
278 if zstyle -t ':prompt:ganneff' set_vcs_info_defaults; then
279 # gather version control information for inclusion in a prompt
280 # we will only be using one variable, so let the code know now.
281 zstyle ':vcs_info:*' max-exports 1
282 zstyle ':vcs_info:*' use-prompt-escapes
283 zstyle ':vcs_info:*' use_simple
284 zstyle ':vcs_info:*' stagedstr "!"
285 zstyle ':vcs_info:*' unstagedstr "?"
286 zstyle ':vcs_info:*' check-for-changes true
287
288 # change vcs_info formats for the prompt
289 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "${PR_YELLOW}%b%{${PR_RED}%}:${PR_YELLOW}%r${PR_NO_COLOR}"
290 zstyle ':vcs_info:*' formats "(${PR_YELLOW}%s${PR_NO_COLOR})-[${PR_GREEN}%b${PR_NO_COLOR}]%m%u%c "
291 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 "
292 fi
293 fi
294
295 # These maps define default tokens and pre-/post-decoration for items to be
296 # used within the themes. All defaults may be customised in a context sensitive
297 # matter by using zsh's `zstyle' mechanism.
298 typeset -gA ganneff_prompt_pre_default \
299 ganneff_prompt_post_default \
300 ganneff_prompt_token_default
301
302 ganneff_prompt_pre_default=(
303 at ''
304 battery ' '
305 change-root ''
306 date '${PR_BLUE}'
307 history '${PR_GREEN}'
308 host '${PR_RED}'
309 jobs '${PR_CYAN}'
310 newline ''
311 path '${PR_MAGENTA}'
312 percent ''
313 rc '${PR_RED}'
314 rc-always ''
315 shell-level '${PR_RED}'
316 time '${PR_BLUE}'
317 user '${PR_BLUE}'
318 vcs ''
319 ulcorner '${PR_SHIFT_IN}'
320 llcorner '${PR_SHIFT_IN}'
321 urcorner '${PR_SHIFT_IN}'
322 lrcorner '${PR_SHIFT_IN}'
323 line '${PR_SHIFT_IN}'
324 pts ''
325 privileges ''
326 openparentheses ''
327 closeparentheses ''
328 openbracket ''
329 closebracket ''
330 openbraces ''
331 closebraces ''
332 openanglebracket ''
333 closeanglebracket ''
334 pipe ''
335 space ''
336 colon ''
337 flexline '${PR_SHIFT_IN}'
338 )
339
340
341 ganneff_prompt_post_default=(
342 at ''
343 battery ''
344 change-root ''
345 date '${PR_NO_COLOR}'
346 history '${PR_NO_COLOR}'
347 host '${PR_NO_COLOR}'
348 jobs '${PR_NO_COLOR}'
349 newline ''
350 path '${PR_NO_COLOR}'
351 percent ''
352 rc '${PR_NO_COLOR}'
353 rc-always ''
354 shell-level '${PR_NO_COLOR}'
355 time '${PR_NO_COLOR}'
356 user '${PR_NO_COLOR}'
357 vcs ''
358 ulcorner '${PR_SHIFT_OUT}'
359 llcorner '${PR_SHIFT_OUT}'
360 urcorner '${PR_SHIFT_OUT}'
361 lrcorner '${PR_SHIFT_OUT}'
362 line '${PR_SHIFT_OUT}'
363 pts ''
364 privileges ''
365 openparentheses ''
366 closeparentheses ''
367 openbracket ''
368 closebracket ''
369 openbraces ''
370 closebraces ''
371 openanglebracket ''
372 closeanglebracket ''
373 pipe ''
374 space ''
375 colon ''
376 flexline '${PR_SHIFT_OUT}'
377 )
378
379 ganneff_prompt_token_default=(
380 at '@'
381 battery 'PERCENT'
382 change-root 'debian_chroot'
383 date '%D{%Y-%m-%d}'
384 history '{#%!}'
385 host '%m'
386 jobs '[%j running job(s)] '
387 newline $'\n'
388 path '%40<..<%~%<<'
389 percent '% # '
390 rc '%(?..%? )'
391 rc-always '%?'
392 shell-level '%(2L.%L.)'
393 time '%D{%H:%M:%S}'
394 user '%n'
395 vcs '0'
396 ulcorner '${PR_ULCORNER}'
397 llcorner '${PR_LLCORNER}'
398 urcorner '${PR_URCORNER}'
399 lrcorner '${PR_LRCORNER}'
400 line '${PR_HBAR}'
401 pts '%y'
402 privileges '%#'
403 openparentheses '('
404 closeparentheses ')'
405 openbracket '['
406 closebracket ']'
407 openbraces '{'
408 closebraces '}'
409 openanglebracket '<'
410 closeanglebracket '>'
411 pipe '|'
412 space ' '
413 colon ':'
414 flexline 'PR_FLEXLINE'
415 )
416
417 PR_FLEXLINE=""
418 add-zsh-hook precmd prompt_ganneff_precmd
419 # Call the winch function once to ensure the length gets calculated
420 # correctly
421 prompt_ganneff_winch
422 local pr_battery
423 zstyle -s ':prompt:ganneff' battery pr_battery
424 if [[ $pr_battery != "none" ]]; then
425 add-zsh-hook precmd prompt_ganneff_battery
426 prompt_ganneff_battery
427 fi
428
429 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}
430 prompt_ganneff_winch"
431 }
432
433 prompt_ganneff_precmd () {
434 emulate -L zsh
435 setopt nolocaltraps
436
437 zstyle -t ':prompt:ganneff' vcs_info && vcs_info
438 local -a left_items right_items
439 left_items=(ulcorner line openbracket user at host pts closebracket line history flexline
440 openbracket path closebracket line urcorner newline
441 llcorner line rc openbracket time closebracket line vcs line change-root pipe space)
442 PR_PS1=""; nomore=0
443 ganneff_prompt_addto PS1 full "${left_items[@]}"
444 if zstyle -T ":prompt:ganneff:right:setup" use-rprompt; then
445 right_items=(space pipe line openbracket date closebracket line lrcorner)
446 ganneff_prompt_addto RPS1 full "${right_items[@]}"
447 fi
448
449 # Now a kind-of-hack to reduce the prompt when we run out of space.
450 promptsize=${#PR_PS1}
451 if [[ ${promptsize} -lt ${TERMWIDTH} ]]; then
452 # the q here should be ${PR_HBAR}, but for some reason zsh didn't like me,
453 # so meh
454 if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]] \
455 && [[ "$TERM" != "linux" ]]; then
456 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..q.)}"
457 else
458 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..-.)}"
459 fi
460 else
461 # Small size prompt is needed
462 left_items=(ulcorner line openbracket user at host closebracket line openbracket path closebracket newline
463 llcorner line rc openbracket time closebracket line vcs line pipe space)
464 ganneff_prompt_addto PS1 small "${left_items[@]}"
465 # And with a small prompt, we don't show the right size at all.
466 RPS1=""
467 fi
468 }
469
470 prompt_ganneff_length () {
471 (( TERMWIDTH = ${COLUMNS} - 1 ))
472 }
473
474 prompt_ganneff_winch () {
475 emulate -L zsh
476 setopt nolocaltraps noksharrays unset
477
478 # Delete ourself from TRAPWINCH if not using our precmd insert.
479 [[ $precmd_functions = *prompt_ganneff_precmd* ]] && prompt_ganneff_length ||
480 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}"
481 }
482
483 ganneff_typeset_and_wrap () {
484 emulate -L zsh
485 local target="$1"
486 local new="$2"
487 local left="$3"
488 local right="$4"
489
490 if (( ${+parameters[$new]} )); then
491 typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
492 fi
493 }
494
495 ganneff_prompt_addto () {
496 emulate -L zsh
497 local target="$1"
498 local size="$2"
499 local lr it apre apost new v prefunc
500 local -a items
501 shift
502 shift
503
504 [[ $target == PS1 ]] && lr=left || lr=right
505 zstyle -a ":prompt:ganneff:${lr}:${size}:setup" items items || items=( "$@" )
506 typeset -g "${target}="
507 for it in "${items[@]}"; do
508 zstyle -s ":prompt:ganneff:${lr}:items:$it" pre apre \
509 || zstyle -s ":prompt:ganneff:extra:$it" pre apre \
510 || apre=${ganneff_prompt_pre_default[$it]}
511 zstyle -s ":prompt:ganneff:${lr}:items:$it" post apost \
512 || zstyle -s ":prompt:ganneff:extra:$it" post apost \
513 || apost=${ganneff_prompt_post_default[$it]}
514 zstyle -s ":prompt:ganneff:${lr}:items:$it" token new \
515 || zstyle -s ":prompt:ganneff:extra:$it" token new \
516 || new=${ganneff_prompt_token_default[$it]}
517
518 # Now check if there is the wish for a precmd function and if so,
519 # run it
520 zstyle -s ":prompt:ganneff:extra:$it" precmd prefunc
521 if [[ -n "${prefunc}" ]]; then
522 ${prefunc} || true
523 fi
524
525 typeset -g "${target}=${(P)target}${apre}"
526 # Store the expanded value in PR_PS1, as we use that for length calculations
527 [[ $it == "newline" ]] && nomore=1
528 if [[ $nomore -eq 0 ]] && [[ $it != "flexline" ]] && PR_PS1+=${(e%)new}
529 case $it in
530 battery)
531 ganneff_typeset_and_wrap $target $new '' ''
532 ;;
533 change-root)
534 ganneff_typeset_and_wrap $target $new '(' ')'
535 ;;
536 flexline)
537 typeset -g "${target}=${(P)target}\${${new}}"
538 ;;
539 ganneff-chroot)
540 if [[ -n ${(P)new} ]]; then
541 typeset -g "${target}=${(P)target}(CHROOT)"
542 fi
543 ;;
544 vcs)
545 v="vcs_info_msg_${new}_"
546 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
547 typeset -g "${target}=${(P)target}${(P)v}"
548 fi
549 ;;
550 *) typeset -g "${target}=${(P)target}${new}" ;;
551 esac
552 typeset -g "${target}=${(P)target}${apost}"
553 done
554 }
555
556 prompt_ganneff_battery() {
557 zstyle -s ':prompt:ganneff' battery pr_battery
558 case $pr_battery in
559 ibam)
560 local ACPIDATA=$(ibam --percentbattery 2>/dev/null || echo "")
561 PERCENT=${${ACPIDATA[(f)1]}[(w)-2]}
562 ;;
563 acpi)
564 PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
565 ;;
566 *)
567 PERCENT=""
568 ;;
569 esac
570
571 if [[ -z "$PERCENT" ]] ; then
572 PERCENT="No battery or $pr_battery not present "
573 else
574 if [[ "$PERCENT" -lt 20 ]] ; then
575 PERCENT="warning: ${PERCENT}%%"
576 else
577 PERCENT="${PERCENT}%%"
578 fi
579 fi
580 }
581
582 is439(){
583 [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \
584 || $ZSH_VERSION == <5->* ]] && return 0
585 return 1
586 }
587
588 prompt_ganneff_setup "$@"