zshrc: New prompt: Move more precmd() code to hook fncs
[grml-etc-core.git] / etc / zsh / zshrc
index bec03d4..75d3e99 100644 (file)
@@ -1284,9 +1284,163 @@ function command_not_found_handler() {
     return 1
 }
 
+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:
+
+        <user>@<host> <current-working-directory>[ <vcs_info-data>]%
+
+    The prompt itself integrates with zsh's prompt themes system (as you are
+    witnessing right now) and is configurable to a certain degree. In
+    particular, these aspects are customisable:
+
+        - The items used in the prompt (e.g. you can remove \`user' from
+          the list of activated items, which will cause the user name to
+          be omitted from the prompt string).
+
+        - The attributes used with the items are customisable via strings
+          used before and after the actual item.
+
+    The available items are: rc, rc-always, change-root, user, at, host, path,
+    vcs, percent, sad-smiley.
+
+    The actual configuration is done via zsh's \`zstyle' mechanism. The
+    context, that is used while looking up styles is:
+
+        ':prompt:grml:<sub-context>'
+
+    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
+
+    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.
+
+        - items (list): The list of items used in the prompt. If \`vcs' is
+          present in the list, the theme's code invokes \`vcs_info'
+          accordingly. Default: rc user change-root at host path vcs precent
+
+    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:
+
+        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
+    is exactly, what is still required with the new \`pre' value).
+__EOF0__
+}
+
+function prompt_grml_setup () {
+    emulate -L zsh
+    autoload -Uz vcs_info
+    autoload -Uz add-zsh-hook
+    add-zsh-hook precmd prompt_grml_precmd
+}
+
+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        ''
+)
+
+grml_prompt_post_default=(
+    rc                '%f'
+    rc-always         ''
+    change-root       ''
+    user              '%f%b'
+    at                ''
+    host              ' '
+    path              ' %B'
+    vcs               ''
+    percent           ' '
+    sad-smiley        ''
+)
+
+grml_prompt_token_default=(
+    rc                '%(?..%? )'
+    rc-always         '%?'
+    change-root       'debian_chroot'
+    user              '%n'
+    at                '@'
+    host              '%m'
+    path              '%40<..<%~%<<'
+    vcs               '0'
+    percent           '%%'
+    sad-smiley        '%(?..:()'
+)
+
+function prompt_grml_precmd () {
+    emulate -L zsh
+    setopt extendedglob
+    local it apre apost new v
+    local -a items
+
+    zstyle -a ':prompt:grml:setup' items items \
+        || items=( rc change-root user at host path vcs percent )
+    PS1=''
+    for it in "${items[@]}"; do
+        zstyle -s ":prompt:grml:items:$it" pre apre \
+            || apre=${grml_prompt_pre_default[$it]}
+        zstyle -s ":prompt:grml:items:$it" post apost \
+            || apost=${grml_prompt_post_default[$it]}
+        zstyle -s ":prompt:grml:items:$it" token new \
+            || new=${grml_prompt_token_default[$it]}
+        PS1="${PS1}${apre}"
+        case $it in
+            change-root)
+                (( ${+parameters[$new]} )) && PS1="${PS1}(${(P)new})"
+                ;;
+            vcs)
+                v="vcs_info_msg_${new}_"
+                vcs_info
+                if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
+                    PS1="${PS1}${(P)v}"
+                fi
+                ;;
+            *) PS1="${PS1}${new}" ;;
+        esac
+        PS1="${PS1}${apost}"
+    done
+    if zstyle -t ':prompt:grml:setup' use-rprompt; then
+        zstyle -s ":prompt:grml:items:sad-smiley" token new \
+            || new=${grml_prompt_token_default[sad-smiley]}
+        RPS1="$new"
+    fi
+}
+
 # set prompt
 if zrcautoload promptinit && promptinit 2>/dev/null ; then
     promptinit # people should be able to use their favourite prompt
+
+    # 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 )
+    # Also, keep the array sorted...
+    prompt_themes=( "${(@on)prompt_themes}" )
 else
     print 'Notice: no promptinit available :('
 fi
@@ -1314,13 +1468,18 @@ 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
+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
+    case $TERM in
+        (xterm*|rxvt*)
+            set_title ${(%):-"%n@%m: %~"}
+            ;;
+    esac
+}
 
+function grml_vcs_to_screen_title () {
     if [[ $TERM == screen* ]] ; then
         if [[ -n ${vcs_info_msg_1_} ]] ; then
             ESC_print ${vcs_info_msg_1_}
@@ -1328,6 +1487,17 @@ is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
             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
+
+# TODO: revise all these NO* variables and especially their documentation
+#       in zsh-help() below.
+is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
     # just use DONTSETRPROMPT=1 to be able to overwrite RPROMPT
     if [[ ${DONTSETRPROMPT:-} -eq 0 ]] ; then
         if [[ $BATTERY -gt 0 ]] ; then
@@ -1338,14 +1508,6 @@ is4 && [[ $NOPRECMD -eq 0 ]] && precmd () {
             RPROMPT="%(?..:() "
         fi
     fi
-    # adjust title of xterm
-    # see http://www.faqs.org/docs/Linux-mini/Xterm-Title.html
-    [[ ${NOTITLE:-} -gt 0 ]] && return 0
-    case $TERM in
-        (xterm*|rxvt*)
-            set_title ${(%):-"%n@%m: %~"}
-            ;;
-    esac
 }
 
 # preexec() => a function running before every command