zshrc: New prompt: Fix wrong logic for user name colouring
[grml-etc-core.git] / etc / zsh / zshrc
index 305155e..4fa913e 100644 (file)
@@ -1288,8 +1288,8 @@ function prompt_grml_help () {
     cat <<__EOF0__
   prompt grml
 
-    This is the prompt as used by the grml-live system <http://grml.org>.
-    It is a rather simple one-line prompt, that by default looks like this:
+    This is the prompt as used by the grml-live system <http://grml.org>. It is
+    a rather simple one-line prompt, that by default looks something like this:
 
         <user>@<host> <current-working-directory>[ <vcs_info-data>]%
 
@@ -1305,25 +1305,22 @@ function prompt_grml_help () {
           used before and after the actual item.
 
     The available items are: rc, rc-always, change-root, user, at, host, path,
-    vcs, percent, sad-smiley.
+    vcs, percent, sad-smiley, battery.
 
     The actual configuration is done via zsh's \`zstyle' mechanism. The
     context, that is used while looking up styles is:
 
-        ':prompt:grml:<sub-context>'
+        ':prompt:grml:<left-or-right>:<subcontext>'
 
-    Here <sub-context> is either 'items:<item>' or 'setup'. The available
-    styles in the \`setup' context are: use-rprompt, items. For example,
-    default \`items' style could be configured like this:
-
-        zstyle ':prompt:grml:setup' items user at host path \\
-                                          vcs percent
+    Here <left-or-right> is either \`left' or \`right', signifying whether the
+    style should affect the left or the right prompt. <subcontext> is either
+    \`setup' or 'items:<item>', where \`<item>' is one of the available items.
 
     The styles:
 
         - use-rprompt (boolean): If \`true' (the default), print a sad smiley
-          in $RPROMPT if the last command a returned non-successful error
-          code.
+          in $RPROMPT if the last command a returned non-successful error code.
+          (This in only valid if <left-or-right> is "right"; ignored otherwise)
 
         - items (list): The list of items used in the prompt. If \`vcs' is
           present in the list, the theme's code invokes \`vcs_info'
@@ -1334,7 +1331,7 @@ function prompt_grml_help () {
     following would cause the user name to be printed in red instead of the
     default blue:
 
-        zstyle ':prompt:grml:items:user' pre '%F{red}'
+        zstyle ':prompt:grml:*:items:user' pre '%F{red}'
 
     Note, that the \`post' style may remain at its default value, because its
     default value is '%f', which turns the foreground text attribute off (which
@@ -1342,10 +1339,189 @@ function prompt_grml_help () {
 __EOF0__
 }
 
+function grml_prompt_setup () {
+    emulate -L zsh
+    autoload -Uz vcs_info
+    autoload -Uz add-zsh-hook
+    add-zsh-hook precmd prompt_$1_precmd
+}
+
 function prompt_grml_setup () {
+    grml_prompt_setup grml
+}
+
+function prompt_grml-chroot_setup () {
+    grml_prompt_setup grml-chroot
+}
+
+function prompt_grml-large_setup () {
+    grml_prompt_setup grml-large
+}
+
+typeset -gA grml_prompt_pre_default \
+            grml_prompt_post_default \
+            grml_prompt_token_default
+
+grml_prompt_pre_default=(
+    rc                '%F{red}'
+    rc-always         ''
+    change-root       ''
+    user              '%B%F{blue}'
+    at                ''
+    host              ''
+    path              '%b'
+    vcs               ''
+    percent           ''
+    sad-smiley        ''
+    battery           ' '
+    newline           ''
+    jobs              '%F{cyan}'
+    history           '%F{green}'
+    date              '%F{blue}'
+    time              '%F{blue}'
+    shell-level       '%F{red}'
+    grml-chroot       '%F{red}'
+)
+
+grml_prompt_post_default=(
+    rc                '%f'
+    rc-always         ''
+    change-root       ''
+    user              '%f%b'
+    at                ''
+    host              ''
+    path              '%B'
+    vcs               ''
+    percent           ''
+    sad-smiley        ''
+    battery           ''
+    newline           ''
+    jobs              '%f'
+    history           '%f'
+    date              '%f'
+    time              '%f'
+    shell-level       '%f'
+    grml-chroot       '%f '
+)
+
+grml_prompt_token_default=(
+    rc                '%(?..%? )'
+    rc-always         '%?'
+    change-root       'debian_chroot'
+    user              '%n'
+    at                '@'
+    host              '%m '
+    path              '%40<..<%~%<< '
+    vcs               '0'
+    percent           '%% '
+    sad-smiley        '%(?..:()'
+    battery           'PERCENT'
+    newline           $'\n'
+    jobs              '[%j running job(s)] '
+    history           '{history#%!} '
+    date              '%D{%Y-%m-%d}'
+    time              '%D{%H:%M:%S} '
+    shell-level       '%(3L.+ .)'
+    grml-chroot       'GRML_CHROOT'
+)
+
+function grml_typeset_and_wrap () {
+    emulate -L zsh
+    local target="$1"
+    local new="$2"
+    local left="$3"
+    local right="$4"
+
+    if (( ${+parameters[$new]} )); then
+        typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
+    fi
+}
+
+function grml_prompt_addto () {
+    emulate -L zsh
+    local target="$1"
+    local lr it apre apost new v
+    local -a items
+    shift
+
+    [[ $target == PS1 ]] && lr=left || lr=right
+    zstyle -a ":prompt:${grmltheme}:${lr}:setup" items items || items=( "$@" )
+    typeset -g "${target}="
+    for it in "${items[@]}"; do
+        zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" pre apre \
+            || apre=${grml_prompt_pre_default[$it]}
+        zstyle -s ":prompt:grml:${grmltheme}:${lr}:$it" post apost \
+            || apost=${grml_prompt_post_default[$it]}
+        zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
+            || new=${grml_prompt_token_default[$it]}
+        typeset -g "${target}=${(P)target}${apre}"
+        case $it in
+            battery)
+                grml_typeset_and_wrap $target $new '' ''
+                ;;
+            change-root)
+                grml_typeset_and_wrap $target $new '(' ')'
+                ;;
+            grml-chroot)
+                if [[ -n ${(P)new} ]]; then
+                    typeset -g "${target}=${(P)target}(CHROOT)"
+                fi
+                ;;
+            vcs)
+                v="vcs_info_msg_${new}_"
+                if (( ! vcscalled )); then
+                    vcs_info
+                    vcscalled=1
+                fi
+                if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
+                    typeset -g "${target}=${(P)target}${(P)v}"
+                fi
+                ;;
+            *) typeset -g "${target}=${(P)target}${new}" ;;
+        esac
+        typeset -g "${target}=${(P)target}${apost}"
+    done
 }
 
 function prompt_grml_precmd () {
+    emulate -L zsh
+    local grmltheme=grml
+    local -a left_items right_items
+    left_items=(rc change-root user at host path vcs percent)
+    right_items=(sad-smiley)
+
+    prompt_grml_precmd_worker
+}
+
+function prompt_grml-chroot_precmd () {
+    emulate -L zsh
+    local grmltheme=grml-chroot
+    local -a left_items right_items
+    left_items=(grml-chroot user at host path percent)
+    right_items=()
+
+    prompt_grml_precmd_worker
+}
+
+function prompt_grml-large_precmd () {
+    emulate -L zsh
+    local grmltheme=grml-large
+    local -a left_items right_items
+    left_items=(rc jobs history shell-level change-root time date newline
+                user at host path vcs percent)
+    right_items=(sad-smiley)
+
+    prompt_grml_precmd_worker
+}
+
+function prompt_grml_precmd_worker () {
+    emulate -L zsh
+    local -i vcscalled=0
+
+    grml_prompt_addto PS1 "${left_items[@]}"
+    if zstyle -T ":prompt:${grmltheme}:right:setup" use-rprompt; then
+        grml_prompt_addto RPS1 "${right_items[@]}"
+    fi
 }
 
 # set prompt
@@ -1355,9 +1531,24 @@ if zrcautoload promptinit && promptinit 2>/dev/null ; then
     # Since we define the required functions in here and not in files in
     # $fpath, we need to stick the theme's name into `$prompt_themes'
     # ourselves, since promptinit does not pick them up otherwise.
-    prompt_themes+=( grml )
+    prompt_themes+=( grml grml-chroot grml-large )
     # Also, keep the array sorted...
     prompt_themes=( "${(@on)prompt_themes}" )
+
+    if [[ $BATTERY -gt 0 ]]; then
+        zstyle ':prompt:grml:right:setup' items sad-smiley battery
+        add-zsh-hook precmd battery
+    fi
+    if [[ "$TERM" == dumb ]] ; then
+        for i in rc user path jobs history date time shell-level; do
+            zstyle ":prompt:grml(|-large|-chroot):*:items:$i" pre ''
+            zstyle ':prompt:grml(|-large|-chroot):*:items:$i' post ''
+        done
+        unset i
+        zstyle ':prompt:grml(|-large|-chroot):right:setup' use-rprompt false
+    elif (( EUID == 0 )); then
+        zstyle ':prompt:grml(|-large|-chroot):*:items:user' pre '%F{red}'
+    fi
 else
     print 'Notice: no promptinit available :('
 fi
@@ -1385,30 +1576,7 @@ function info_print () {
     printf '%s' "${esc_end}"
 }
 
-# TODO: revise all these NO* variables and especially their documentation
-#       in zsh-help() below.
-is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
-    [[ $NOPRECMD -gt 0 ]] && return 0
-    # update VCS information
-    (( ${+functions[vcs_info]} )) && vcs_info
-
-    if [[ $TERM == screen* ]] ; then
-        if [[ -n ${vcs_info_msg_1_} ]] ; then
-            ESC_print ${vcs_info_msg_1_}
-        else
-            ESC_print "zsh"
-        fi
-    fi
-    # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
-    if [[ ${DONTSETRPROMPT:-} -eq 0 ]] ; then
-        if [[ $BATTERY -gt 0 ]] ; then
-            # update battery (dropped into $PERCENT) information
-            battery
-            RPROMPT="%(?..:() ${PERCENT}"
-        else
-            RPROMPT="%(?..:() "
-        fi
-    fi
+function grml_reset_screen_title () {
     # adjust title of xterm
     # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
     [[ ${NOTITLE:-} -gt 0 ]] && return 0
@@ -1419,6 +1587,22 @@ is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
     esac
 }
 
+function grml_vcs_to_screen_title () {
+    if [[ $TERM == screen* ]] ; then
+        if [[ -n ${vcs_info_msg_1_} ]] ; then
+            ESC_print ${vcs_info_msg_1_}
+        else
+            ESC_print "zsh"
+        fi
+    fi
+}
+
+zrcautoload add-zsh-hook || add-zsh-hook () { :; }
+if [[ $NOPRECMD -gt 0 ]]; then
+    add-zsh-hook precmd grml_reset_screen_title
+    add-zsh-hook precmd grml_vcs_to_screen_title
+fi
+
 # preexec() => a function running before every command
 is4 && [[ $NOPRECMD -eq 0 ]] && \
 preexec () {