# - The "design" is taken from Phil!'s ZSH prompt, as found on
# http://aperiodic.net/phil/prompt/
#
-# - The technic using zstyle is inspired by the prompt as used by
+# - The tech using zstyle is inspired by the prompt as used by
# the grml-live system <http://grml.org>, see
# http://git.grml.org/?p=grml-etc-core.git;a=summary for details
# on theirs.
The available items are: at, battery, change-root, date, history,
host, jobs, newline, path, percent, rc, rc-always, shell-level,
time, user, vcs, ulcorner, llcorner, urcorner, lrcorner, line, pts,
- openbracket, closebracket, pipe, space, flexline
+ privileges, openparentheses, closeparentheses, openbracket,
+ closebracket, openbraces, closebraces, openanglebracket,
+ closeanglebracket, colon, pipe, space, flexline
Most of those should be self-explanatory, some may need more:
line - Draws a single line character
Only works in a two-line prompt in the upper line, that
is, a newline MUST appear in the setup!
- The actual configuration is done via zsh's \`zstyle' mechanism. The
- context, that is used while looking up styles is:
+ Should they not fit your need, there is an easy way to have the
+ prompt include basically anything you want. Just define your own
+ items. For that you simply define them inside the
+ ':prompt:ganneff:extra:' namespace.
+
+ Example: To have the prompt include the value of the variable
+ \$FOOBAR, in red and have the variable updated by the function
+ jj_foobar, use the following:
+
+ zstyle ':prompt:ganneff:extra:foobar' pre '${PR_RED}'
+ zstyle ':prompt:ganneff:extra:foobar' post '${PR_NO_COLOR}'
+ zstyle ':prompt:ganneff:extra:foobar' token '$FOOBAR'
+ zstyle ':prompt:ganneff:extra:foobar' precmd jj_foobar
+
+ Now you can add the token \`foobar' to the list of items and voila,
+ your own stuff appears.
+
+ Note that the function part only works in zsh 4.3.5 or later (I've
+ been to lazy to replace add-zsh-hook with something for the older
+ versions).
+
+
+ The configuration of the predefined items can also be changed using
+ zsh's \`zstyle' mechanism. The context, that is used while looking
+ up styles is:
':prompt:ganneff:<left-or-right>:<full-or-small>:<subcontext>'
- Here <left-or-right> is either \`left' or \`right', signifying whether the
- style should affect the left or the right prompt. <full-or-small> is
- either \`full' or \`small' and only valid in the item selection,
- signifying wether the item list should affect the full length or
- the "small terminal" prompt. As "small terminal" prompt does not
- display the right side prompt, <full-or-small> has no effect on the
- right side prompt.
+ Here <left-or-right> is either \`left' or \`right', signifying
+ whether the style should affect the left or the right prompt.
+
+ <full-or-small> is either \`full' or \`small' and only valid in the
+ item selection, signifying wether the item list should affect the
+ full length or the "small terminal" prompt. As "small terminal"
+ prompt does not display the right side prompt, <full-or-small> has
+ no effect on the right side prompt.
+
<subcontext> is either \`setup' or 'items:<item>', where \`<item>'
is one of the available items.
- The styles available under ':prompt:ganneff:':
+ The styles/settings available under ':prompt:ganneff:':
- vcs_info (boolean): If \`true' (the default), use \`vcs_info'.
- nicelines (boolean): If \`true' (the default), use special
magic to draw nice lines and corners. Might not work on every
terminal. If false, draws using plain ascii characters.
+ Linux console also seems to identify itself as if it could,
+ but then doesn't do drawing right (not in our way at least).
- battery (string): If \`none' then no battery function at all.
If either \`ibam' or \`acpi' then use those tools to gather
accordingly. Default (left): rc change-root user at host path vcs
percent; Default (right): sad-smiley
- Available styles in 'items:<item>' are: pre, post. These are strings that
- are inserted before (pre) and after (post) the item in question. Thus, the
- following would cause the user name to be printed in red instead of the
- default blue:
+ Note that both, nicelines and colors are forced to false in case the
+ TERM variable is set to dumb.
+
+ Available styles in 'items:<item>' are: pre, post, token and precmd.
+ Pre and Post are strings that are inserted before (pre) and after
+ (post) the item in question. Token is the token itself that gets
+ inserted into PS1. Thus, the following would cause the
+ user name to be printed in red instead of the default blue:
zstyle ':prompt:ganneff:*:items:user' pre '\${PR_RED}'
- Note, that the \`post' style may remain at its default value, because its
- default value is '\${PR_NO_COLOR}', which turns the foreground text
- attribute off (which is exactly, what is still required with the new
- \`pre' value).
+ and
+
+ zstyle ':prompt:ganneff:*:items:date' token '%D{%Y-%m-%d [d:%j/w:%V]}'
+
+ will output a very different date token compared with the default
+ definition of '%D{%Y-%m-%d}'.
+
+ Note, that in the above example the \`post' style may remain at its
+ default value, because its default value is '\${PR_NO_COLOR}', which
+ turns the foreground text attribute off (which is exactly, what is
+ still required with the new \`pre' value).
Possible values for the colors: \${PR_XXX} and \${PR_BOLD_XXX} with
- XXX replaced with one of: RED GREEN YELLOW BLUE MAGENTA CYAN WHITE
+ XXX replaced with one of: RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK.
\${PR_NO_COLOR} resets color.
Using the \${PR_XXX} values instead of zsh's internal \%F{xxx} allows
- the style to turn off colors to work.
+ the usage of the colors style to turn of prompt colors easily.
+
+ Last note: You really want to have "setopt promptsubst", otherwise you
+ won't like this prompt.
__EOF0__
}
emulate -L zsh
setopt nolocaltraps
+ # We forcefully overwrite colors and nicelines setting for a dumb
+ # terminal.
+ if [[ "$TERM" == "dumb" ]]; then
+ zstyle ':prompt:ganneff' colors false
+ zstyle ':prompt:ganneff' nicelines false
+ fi
+
# See if we can and should use extended characters to look nicer.
- if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]] \
- && [[ "$TERM" != "linux" ]]; then
- typeset -A altchar
- set -A altchar ${(s..)terminfo[acsc]}
- # Some stuff to help us draw nice lines
- PR_SET_CHARSET="%{$terminfo[enacs]%}"
- PR_SHIFT_IN="%{$terminfo[smacs]%}"
- PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
- PR_HBAR=${altchar[q]:--}
- PR_ULCORNER=${altchar[l]:--}
- PR_LLCORNER=${altchar[m]:--}
- PR_LRCORNER=${altchar[j]:--}
- PR_URCORNER=${altchar[k]:--}
+ if zstyle -t ':prompt:ganneff' nicelines; then
+ if [[ $(locale charmap) == "UTF-8" ]]; then
+ PR_SET_CHARSET=""
+ PR_SHIFT_IN=""
+ PR_SHIFT_OUT=""
+ PR_HBAR="─"
+ PR_ULCORNER="┌"
+ PR_LLCORNER="└"
+ PR_LRCORNER="┘"
+ PR_URCORNER="┐"
+ else
+ typeset -A altchar
+ set -A altchar ${(s..)terminfo[acsc]}
+ # Some stuff to help us draw nice lines
+ PR_SET_CHARSET="%{$terminfo[enacs]%}"
+ PR_SHIFT_IN="%{$terminfo[smacs]%}"
+ PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
+ PR_HBAR=${altchar[q]:--}
+ PR_ULCORNER=${altchar[l]:--}
+ PR_LLCORNER=${altchar[m]:--}
+ PR_LRCORNER=${altchar[j]:--}
+ PR_URCORNER=${altchar[k]:--}
+ fi
else
PR_SET_CHARSET=""
PR_SHIFT_IN=""
PR_URCORNER=""
fi
- if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
+ if zstyle -t ':prompt:ganneff' colors; then
if [[ -n "${BLUE}" ]] && [[ -n "${YELLOW}" ]]; then
# Two defined, so we assume someone already defined themself
# the colors. We just use them and not setup our own.
- for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
- eval PR_$color="%{${(P)color}%}"
- eval PR_BOLD_$color="%{$terminfo[bold]${(LP)color}%}"
+ for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK GREY; do
+ eval PR_$color='%{${(P)color}%}'
+ eval PR_BOLD_$color='%{$terminfo[bold]${(LP)color}%}'
done
PR_NO_COLOR="%{${reset_color}%}"
else
# Seems like colors are not defined, so set them up
- docolors
+ # This duplicates docolors from 01_Terminfo.zsh, but is here to have
+ # prompt_ganneff_setup not require anything else from my dotfiles
+ if autoload -Uz colors && colors 2>/dev/null ; then
+ for COLOR in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE BLACK GREY; do
+ eval PR_$COLOR='%{$fg_no_bold[${(L)COLOR}]%}'
+ eval PR_BOLD_$COLOR='%{$fg_bold[${(L)COLOR}]%}'
+ done
+ eval PR_NO_COLOR='%{$reset_color%}'
+ else
+ PR_BLUE=$'%{\e[1;34m%}'
+ PR_RED=$'%{\e[1;31m%}'
+ PR_GREEN=$'%{\e[1;32m%}'
+ PR_CYAN=$'%{\e[1;36m%}'
+ PR_WHITE=$'%{\e[1;37m%}'
+ PR_MAGENTA=$'%{\e[1;35m%}'
+ PR_YELLOW=$'%{\e[1;33m%}'
+ PR_NO_COLOR=$'%{\e[0m%}'
+ fi
fi
else
PR_BLUE=''
# The secondary prompt, printed when the shell needs more
# information to complete a command. %_ displays any shell constructs
# or quotation marks which are currently being processed.
- if zstyle -t ':prompt:ganneff' colors && [[ "$TERM" != dumb ]]; then
+ if zstyle -t ':prompt:ganneff' nicelines; then
PS2='${PR_CYAN}${PR_SHIFT_IN}${PR_HBAR}${PR_BLUE}${PR_HBAR}${PR_SHIFT_OUT}\
(${PR_GREEN}%_${PR_BLUE})\
${PR_SHIFT_IN}${PR_HBAR}${PR_CYAN}${PR_HBAR}${PR_SHIFT_OUT}${PR_NO_COLOR} '
# selection prompt used within a select loop.
PS3='?# '
# the execution trace prompt (setopt xtrace). default: '+%N:%i>'
- PS4='+%N:%i:%_> '
+ # Not changed if the option xtrace is on, assuming that a trace prompt is then
+ # already defined.
+ if [[ ${options[xtrace]} == off ]]; then
+ PS4='+%N:%i:%_> '
+ fi
if zstyle -t ':prompt:ganneff' vcs_info && \
is439 && autoload -Uz vcs_info && vcs_info; then
ganneff_prompt_token_default
ganneff_prompt_pre_default=(
- at ''
- battery ' '
- change-root ''
- date '${PR_BLUE}'
- history '${PR_GREEN}'
- host '${PR_RED}'
- jobs '${PR_CYAN}'
- newline ''
- path '${PR_MAGENTA}'
- percent ''
- rc '${PR_RED}'
- rc-always ''
- shell-level '${PR_RED}'
- time '${PR_BLUE}'
- user '${PR_BLUE}'
- vcs ''
- ulcorner '${PR_SHIFT_IN}'
- llcorner '${PR_SHIFT_IN}'
- urcorner '${PR_SHIFT_IN}'
- lrcorner '${PR_SHIFT_IN}'
- line '${PR_SHIFT_IN}'
- pts ''
- openbracket ''
- closebracket ''
- pipe ''
- space ''
- flexline '${PR_SHIFT_IN}'
+ at ''
+ battery ' '
+ change-root ''
+ date '${PR_BLUE}'
+ history '${PR_GREEN}'
+ host '${PR_RED}'
+ jobs '${PR_CYAN}'
+ newline ''
+ path '${PR_MAGENTA}'
+ percent ''
+ rc '${PR_RED}'
+ rc-always ''
+ shell-level '${PR_RED}'
+ time '${PR_BLUE}'
+ user '${PR_BLUE}'
+ vcs ''
+ ulcorner '${PR_SHIFT_IN}'
+ llcorner '${PR_SHIFT_IN}'
+ urcorner '${PR_SHIFT_IN}'
+ lrcorner '${PR_SHIFT_IN}'
+ line '${PR_SHIFT_IN}'
+ pts ''
+ privileges ''
+ openparentheses ''
+ closeparentheses ''
+ openbracket ''
+ closebracket ''
+ openbraces ''
+ closebraces ''
+ openanglebracket ''
+ closeanglebracket ''
+ pipe ''
+ space ''
+ colon ''
+ flexline '${PR_SHIFT_IN}'
)
+
ganneff_prompt_post_default=(
at ''
battery ''
lrcorner '${PR_SHIFT_OUT}'
line '${PR_SHIFT_OUT}'
pts ''
+ privileges ''
+ openparentheses ''
+ closeparentheses ''
openbracket ''
closebracket ''
+ openbraces ''
+ closebraces ''
+ openanglebracket ''
+ closeanglebracket ''
pipe ''
space ''
+ colon ''
flexline '${PR_SHIFT_OUT}'
)
jobs '[%j running job(s)] '
newline $'\n'
path '%40<..<%~%<<'
- percent '% # '
+ percent '%# '
rc '%(?..%? )'
rc-always '%?'
shell-level '%(2L.%L.)'
urcorner '${PR_URCORNER}'
lrcorner '${PR_LRCORNER}'
line '${PR_HBAR}'
- pts ':%y'
- openbracket '('
- closebracket ')'
+ pts '%y'
+ privileges '%#'
+ openparentheses '('
+ closeparentheses ')'
+ openbracket '['
+ closebracket ']'
+ openbraces '{'
+ closebraces '}'
+ openanglebracket '<'
+ closeanglebracket '>'
pipe '|'
space ' '
+ colon ':'
flexline 'PR_FLEXLINE'
)
functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_ganneff_winch}
prompt_ganneff_winch"
+
+ # Should we "ring the bell" when a command finishes?
+ zstyle -s ':prompt:ganneff' longbell _prompt_ganneff_belltime || \
+ _prompt_ganneff_belltime=600
+ if [[ ${_prompt_ganneff_belltime} -gt 0 ]]; then
+ # New shell, initialize the timestamp once
+ _prompt_ganneff_timestamp=${EPOCHSECONDS}
+ typeset -ga _prompt_ganneff_ignore
+ zstyle -a ':prompt:ganneff' bell_ignore _prompt_ganneff_ignore || \
+ _prompt_ganneff_ignore=( '$EDITOR' '$PAGER' sleep man ssh zsh )
+ # In case the commands to ignore include variables (say $EDITOR), we want to
+ # store them once as variable - and once the variable expanded.
+ for (( i = 1; i <= ${#_prompt_ganneff_ignore}; i++ )) do
+ if (( ${${_prompt_ganneff_ignore[$i]}[(i)$]} <= ${#_prompt_ganneff_ignore[$i]} )); then
+ _prompt_ganneff_ignore+=(${(e)${_prompt_ganneff_ignore[$i]}})
+ fi
+ done
+ add-zsh-hook preexec prompt_ganneff_preexec
+ fi
+}
+
+# right before we begin to execute something, store the time it started at
+prompt_ganneff_preexec() {
+ _prompt_ganneff_timestamp=${EPOCHSECONDS}
+ _prompt_ganneff_lastcmd=${2}
}
prompt_ganneff_precmd () {
setopt nolocaltraps
zstyle -t ':prompt:ganneff' vcs_info && vcs_info
- local -a left_items right_items
- left_items=(ulcorner line openbracket user at host pts closebracket line history flexline
- openbracket path closebracket line urcorner newline
- llcorner line rc openbracket time closebracket line vcs line change-root pipe space)
+ local -a left_items right_items drop_words
+
+ left_items=(ulcorner line openparantheses user at host colon pts closeparantheses line history
+ line shell-level line flexline openparentheses path closeparentheses line urcorner newline
+ llcorner line rc openparentheses time closeparentheses line vcs line change-root pipe space)
PR_PS1=""; nomore=0
ganneff_prompt_addto PS1 full "${left_items[@]}"
if zstyle -T ":prompt:ganneff:right:setup" use-rprompt; then
- right_items=(space pipe line openbracket date closebracket line lrcorner)
+ right_items=(pipe line openparentheses date closeparentheses line lrcorner)
ganneff_prompt_addto RPS1 full "${right_items[@]}"
fi
# Now a kind-of-hack to reduce the prompt when we run out of space.
promptsize=${#PR_PS1}
if [[ ${promptsize} -lt ${TERMWIDTH} ]]; then
- # the q here should be ${PR_HBAR}, but for some reason zsh didn't like me,
- # so meh
- if zstyle -t ':prompt:ganneff' nicelines && [[ "$TERM" != dumb ]] \
- && [[ "$TERM" != "linux" ]]; then
- PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..q.)}"
- else
- PR_FLEXLINE="${(l.(($TERMWIDTH - $promptsize ))..-.)}"
- fi
+ PR_FLEXLINE=${${(el.(($TERMWIDTH - $promptsize ))..X.)}//X/$PR_HBAR}
else
# Small size prompt is needed
- left_items=(ulcorner line openbracket user at host closebracket line openbracket path closebracket newline
- llcorner line rc openbracket time closebracket line vcs line pipe space)
+ left_items=(ulcorner line openparentheses user at host closeparentheses line openparentheses
+ path closeparentheses newline
+ llcorner line rc openparentheses time closeparentheses line vcs line pipe space)
ganneff_prompt_addto PS1 small "${left_items[@]}"
# And with a small prompt, we don't show the right size at all.
RPS1=""
fi
+
+ # Should we "ring the bell" when a command finishes?
+ if (( _prompt_ganneff_timestamp )); then
+ ran_long=$(( ${EPOCHSECONDS} - ${_prompt_ganneff_timestamp} >= ${_prompt_ganneff_belltime} ))
+ if (( ran_long )); then
+ has_ignored_cmd=0
+ drop_words=(builtin command nocorrect noglob)
+ for cmd in ${(s:;:)_prompt_ganneff_lastcmd//|/;}; do
+ words=(${(z)cmd})
+ util=${words[1]}
+ if (( ${drop_words[(i)$util]} <= ${#drop_words} )); then
+ util=${words[2]}
+ fi
+ if (( ${_prompt_ganneff_ignore[(i)$util]} <= ${#_prompt_ganneff_ignore} )); then
+ has_ignored_cmd=1
+ break
+ fi
+ done
+ if (( ! ${has_ignored_cmd} )); then
+ print -n "\a"
+ fi
+ fi
+ fi
}
prompt_ganneff_length () {
emulate -L zsh
local target="$1"
local size="$2"
- local lr it apre apost new v
+ local lr it apre apost new v prefunc
local -a items
shift
shift
typeset -g "${target}="
for it in "${items[@]}"; do
zstyle -s ":prompt:ganneff:${lr}:items:$it" pre apre \
+ || zstyle -s ":prompt:ganneff:extra:$it" pre apre \
|| apre=${ganneff_prompt_pre_default[$it]}
zstyle -s ":prompt:ganneff:${lr}:items:$it" post apost \
+ || zstyle -s ":prompt:ganneff:extra:$it" post apost \
|| apost=${ganneff_prompt_post_default[$it]}
zstyle -s ":prompt:ganneff:${lr}:items:$it" token new \
+ || zstyle -s ":prompt:ganneff:extra:$it" token new \
|| new=${ganneff_prompt_token_default[$it]}
+
+ # Now check if there is the wish for a precmd function and if so,
+ # run it
+ zstyle -s ":prompt:ganneff:extra:$it" precmd prefunc
+ if [[ -n "${prefunc}" ]]; then
+ ${prefunc} || true
+ fi
+
typeset -g "${target}=${(P)target}${apre}"
# Store the expanded value in PR_PS1, as we use that for length calculations
[[ $it == "newline" ]] && nomore=1
prompt_ganneff_battery() {
zstyle -s ':prompt:ganneff' battery pr_battery
case $pr_battery in
- ibam)
- local ACPIDATA=$(ibam --percentbattery 2>/dev/null || echo "")
+ ibam)
+ local ACPIDATA=$(ibam --percentbattery 2>/dev/null || echo "")
PERCENT=${${ACPIDATA[(f)1]}[(w)-2]}
;;
acpi)
fi
}
+is439(){
+ [[ $ZSH_VERSION == 4.3.<9->* || $ZSH_VERSION == 4.<4->* \
+ || $ZSH_VERSION == <5->* ]] && return 0
+ return 1
+}
+
prompt_ganneff_setup "$@"