3 # This prompt is based on work of other people.
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/
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
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
17 # - The winch function as seen in the prompt theme "bart", delivered
20 prompt_ganneff_help () {
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
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/
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
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:
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).
45 - The attributes used with the items are customisable via strings
46 used before and after the actual item.
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.
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
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!
67 The actual configuration is done via zsh's \`zstyle' mechanism. The
68 context, that is used while looking up styles is:
70 ':prompt:ganneff:<left-or-right>:<full-or-small>:<subcontext>'
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
79 <subcontext> is either \`setup' or 'items:<item>', where \`<item>'
80 is one of the available items.
82 The styles available under ':prompt:ganneff:':
84 - vcs_info (boolean): If \`true' (the default), use \`vcs_info'.
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.
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 "
104 - colors (boolean): If \`true' (the default), use colors. b/w
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.
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.
115 - use-rprompt (boolean): If \`true' (the default), print the
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
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
128 zstyle ':prompt:ganneff:*:items:user' pre '\${PR_RED}'
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
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.
143 prompt_ganneff_setup () {
147 # See if we can and should use extended characters to look nicer.
148 if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]]; then
150 set -A altchar ${(s..)terminfo[acsc]}
151 # Some stuff to help us draw nice lines
152 PR_SET_CHARSET="%{$terminfo[enacs]%}"
153 PR_SHIFT_IN="%{$terminfo[smacs]%}"
154 PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
155 PR_HBAR=${altchar[q]:--}
156 PR_ULCORNER=${altchar[l]:--}
157 PR_LLCORNER=${altchar[m]:--}
158 PR_LRCORNER=${altchar[j]:--}
159 PR_URCORNER=${altchar[k]:--}
171 if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
172 if [[ -n "${BLUE}" ]] && [[ -n "${YELLOW}" ]]; then
173 # Two defined, so we assume someone already defined themself
174 # the colors. We just use them and not setup our own.
175 for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
176 eval PR_$color="%{${(P)color}%}"
177 eval PR_BOLD_$color="%{$terminfo[bold]${(LP)color}%}"
179 PR_NO_COLOR="%{${reset_color}%}"
181 # Seems like colors are not defined, so set them up
192 PR_NO_COLOR="%{${reset_color}%}"
196 # The secondary prompt, printed when the shell needs more
197 # information to complete a command. %_ displays any shell constructs
198 # or quotation marks which are currently being processed.
199 if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
200 PS2='${PR_CYAN}${PR_SHIFT_IN}${PR_HBAR}${PR_BLUE}${PR_HBAR}${PR_SHIFT_OUT}\
201 (${PR_GREEN}%_${PR_BLUE})\
202 ${PR_SHIFT_IN}${PR_HBAR}${PR_CYAN}${PR_HBAR}${PR_SHIFT_OUT}${PR_NO_COLOR} '
206 # selection prompt used within a select loop.
208 # the execution trace prompt (setopt xtrace). default: '+%N:%i>'
211 if zstyle -t ':prompt:ganneff' vcs_info && \
212 is439 && autoload -Uz vcs_info && vcs_info; then
213 if zstyle -t ':prompt:ganneff' set_vcs_info_defaults; then
214 # gather version control information for inclusion in a prompt
215 # we will only be using one variable, so let the code know now.
216 zstyle ':vcs_info:*' max-exports 1
217 zstyle ':vcs_info:*' use-prompt-escapes
218 zstyle ':vcs_info:*' use_simple
219 zstyle ':vcs_info:*' stagedstr "!"
220 zstyle ':vcs_info:*' unstagedstr "?"
221 zstyle ':vcs_info:*' check-for-changes true
223 # change vcs_info formats for the prompt
224 zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "${PR_YELLOW}%b%{${PR_RED}%}:${PR_YELLOW}%r${PR_NO_COLOR}"
225 zstyle ':vcs_info:*' formats "(${PR_YELLOW}%s${PR_NO_COLOR})-[${PR_GREEN}%b${PR_NO_COLOR}]%m%u%c "
226 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 "
230 # These maps define default tokens and pre-/post-decoration for items to be
231 # used within the themes. All defaults may be customised in a context sensitive
232 # matter by using zsh's `zstyle' mechanism.
233 typeset -gA ganneff_prompt_pre_default \
234 ganneff_prompt_post_default \
235 ganneff_prompt_token_default
237 ganneff_prompt_pre_default=(
242 history '${PR_GREEN}'
250 shell-level '${PR_RED}'
254 ulcorner '${PR_SHIFT_IN}'
255 llcorner '${PR_SHIFT_IN}'
256 urcorner '${PR_SHIFT_IN}'
257 lrcorner '${PR_SHIFT_IN}'
258 line '${PR_SHIFT_IN}'
264 flexline '${PR_SHIFT_IN}'
267 ganneff_prompt_post_default=(
271 date '${PR_NO_COLOR}'
272 history '${PR_NO_COLOR}'
273 host '${PR_NO_COLOR}'
274 jobs '${PR_NO_COLOR}'
276 path '${PR_NO_COLOR}'
280 shell-level '${PR_NO_COLOR}'
281 time '${PR_NO_COLOR}'
282 user '${PR_NO_COLOR}'
284 ulcorner '${PR_SHIFT_OUT}'
285 llcorner '${PR_SHIFT_OUT}'
286 urcorner '${PR_SHIFT_OUT}'
287 lrcorner '${PR_SHIFT_OUT}'
288 line '${PR_SHIFT_OUT}'
294 flexline '${PR_SHIFT_OUT}'
297 ganneff_prompt_token_default=(
300 change-root 'debian_chroot'
304 jobs '[%j running job(s)] '
310 shell-level '%(3L.+ .)'
314 ulcorner '${PR_ULCORNER}'
315 llcorner '${PR_LLCORNER}'
316 urcorner '${PR_URCORNER}'
317 lrcorner '${PR_LRCORNER}'
324 flexline 'PR_FLEXLINE'
328 add-zsh-hook precmd prompt_ganneff_precmd
329 # Call the winch function once to ensure the length gets calculated
333 zstyle -s ':prompt:ganneff' battery pr_battery
334 if [[ $pr_battery != "none" ]]; then
335 add-zsh-hook precmd prompt_ganneff_battery
336 prompt_ganneff_battery
339 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}
340 prompt_ganneff_winch"
343 prompt_ganneff_precmd () {
347 zstyle -t ':prompt:ganneff' vcs_info && vcs_info
348 local -a left_items right_items
349 left_items=(ulcorner line openbracket user at host pts closebracket line history flexline
350 openbracket path closebracket line urcorner newline
351 llcorner line rc openbracket time closebracket line vcs line change-root pipe space)
353 ganneff_prompt_addto PS1 full "${left_items[@]}"
354 if zstyle -T ":prompt:ganneff:right:setup" use-rprompt; then
355 right_items=(space pipe line openbracket date closebracket line lrcorner)
356 ganneff_prompt_addto RPS1 full "${right_items[@]}"
359 # Now a kind-of-hack to reduce the prompt when we run out of space.
360 promptsize=${#PR_PS1}
361 if [[ ${promptsize} -lt ${TERMWIDTH} ]]; then
362 # the q here should be ${PR_HBAR}, but for some reason zsh didn't like me,
364 if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]]; then
365 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..q.)}"
367 PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..-.)}"
370 # Small size prompt is needed
371 left_items=(ulcorner line openbracket user at host closebracket line openbracket path closebracket newline
372 llcorner line rc openbracket time closebracket line vcs line pipe space)
373 ganneff_prompt_addto PS1 small "${left_items[@]}"
374 # And with a small prompt, we don't show the right size at all.
379 prompt_ganneff_length () {
380 (( TERMWIDTH = ${COLUMNS} - 1 ))
383 prompt_ganneff_winch () {
385 setopt nolocaltraps noksharrays unset
387 # Delete ourself from TRAPWINCH if not using our precmd insert.
388 [[ $precmd_functions = *prompt_ganneff_precmd* ]] && prompt_ganneff_length ||
389 functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}"
392 ganneff_typeset_and_wrap () {
399 if (( ${+parameters[$new]} )); then
400 typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
404 ganneff_prompt_addto () {
408 local lr it apre apost new v
413 [[ $target == PS1 ]] && lr=left || lr=right
414 zstyle -a ":prompt:ganneff:${lr}:${size}:setup" items items || items=( "$@" )
415 typeset -g "${target}="
416 for it in "${items[@]}"; do
417 zstyle -s ":prompt:ganneff:${lr}:items:$it" pre apre \
418 || apre=${ganneff_prompt_pre_default[$it]}
419 zstyle -s ":prompt:ganneff:${lr}:items:$it" post apost \
420 || apost=${ganneff_prompt_post_default[$it]}
421 zstyle -s ":prompt:ganneff:${lr}:items:$it" token new \
422 || new=${ganneff_prompt_token_default[$it]}
423 typeset -g "${target}=${(P)target}${apre}"
424 # Store the expanded value in PR_PS1, as we use that for length calculations
425 [[ $it == "newline" ]] && nomore=1
426 if [[ $nomore -eq 0 ]] && [[ $it != "flexline" ]] && PR_PS1+=${(e%)new}
429 ganneff_typeset_and_wrap $target $new '' ''
432 ganneff_typeset_and_wrap $target $new '(' ')'
435 typeset -g "${target}=${(P)target}\${${new}}"
438 if [[ -n ${(P)new} ]]; then
439 typeset -g "${target}=${(P)target}(CHROOT)"
443 v="vcs_info_msg_${new}_"
444 if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
445 typeset -g "${target}=${(P)target}${(P)v}"
448 *) typeset -g "${target}=${(P)target}${new}" ;;
450 typeset -g "${target}=${(P)target}${apost}"
454 prompt_ganneff_battery() {
455 zstyle -s ':prompt:ganneff' battery pr_battery
458 local ACPIDATA=$(ibam --percentbattery 2>/dev/null || echo "")
459 PERCENT=${${ACPIDATA[(f)1]}[(w)-2]}
462 PERCENT="${${"$(acpi 2>/dev/null)"}/(#b)[[:space:]]#Battery <->: [^0-9]##, (<->)%*/${match[1]}}"
469 if [[ -z "$PERCENT" ]] ; then
470 PERCENT="No battery or $pr_battery not present "
472 if [[ "$PERCENT" -lt 20 ]] ; then
473 PERCENT="warning: ${PERCENT}%%"
475 PERCENT="${PERCENT}%%"
480 prompt_ganneff_setup "$@"