1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-04 10:41:11 +02:00

41472: introduce cleanup hooks default and restore special themes, and update documentation

This commit is contained in:
Barton E. Schaefer 2017-07-29 16:58:39 -07:00
parent 32ca9222af
commit 43e55a9bcd
6 changed files with 186 additions and 38 deletions

View file

@ -1920,8 +1920,9 @@ subsect(Installation)
You should make sure all the functions from the tt(Functions/Prompts)
directory of the source distribution are available; they all begin with
the string `tt(prompt_)' except for the special function`tt(promptinit)'.
You also need the `tt(colors)' function from tt(Functions/Misc). All of
these functions may already have been installed on your system; if not,
You also need the `tt(colors)' and `tt(add-zsh-hook)' functions from
tt(Functions/Misc).
All these functions may already be installed on your system; if not,
you will need to find them and copy them. The directory should appear as
one of the elements of the tt(fpath) array (this should already be the
case if they were installed), and at least the function tt(promptinit)
@ -1975,6 +1976,75 @@ normally call a theme's setup function directly.
)
enditem()
subsect(Utility Themes)
startitem()
item(tt(prompt off))(
The theme `tt(off)' sets all the prompt variables to minimal values with
no special effects.
)
item(tt(prompt default))(
The theme `tt(default)' sets all prompt variables to the same state as
if an interactive zsh was started with no initialization files.
)
item(tt(prompt restore))(
The special theme `tt(restore)' erases all theme settings and sets prompt
variables to their state before the first time the `tt(prompt)' function
was run, provided each theme has properly defined its cleanup (see below).
Note that you can undo `tt(prompt off)' and `tt(prompt default)' with
`tt(prompt restore)', but a second restore does not undo the first.
)
enditem()
subsect(Writing Themes)
The first step for adding your own theme is to choose a name for it,
and create a file `tt(prompt_var(name)_setup)' in a directory in your
tt(fpath), such as tt(~/myfns) in the example above. The file should
at minimum contain assignments for the prompt variables that your
theme wishes to modify. By convention, themes use tt(PS1), tt(PS2),
tt(RPS1), etc., rather than the longer tt(PROMPT) and tt(RPROMPT).
The file is autoloaded as a function in the current shell context, so
it may contain any necessary commands to customize your theme, including
defining additional functions. To make some complex tasks easier, your
setup function may also do any of the following:
startitem()
item(Assign tt(prompt_opts))(
The array tt(prompt_opts) may be assigned any of tt("bang"), tt("cr"),
tt("percent"), tt("sp"), and/or tt("subst") as values. The corresponding
setopts (tt(promptbang), etc.) are turned on, all other prompt-related
options are turned off. The tt(prompt_opts) array preserves setopts even
beyond the scope of tt(localoptions), should your function need that.
)
item(Modify precmd and preexec)(
Use of tt(add-zsh-hook) is recommended. The tt(precmd) and tt(preexec)
hooks are automatically adjusted if the prompt theme changes or is
disabled.
)
item(Declare cleanup)(
If your function makes any other changes that should be undone when the
theme is disabled, your setup function may call
example(prompt_cleanup var(command))
where var(command) should be suitably quoted. If your theme is ever
disabled or replaced by another, var(command) is executed with tt(eval).
You may declare more than one such cleanup hook.
)
item(Define preview)(
Define or autoload a function tt(prompt_var(name)_preview) to display
a simulated version of your prompt. A simple default previewer is
defined by tt(promptinit) for themes that do not define their own.
This preview function is called by `tt(prompt -p)'.
)
item(Provide help)(
Define or autoload a function tt(prompt_var(name)_help) to display
documentation or help text for your theme.
This help function is called by `tt(prompt -h)'.
)
enditem()
texinode(ZLE Functions)(Exception Handling)(Prompt Themes)(User Contributions)
sect(ZLE Functions)

View file

@ -16,9 +16,13 @@ prompt_bart_help () {
blue, and the default foreground) are used if no arguments are
given. The defaults look best on a light background.
The "off" token temporarily disables the theme; "on" restores it.
No background colors or hardwired cursor motion escapes are used,
and it is not necessary to setopt promptsubst.
The "off" token temporarily disables the theme; "on" restores it.
Note, this does NOT fully reset to the original prompt state, it
only hides/reveals the extra lines above the command line and
removes the supporting hooks.
EOF
[[ $(read -sek 1 "?${(%):-%S[press return]%s}") == [Qq] ]] &&
print -nP '\r%E' && return
@ -183,7 +187,7 @@ prompt_bart_setup () {
add-zsh-hook -D preexec "prompt_*_preexec"
functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch}"
[[ $prompt_theme[1] = bart ]] && PS1=${${(f)PS1}[-1]}
return 1
return 1 # Prevent change of $prompt_theme
;;
(on|enable)
shift
@ -224,6 +228,8 @@ prompt_bart_setup () {
add-zsh-hook precmd prompt_bart_precmd
add-zsh-hook preexec prompt_bart_preexec
prompt_cleanup \
'functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch}"'
functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch}
prompt_bart_winch"

View file

@ -0,0 +1,7 @@
PS1='%m%# '
PS2='%_> '
PS3='?# '
PS4='+%N:%i> '
unset RPS1 RPS2 RPROMPT RPROMPT2
prompt_opts=( cr percent sp )

View file

@ -1,9 +1,10 @@
# Very simple prompt
prompt_off_setup () {
PS1="%# "
PS2="> "
prompt_opts=( cr percent )
}
prompt_default_setup 2>/dev/null
prompt_off_setup "$@"
PS1="%# "
PS2="> "
PS3='?# '
PS4='+> '
prompt_opts=( cr percent sp )

View file

@ -0,0 +1,2 @@
# Damn that was easy
zstyle -t :prompt-theme cleanup

View file

@ -47,20 +47,36 @@ prompt_preview_safely() {
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
local -a precmd_functions preexec_functions
# This handles all the stuff from the default :prompt-theme cleanup
local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2
local +h PROMPT=$PROMPT RPROMPT=$RPOMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR
local -a precmd_functions preexec_functions prompt_preview_cleanup
local -aLl +h zle_highlight
# 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
{
# Save and clear current restore-point if any
zstyle -g prompt_preview_cleanup :prompt-theme cleanup
{
zstyle -d :prompt-theme cleanup
if typeset +f prompt_${1}_preview >&/dev/null; then
prompt_${1}_preview "$@[2,-1]"
else
prompt_preview_theme "$@"
fi
# 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
} always {
# Run any theme-specific cleanup, then reset restore point
zstyle -t :prompt-theme cleanup
}
} always {
(( $#prompt_preview_cleanup )) &&
zstyle -e :prompt-theme cleanup "${prompt_preview_cleanup[@]}"
}
}
set_prompt() {
@ -84,9 +100,9 @@ Use prompt -h <theme> for help on specific themes.'
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
local precmd_functions preexec_functions
local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2
local +h PROMPT=$PROMPT RPROMPT=$RPOMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR
local -a precmd_functions preexec_functions
else
trap 'prompt_${prompt_theme[1]}_setup "${(@)prompt_theme[2,-1]}"' 0
fi
@ -104,11 +120,11 @@ Use prompt -h <theme> for help on specific themes.'
;;
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
# 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"
prompt_$2_help
@ -168,28 +184,74 @@ Use prompt -h <theme> for help on specific themes.'
esac
}
prompt () {
local prompt_opts
prompt_cleanup () {
local -a cleanup_hooks
if zstyle -g cleanup_hooks :prompt-theme cleanup
then
cleanup_hooks+=(';' "$@")
zstyle -e :prompt-theme cleanup "${cleanup_hooks[@]}"
elif (( $+prompt_preview_cleanup == 0 ))
then
print -u2 "prompt_cleanup: no prompt theme active"
return 1
fi
}
prompt () {
local -a prompt_opts theme_active
zstyle -g theme_active :prompt-theme cleanup || {
# This is done here rather than in set_prompt so that it
# is safe and sane for set_prompt to setopt localoptions,
# which will be cleared before we arrive back here again.
# This is also why we pass around the prompt_opts array.
[[ -o promptbang ]] && prompt_opts+=(bang)
[[ -o promptcr ]] && prompt_opts+=(cr)
[[ -o promptpercent ]] && prompt_opts+=(percent)
[[ -o promptsp ]] && prompt_opts+=(sp)
[[ -o promptsubst ]] && prompt_opts+=(subst)
zstyle -e :prompt-theme cleanup \
'zstyle -d :prompt-theme cleanup;' \
'prompt_default_setup;' \
${PS1+PS1="${(q)PS1}"} \
${PS2+PS2="${(q)PS2}"} \
${PS3+PS3="${(q)PS3}"} \
${PS4+PS4="${(q)PS4}"} \
${RPS1+RPS1="${(q)RPS1}"} \
${RPS2+RPS2="${(q)RPS2}"} \
${RPROMPT+RPROMPT="${(q)RPROMPT}"} \
${RPROMPT2+RPROMPT2="${(q)RPROMPT2}"} \
${PSVAR+PSVAR="${(q)PSVAR}"} \
"precmd_functions=(${(q)precmd_functions[@]})" \
"preexec_functions=(${(q)preexec_functions[@]})" \
"prompt_opts=( ${prompt_opts[*]} )" \
'reply=(yes)'
}
set_prompt "$@"
(( $#prompt_opts )) &&
setopt noprompt{bang,cr,percent,subst} "prompt${^prompt_opts[@]}"
(( ${#prompt_opts} )) &&
setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}"
true
}
prompt_preview_theme () {
emulate -L zsh
local -a psv; psv=($psvar); local -a +h psvar; psvar=($psv) # Ick
local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1
local precmd_functions preexec_functions prompt_opts
local -aLl +h zle_highlight
# Check for proper state handling
(( $+prompt_preview_cleanup )) || {
prompt_preview_safely "$@"
return
}
# Minimal preview for prompts that don't supply one
local -a prompt_opts
print -n "$1 theme"
(( $#* > 1 )) && print -n " with parameters \`$*[2,-1]'"
print ":"
prompt_${1}_setup "$@[2,-1]"
(( ${#prompt_opts} )) &&
setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}"
[[ -n ${precmd_functions[(r)prompt_${1}_precmd]} ]] &&
prompt_${1}_precmd
[[ -o promptcr ]] && print -n $'\r'; :