1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-23 04:30:24 +02:00

48853: improved handling of theme resets when changing prompt themes, especially for theme preview

This commit is contained in:
Marlon Richert 2021-05-16 21:18:06 -07:00 committed by Bart Schaefer
parent 338af5ea0f
commit 7383baf4cf
3 changed files with 81 additions and 98 deletions

View file

@ -1,5 +1,9 @@
2021-05-16 Bart Schaefer <schaefer@zsh.org> 2021-05-16 Bart Schaefer <schaefer@zsh.org>
* Marlon Richert: 48853: Doc/Zsh/contrib.yo,
Functions/Prompts/promptinit: improved handling of theme resets
when changing prompt themes, especially for theme preview
* 48860: Etc/BUGS: remove mention of bugs that were fixed * 48860: Etc/BUGS: remove mention of bugs that were fixed
* 48857: Src/builtin.c, Src/exec.c, Src/loop.c, Src/makepro.awk, * 48857: Src/builtin.c, Src/exec.c, Src/loop.c, Src/makepro.awk,

View file

@ -2041,10 +2041,12 @@ setopts (tt(promptbang), etc.) are turned on, all other prompt-related
options are turned off. The tt(prompt_opts) array preserves setopts even options are turned off. The tt(prompt_opts) array preserves setopts even
beyond the scope of tt(localoptions), should your function need that. beyond the scope of tt(localoptions), should your function need that.
) )
item(Modify precmd and preexec)( item(Modify hooks)(
Use of tt(add-zsh-hook) is recommended. The tt(precmd) and tt(preexec) Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended (see
hooks are automatically adjusted if the prompt theme changes or is ifzman(the bf(Manipulating Hook Functions) section above)\
disabled. ifnzman(noderef(Manipulating Hook Functions))\
). All hooks that follow the naming pattern tt(prompt_)var(theme)tt(_)var(hook)
are automatically removed when the prompt theme changes or is disabled.
) )
item(Declare cleanup)( item(Declare cleanup)(
If your function makes any other changes that should be undone when the If your function makes any other changes that should be undone when the

View file

@ -14,6 +14,8 @@ prompt_themes=()
promptinit () { promptinit () {
emulate -L zsh emulate -L zsh
setopt extendedglob setopt extendedglob
autoload -Uz add-zsh-hook add-zle-hook-widget
local ppath='' name theme local ppath='' name theme
local -a match mbegin mend local -a match mbegin mend
@ -32,9 +34,6 @@ promptinit () {
fi fi
done done
# To manipulate precmd and preexec hooks...
autoload -Uz add-zsh-hook
# Variables common to all prompt styles # Variables common to all prompt styles
prompt_newline=$'\n%{\r%}' prompt_newline=$'\n%{\r%}'
} }
@ -47,38 +46,23 @@ prompt_preview_safely() {
return return
fi fi
# This handles all the stuff from the default :prompt-theme restore # Run this in a subshell, so we don't need to clean up afterwards.
local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2 (
local +h PROMPT=$PROMPT RPROMPT=$RPROMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR # Execute current theme's cleanup sequence, if any.
local -a precmd_functions preexec_functions prompt_preview_restore zstyle -t :prompt-theme cleanup
local -aLl +h zle_highlight
{ # If we can't find a _preview function, run the _setup function to see if
# Save and clear current restore-point if any # it will create one.
zstyle -g prompt_preview_restore :prompt-theme restore typeset +f prompt_${1}_preview >&/dev/null ||
{
zstyle -d :prompt-theme restore
# Execute current cleanup sequence, if any.
zstyle -t :prompt-theme cleanup
# 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 prompt_${1}_setup
if typeset +f prompt_${1}_preview >&/dev/null; then # ...then try again.
prompt_${1}_preview "$@[2,-1]" if typeset +f prompt_${1}_preview >&/dev/null; then
else prompt_${1}_preview "$@[2,-1]"
prompt_preview_theme "$@" else
fi prompt_preview_theme "$@"
} always { fi
# Run any theme-specific cleanup, then reset restore point )
zstyle -t :prompt-theme cleanup
}
} always {
(( $#prompt_preview_restore )) &&
zstyle -e :prompt-theme restore "${prompt_preview_restore[@]}"
}
} }
set_prompt() { set_prompt() {
@ -97,21 +81,6 @@ Options:
Use prompt -h <theme> for help on specific themes.' Use prompt -h <theme> for help on specific themes.'
getopts "chlps:" opt getopts "chlps:" opt
case "$opt" in
(h|p)
setopt localtraps
if [[ -z "$prompt_theme[1]" ]]; then
# Not using a prompt theme; save settings
local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2
local +h PROMPT=$PROMPT RPROMPT=$RPROMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR
local -a precmd_functions preexec_functions
local theme_reset=''
else
local theme_reset='prompt_${prompt_theme[1]}_setup "${(@)prompt_theme[2,-1]}"'
fi
trap 'zstyle -t :prompt-theme cleanup;'"${theme_reset:+ $theme_reset}" 0
;;
esac
case "$opt" in case "$opt" in
c) if [[ -n $prompt_theme ]]; then c) if [[ -n $prompt_theme ]]; then
print -n "Current prompt theme" print -n "Current prompt theme"
@ -123,21 +92,26 @@ Use prompt -h <theme> for help on specific themes.'
return return
;; ;;
h) if [[ -n "$2" && -n $prompt_themes[(r)$2] ]]; then h) if [[ -n "$2" && -n $prompt_themes[(r)$2] ]]; then
if functions prompt_$2_setup >/dev/null; then # Run this in a subshell, so we don't need to clean up afterwards.
(
# Execute current theme's cleanup sequence, if any.
zstyle -t :prompt-theme cleanup zstyle -t :prompt-theme cleanup
# The next line is a bit ugly. It (perhaps unnecessarily)
# runs the prompt theme setup function to ensure that if # If we can't find a _help function, run the _setup function to see
# the theme has a _help function that it's been autoloaded. # if it will create one.
prompt_$2_setup typeset +f prompt_$2_help >/dev/null ||
fi prompt_$2_setup
if functions prompt_$2_help >/dev/null; then
print "Help for $2 theme:\n" # ...then try again.
prompt_$2_help if typeset +f prompt_$2_help >/dev/null; then
else print "Help for $2 theme:\n"
print "No help available for $2 theme." prompt_$2_help
fi else
print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'" print "No help available for $2 theme."
print "to try it out, and \`prompt -s $2' to use it in future sessions." 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 else
print "$usage" print "$usage"
fi fi
@ -178,8 +152,13 @@ Use prompt -h <theme> for help on specific themes.'
# Reset some commonly altered bits to the default # Reset some commonly altered bits to the default
local hook local hook
for hook in chpwd precmd preexec periodic zshaddhistory zshexit; do for hook in chpwd precmd preexec periodic zshaddhistory zshexit \
add-zsh-hook -D "${hook}" "prompt_*_${hook}" zsh_directory_name; do
add-zsh-hook -D "$hook" "prompt_*_$hook"
done
for hook in isearch-exit isearch-update line-pre-redraw line-init \
line-finish history-line-set keymap-select; do
add-zle-hook-widget -D "$hook" "prompt_*_$hook"
done done
typeset -ga zle_highlight=( ${zle_highlight:#default:*} ) typeset -ga zle_highlight=( ${zle_highlight:#default:*} )
(( ${#zle_highlight} )) || unset zle_highlight (( ${#zle_highlight} )) || unset zle_highlight
@ -192,11 +171,8 @@ Use prompt -h <theme> for help on specific themes.'
prompt_cleanup () { prompt_cleanup () {
local -a cleanup_hooks theme_active local -a cleanup_hooks theme_active
if ! zstyle -g cleanup_hooks :prompt-theme cleanup if ! zstyle -g cleanup_hooks :prompt-theme cleanup; then
then if ! zstyle -g theme_active :prompt-theme restore; then
(( $+prompt_preview_restore == 0 )) &&
if ! zstyle -g theme_active :prompt-theme restore
then
print -u2 "prompt_cleanup: no prompt theme active" print -u2 "prompt_cleanup: no prompt theme active"
return 1 return 1
fi fi
@ -225,22 +201,21 @@ prompt () {
[[ -o promptpercent ]] && prompt_opts+=(percent) [[ -o promptpercent ]] && prompt_opts+=(percent)
[[ -o promptsp ]] && prompt_opts+=(sp) [[ -o promptsp ]] && prompt_opts+=(sp)
[[ -o promptsubst ]] && prompt_opts+=(subst) [[ -o promptsubst ]] && prompt_opts+=(subst)
zstyle -e :prompt-theme restore \ zstyle -e :prompt-theme restore "
'zstyle -d :prompt-theme restore;' \ zstyle -d :prompt-theme restore
'prompt_default_setup;' \ prompt_default_setup
${PS1+PS1="${(q)PS1}"} \ ${PS1+PS1=${(q+)PS1}}
${PS2+PS2="${(q)PS2}"} \ ${PS2+PS2=${(q+)PS2}}
${PS3+PS3="${(q)PS3}"} \ ${PS3+PS3=${(q+)PS3}}
${PS4+PS4="${(q)PS4}"} \ ${PS4+PS4=${(q+)PS4}}
${RPS1+RPS1="${(q)RPS1}"} \ ${RPS1+RPS1=${(q+)RPS1}}
${RPS2+RPS2="${(q)RPS2}"} \ ${RPS2+RPS2=${(q+)RPS2}}
${RPROMPT+RPROMPT="${(q)RPROMPT}"} \ ${RPROMPT+RPROMPT=${(q+)RPROMPT}}
${RPROMPT2+RPROMPT2="${(q)RPROMPT2}"} \ ${RPROMPT2+RPROMPT2=${(q+)RPROMPT2}}
${PSVAR+PSVAR="${(q)PSVAR}"} \ ${PSVAR+PSVAR=${(q+)PSVAR}}
"precmd_functions=(${(q)precmd_functions[@]})" \ prompt_opts=( $prompt_opts[*] )
"preexec_functions=(${(q)preexec_functions[@]})" \ reply=( yes )
"prompt_opts=( ${prompt_opts[*]} )" \ "
'reply=(yes)'
} }
set_prompt "$@" set_prompt "$@"
@ -253,12 +228,6 @@ prompt () {
prompt_preview_theme () { prompt_preview_theme () {
emulate -L zsh emulate -L zsh
# Check for proper state handling
(( $+prompt_preview_restore )) || {
prompt_preview_safely "$@"
return
}
# Minimal preview for prompts that don't supply one # Minimal preview for prompts that don't supply one
local -a prompt_opts local -a prompt_opts
print -n "$1 theme" print -n "$1 theme"
@ -268,12 +237,20 @@ prompt_preview_theme () {
prompt_${1}_setup "$@[2,-1]" prompt_${1}_setup "$@[2,-1]"
(( ${#prompt_opts} )) && (( ${#prompt_opts} )) &&
setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}" setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}"
[[ -n ${chpwd_functions[(r)prompt_${1}_chpwd]} ]] &&
prompt_${1}_chpwd
[[ -n ${precmd_functions[(r)prompt_${1}_precmd]} ]] && [[ -n ${precmd_functions[(r)prompt_${1}_precmd]} ]] &&
prompt_${1}_precmd prompt_${1}_precmd
[[ -o promptcr ]] && print -n $'\r'; :
print -P "${PS1}command arg1 arg2 ... argn" # We'd like to call zle-line-init/finish hooks, too, but that's not possible
# while the ZLE is not active.
[[ -o promptcr ]] && print -n $'\r'
:; print -P -- "${PS1}command arg1 arg2 ... argn"
[[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] && [[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] &&
prompt_${1}_preexec prompt_${1}_preexec
} }
[[ -o kshautoload ]] || promptinit "$@" [[ -o kshautoload ]] || promptinit "$@"