about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Functions/Misc/colors132
-rw-r--r--Functions/Prompts/promptinit154
3 files changed, 195 insertions, 95 deletions
diff --git a/ChangeLog b/ChangeLog
index 0dbfc405f..b1766e856 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2000-06-11  Bart Schaefer  <schaefer@zsh.org>
 
+	* 11866: Functions/Misc/colors, Functions/Prompts/promptinit:  Set
+	up color/colour assoc arrays to map the full range of ANSI text
+	properties; preserve more state during themed prompt previewing.
+
 	* Alexandre: 11864: Src/Zle/complist.c: Shift an array the opposite
 	way to fix colored listings crash.
 
diff --git a/Functions/Misc/colors b/Functions/Misc/colors
index 8ce2326e6..0a31afcf6 100644
--- a/Functions/Misc/colors
+++ b/Functions/Misc/colors
@@ -1,67 +1,79 @@
-# Put standard ANSI color codes in environment for easy use
+# Put standard ANSI color codes in shell parameters for easy use.
+# Note that some terminals do not support all combinations.
 
-reset_color="$(echo -n '\e[0m')"
-bold_color="$(echo -n '\e[1m')"
+typeset -Ag color colour
+
+color=(
+# Attribute codes:
+  00 none
+  01 bold
+  02 faint                  22 normal
+  03 standout               23 no-standout
+  04 underline              24 no-underline
+  05 blink                  25 no-blink
+  07 reverse                27 no-reverse
+  08 conceal
+
+# Text color codes:
+  30 black                  40 bg-black
+  31 red                    41 bg-red
+  32 green                  42 bg-green
+  33 yellow                 43 bg-yellow
+  34 blue                   44 bg-blue
+  35 magenta                45 bg-magenta
+  36 cyan                   46 bg-cyan
+  37 white                  47 bg-white
+  39 default                49 bg-default
+)
+
+# A word about black and white:  The "normal" shade of white is really a
+# very pale grey on many terminals; to get truly white text, you have to
+# use bold white, and to get a truly white background you have to use
+# bold reverse white bg-xxx where xxx is your desired foreground color
+# (and which means the foreground is also bold).
+
+# Map in both directions; could do this with e.g. ${(k)colors[(i)normal]},
+# but it's clearer to include them all both ways.
+
+local k
+for k in ${(k)color}; do color[${color[$k]}]=$k; done
+
+# Add "fg-" keys for all the text colors, for clarity.
+
+for k in ${color[(I)3?]}; do color[fg-${color[$k]}]=$k; done
+
+# This is inaccurate, but the prompt theme system needs it.
+
+color[grey]=${color[black]}
+color[fg-grey]=${color[grey]}
+color[bg-grey]=${color[bg-black]}
+
+# Assistance for the color-blind.
+
+colour=(${(kv)color})	# A case where ksh namerefs would be useful ...
+
+# The following are terminal escape sequences used by colored prompt themes.
+
+local lc=$'\e[' rc=m	# Standard ANSI terminal escape values
+
+typeset -Hg reset_color bold_color
+reset_color="$lc${color[none]}$rc"
+bold_color="$lc${color[bold]}$rc"
 
 # Foreground
 
-fg_grey="$(echo -n '\e[30m')"
-fg_red="$(echo -n '\e[31m')"
-fg_green="$(echo -n '\e[32m')"
-fg_yellow="$(echo -n '\e[33m')"
-fg_blue="$(echo -n '\e[34m')"
-fg_magenta="$(echo -n '\e[35m')"
-fg_cyan="$(echo -n '\e[36m')"
-fg_white="$(echo -n '\e[37m')"
-
-fg_no_bold_grey="$(echo -n '\e[0;30m')"
-fg_no_bold_red="$(echo -n '\e[0;31m')"
-fg_no_bold_green="$(echo -n '\e[0;32m')"
-fg_no_bold_yellow="$(echo -n '\e[0;33m')"
-fg_no_bold_blue="$(echo -n '\e[0;34m')"
-fg_no_bold_magenta="$(echo -n '\e[0;35m')"
-fg_no_bold_cyan="$(echo -n '\e[0;36m')"
-fg_no_bold_white="$(echo -n '\e[0;37m')"
-
-fg_bold_grey="$(echo -n '\e[1;30m')"
-fg_bold_red="$(echo -n '\e[1;31m')"
-fg_bold_green="$(echo -n '\e[1;32m')"
-fg_bold_yellow="$(echo -n '\e[1;33m')"
-fg_bold_blue="$(echo -n '\e[1;34m')"
-fg_bold_magenta="$(echo -n '\e[1;35m')"
-fg_bold_cyan="$(echo -n '\e[1;36m')"
-fg_bold_white="$(echo -n '\e[1;37m')"
+typeset -AHg fg fg_bold fg_no_bold
+for k in ${(v)color[(I)fg-*]}; do
+    fg[${color[$k]}]="$lc$k$rc"
+    fg_bold[${color[$k]}]="$lc${color[bold]};$k$rc"
+    fg_no_bold[${color[$k]}]="$lc${color[normal]};$k$rc"
+done
 
 # Background
 
-bg_grey="$(echo -n '\e[40m')"
-bg_red="$(echo -n '\e[41m')"
-bg_green="$(echo -n '\e[42m')"
-bg_yellow="$(echo -n '\e[43m')"
-bg_blue="$(echo -n '\e[44m')"
-bg_magenta="$(echo -n '\e[45m')"
-bg_cyan="$(echo -n '\e[46m')"
-bg_white="$(echo -n '\e[47m')"
-
-bg_no_bold_grey="$(echo -n '\e[0;40m')"
-bg_no_bold_red="$(echo -n '\e[0;41m')"
-bg_no_bold_green="$(echo -n '\e[0;42m')"
-bg_no_bold_yellow="$(echo -n '\e[0;43m')"
-bg_no_bold_blue="$(echo -n '\e[0;44m')"
-bg_no_bold_magenta="$(echo -n '\e[0;45m')"
-bg_no_bold_cyan="$(echo -n '\e[0;46m')"
-bg_no_bold_white="$(echo -n '\e[0;47m')"
-
-bg_bold_grey="$(echo -n '\e[1;40m')"
-bg_bold_red="$(echo -n '\e[1;41m')"
-bg_bold_green="$(echo -n '\e[1;42m')"
-bg_bold_yellow="$(echo -n '\e[1;43m')"
-bg_bold_blue="$(echo -n '\e[1;44m')"
-bg_bold_magenta="$(echo -n '\e[1;45m')"
-bg_bold_cyan="$(echo -n '\e[1;46m')"
-bg_bold_white="$(echo -n '\e[1;47m')"
-
-# Stop these screwing the environment listing up
-bg_zzzz=$reset_color
-fg_zzzz=$reset_color
-bold_zzzz=$reset_color
+typeset -AHg bg bg_bold bg_no_bold
+for k in ${(v)color[(I)bg-*]}; do
+    bg[${color[$k]}]="$lc$k$rc"
+    bg_bold[${color[$k]}]="$lc${color[bold]};$k$rc"
+    bg_no_bold[${color[$k]}]="$lc${color[normal]};$k$rc"
+done
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index 2cf2a4674..a07650500 100644
--- a/Functions/Prompts/promptinit
+++ b/Functions/Prompts/promptinit
@@ -1,27 +1,32 @@
-# zsh prompt themes extension
-#
-# Load with `autoload -U promptinit; promptinit'.
+##
+## zsh prompt themes extension
+## by Adam Spiers <adam@spiers.net>
+##
+## Load with `autoload -U promptinit; promptinit'.
+## Type `prompt -h' for help.
+##
 
 prompt_themes=()
 typeset -gU prompt_themes
-typeset -g prompt_theme
+typeset -g prompt_theme >/dev/null
 
 promptinit () {
   emulate -L zsh
-  local ppath='' name
+  setopt extendedglob
+  local ppath='' name theme
 
   # Autoload all prompt_*_setup functions in fpath
-  for theme in $fpath/prompt_*_setup(N); do
+  for theme in $^fpath/prompt_*_setup(N); do
     if [[ $theme == */prompt_(#b)(*)_setup ]]; then
       name="$match[1]"
       if [[ -r "$theme" ]]; then
-        prompt_themes=($name $prompt_themes)
+        prompt_themes=($prompt_themes $name)
         autoload -U prompt_${name}_setup
       else
-        print "Couldn't find theme $theme" 
+        print "Couldn't read file $theme containing theme $name."
       fi
     else
-      print "eh?"
+      print "Eh?  Mismatch between glob patterns in promptinit."
     fi
   done
 
@@ -30,29 +35,86 @@ promptinit () {
   colors
 
   # Variables common to all prompt styles
-  prompt_newline=$(echo -ne "\n%{\r%}")
+  prompt_newline=$'\n%{\r%}'
 }
 
-prompt () {
+prompt_preview_safely() {
+  print $reset_color
+  if [[ -z "$prompt_themes[(r)$1]" ]]; then
+    print "Unknown theme: $1"
+    return
+  fi
+
+  local -a psv; psv=($psvar); local -a +h psvar; psvar=($psv) # Ick
+  local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1
+  trap "${$(functions precmd):-:} ; ${$(functions preexec):-:}" 0
+
+  # The next line is a bit ugly.  It (perhaps unnecessarily)
+  # runs the prompt theme setup function to ensure that if
+  # the theme has a _preview function that it's been autoloaded.
+  prompt_${1}_setup
+
+  if typeset +f prompt_${1}_preview >&/dev/null; then
+    prompt_${1}_preview "$@[2,-1]"
+  else
+    prompt_preview_theme "$@"
+  fi
+}
+
+set_prompt() {
+  emulate -L zsh
   local opt preview theme usage old_theme
 
   usage='Usage: prompt <options>
 Options:
+    -c              Show currently selected theme and parameters
     -l              List currently available prompt themes
     -p [<themes>]   Preview given themes (defaults to all)
     -h [<theme>]    Display help (for given theme)
     -s <theme>      Set and save theme
-    <theme>         Switch to new theme immediately (changes not saved)'
+    <theme>         Switch to new theme immediately (changes not saved)
 
-  getopts "hlps" opt
+Use prompt -h <theme> for help on specific themes.'
+
+  getopts "chlps" opt
+  case "$opt" in
+    (h|p)
+      setopt localtraps
+      if [[ -z "$prompt_theme[1]" ]]; then
+        # Not using a prompt theme; save settings
+        local -a psv; psv=($psvar); local -a +h psvar; psvar=($psv) # Ick
+	local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1
+	trap "${$(functions precmd):-:} ; ${$(functions preexec):-:}" 0
+      else
+        trap 'prompt_${prompt_theme[1]}_setup "${(@)prompt_theme[2,-1]}"' 0
+      fi
+      ;;
+  esac
   case "$opt" in
+    c) if (( $+prompt_theme )); then
+         print -n "Current prompt theme"
+         (( $#prompt_theme > 1 )) && print -n " with parameters"
+         print " is:\n  $prompt_theme"
+       else
+         print "Current prompt is not a theme."
+       fi
+       return
+       ;;
     h) if [[ -n "$2" && -n $prompt_themes[(r)$2] ]]; then
+         if functions prompt_$2_setup >/dev/null; then
+	   # The next line is a bit ugly.  It (perhaps unnecessarily)
+	   # runs the prompt theme setup function to ensure that if
+	   # the theme has a _help function that it's been autoloaded.
+	   prompt_$2_setup
+	 fi
          if functions prompt_$2_help >/dev/null; then
-	   print "Help for $2 theme:\n"
+           print "Help for $2 theme:\n"
            prompt_$2_help
          else
-           print "No help available for $2 theme"
+           print "No help available for $2 theme."
          fi
+         print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'"
+         print "to try it out, and \`prompt -s $2' to use it in future sessions."
        else
          print "$usage"
        fi
@@ -61,24 +123,13 @@ Options:
        print $prompt_themes
        return
        ;;
-    p) if (( ! $+prompt_theme )); then
-         print "Cannot preview; current prompt is non-themeable and would"
-	 print "be destroyed."
-	 return
-       fi
-       preview=( $prompt_themes )
-       [[ -n "$2" && -n $prompt_themes[(r)$2] ]] && preview=( $*[2,-1] )
+    p) preview=( $prompt_themes )
+       (( $#* > 1 )) && preview=( "$@[2,-1]" )
        for theme in $preview; do
-         [[ $theme == $prompt_theme[1] ]] && continue
-         print "\nTheme: $theme"
-         prompt_${theme}_setup
-	 precmd
-	 print -n -P "${PS1}"
-	 preexec
-	 print "command arg1 arg2 ... argn"
+         [[ "$theme" == "$prompt_theme[*]" ]] && continue
+         prompt_preview_safely "$=theme"
        done
-       print
-       prompt_${prompt_theme}_setup
+       print $reset_color
        ;;
     s) print "Set and save not yet implemented.  Please ensure your ~/.zshrc"
        print "contains something similar to the following:\n"
@@ -86,12 +137,21 @@ Options:
        print "  promptinit"
        print "  prompt $*[2,-1]"
        ;;
-    *) if [[ -z "$1" || -z $prompt_themes[(r)$1] ]]; then
+    *) if [[ "$1" == 'random' ]]; then
+         local random_themes
+         if (( $#* == 1 )); then
+           random_themes=( $prompt_themes )
+         else
+           random_themes=( "$@[2,-1]" )
+         fi
+         local i=$(( ( $RANDOM % $#random_themes ) + 1 ))
+         argv=( "${=random_themes[$i]}" )
+       fi
+       if [[ -z "$1" || -z $prompt_themes[(r)$1] ]]; then
          print "$usage"
          return
        fi
-       prompt_$1_setup "$*[2,-1]"
-       prompt_theme=( $* )
+       prompt_$1_setup "$@[2,-1]" && prompt_theme=( "$@" )
 
        # Avoid screwing up the environment listing
        PSZZZZ=$reset_color
@@ -103,5 +163,29 @@ Options:
   esac
 }
 
-promptinit "$@"
+prompt () {
+  local prompt_opts
+  
+  set_prompt "$@"
+ 
+  (( $#prompt_opts )) &&
+      setopt noprompt{bang,cr,percent,subst} prompt${^prompt_opts[@]}
+
+  true
+}
+
+prompt_preview_theme () {
+  local -a psv; psv=($psvar); local -a +h psvar; psvar=($psv) # Ick
+  local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1
+  trap "${$(functions precmd):-:} ; ${$(functions preexec):-:}" 0
+
+  print -n "$1 theme"
+  (( $#* > 1 )) && print -n " with parameters \`$*[2,-1]'"
+  print ":"
+  prompt_${1}_setup "$@[2,-1]"
+  precmd
+  print -P "${PS1}command arg1 arg2 ... argn"
+  preexec
+}
 
+[[ -o kshautoload ]] || promptinit "$@"