From 21f6b9d14c100f0887d03422a21c57a0e327fde1 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 11 Jun 2000 22:21:33 +0000 Subject: 11866: More ANSI color stuff; preserve more state during prompt previewing. --- ChangeLog | 4 ++ Functions/Misc/colors | 132 ++++++++++++++++++++----------------- Functions/Prompts/promptinit | 154 +++++++++++++++++++++++++++++++++---------- 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 + * 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 +## +## 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: + -c Show currently selected theme and parameters -l List currently available prompt themes -p [] Preview given themes (defaults to all) -h [] Display help (for given theme) -s Set and save theme - Switch to new theme immediately (changes not saved)' + Switch to new theme immediately (changes not saved) - getopts "hlps" opt +Use prompt -h 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 "$@" -- cgit 1.4.1