From eaa9bebe782489434ecb1d2841da4ee6cb03dcd3 Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Tue, 13 Apr 2021 20:46:20 +0300 Subject: [PATCH] Add `newuser` prompt theme --- Functions/Prompts/prompt_newuser_setup | 197 +++++++++++++++++++++++++ Functions/Prompts/promptinit | 164 ++++++++++---------- 2 files changed, 284 insertions(+), 77 deletions(-) create mode 100644 Functions/Prompts/prompt_newuser_setup diff --git a/Functions/Prompts/prompt_newuser_setup b/Functions/Prompts/prompt_newuser_setup new file mode 100644 index 000000000..a4167a8c8 --- /dev/null +++ b/Functions/Prompts/prompt_newuser_setup @@ -0,0 +1,197 @@ +autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info +readonly -gHA _prompt_newuser_formats=( + start:chpwd $'\n%B%F{blue}%~%b%f/\n' + start:left $'%(?,%F{green},%F{red}%v%k\n%B%S)%#%b%f%s ' + start:right '%B%F{blue}%n%b%f%k@%F{magenta}%m%f' + start:staged '%B%F{green}+%b%f' + start:unstaged '%B%F{red}*%b%f' + start:action '%B%F{red}%a%%b%f' + start:branch '%B%F{cyan}%b%%b%f' + start:repo '|%B%F{blue}%r%%b%f' + cont:indent ' ' + cont:left '' + cont:right '%F{red}%^%f' +) +readonly -ga sysexits=( + USAGE + DATAERR + NOINPUT + NOUSER + NOHOST + UNAVAILABLE + SOFTWARE + OSERR + OSFILE + CANTCREAT + IOERR + TEMPFAIL + PROTOCOL + NOPERM + CONFIG +) + +prompt_newuser_help() { + print -r -- \ +"To customize your prompt, copy-paste any of the following to your .zshrc file +and edit it in there: + + # Start prompt: + zstyle ':prompt:*:start' left ${(q+)_prompt_newuser_formats[start:left]} + zstyle ':prompt:*:start' right ${(q+)_prompt_newuser_formats[start:right]} + + # Prepended to left side of start prompt if we changed dirs: + zstyle ':prompt:*:start' chpwd ${(q+)_prompt_newuser_formats[start:chpwd]} + + # Replaces right side of start prompt when in a repo: + zstyle ':prompt:*:start' unstaged ${(q+)_prompt_newuser_formats[start:unstaged]} + zstyle ':prompt:*:start' staged ${(q+)_prompt_newuser_formats[start:staged]} + zstyle ':prompt:*:start' branch ${(q+)_prompt_newuser_formats[start:branch]} + zstyle ':prompt:*:start' action ${(q+)_prompt_newuser_formats[start:action]} + zstyle ':prompt:*:start' repo ${(q+)_prompt_newuser_formats[start:repo]} + + # Continuation prompt: + zstyle ':prompt:*:cont' left ${(q+)_prompt_newuser_formats[cont:left]} + zstyle ':prompt:*:cont' right ${(q+)_prompt_newuser_formats[cont:right]} + + # Used to indent left side of continuation prompt: + zstyle ':prompt:*:cont' indent ${(q+)_prompt_newuser_formats[cont:indent]} + +For an explanation of the % codes, see +http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html and the end of +http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#vcs_005finfo-Configuration" +} + +prompt_newuser_format() { + local ctx=$1 arg fmt out + shift + for arg; do + zstyle -s :prompt:newuser:$ctx $arg fmt || + fmt="$_prompt_newuser_formats[${ctx}:$arg]" + out+="$fmt" + done + print -r -- "$out" +} + +prompt_newuser_chpwd() { + emulate -L zsh + unset vcs_info_msg_0_ + PS1="$( prompt_newuser_format start chpwd left )" +} + +prompt_newuser_precmd() { + local exitstatus=$? + emulate -L zsh + + psvar[1]= + case $exitstatus in + <128-> ) + psvar[1]="SIG$signals[exitstatus-127] " + ;| + <64-78> ) + psvar[1]="EX_$sysexits[exitstatus-63] " + ;| + <1-> ) + psvar[1]+="($exitstatus)" + esac + + if ! [[ -v vcs_info_msg_0_ ]]; then + zstyle ':vcs_info:*' check-for-staged-changes yes + vcs_info + if [[ -n $vcs_info_msg_0_ ]]; then + RPS1="$vcs_info_msg_0_" + else + RPS1="$( prompt_newuser_format start right )" + fi + fi +} + +prompt_newuser_line-init() { + emulate -L zsh + + case $CONTEXT in + start ) + local -i fd=-1 + exec {fd}< <( + zstyle ':vcs_info:*' check-for-changes yes + vcs_info + print -rNC1 -- "$PWD" "${vcs_info_msg_0_}" + ) + zle -Fw "$fd" prompt_newuser_async + ;; + cont ) + local fmt="$( prompt_newuser_format cont indent )" + local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" ) + PS2="${(j::)indent}$( prompt_newuser_format cont left )" + RPS2="$( prompt_newuser_format cont right )" + ;; + esac +} + +prompt_newuser_async() { + emulate -L zsh + { + zle -F "$1" + + [[ $2 != (|hup) ]] && + return + + () { + local pwd null + IFS=$'\0' read -ru "$1" pwd vcs_info_msg_0_ null + + [[ $pwd == $PWD ]] + } "$@" || return + + if [[ -n $vcs_info_msg_0_ ]]; then + RPS1="$vcs_info_msg_0_" + else + RPS1="$( prompt_newuser_format start right )" + fi + zle .reset-prompt + + } always { + exec {1}<&- + } +} + +prompt_newuser_line-finish() { + emulate -L zsh + PS1="$( prompt_newuser_format start left )" +} + +prompt_newuser_setup() { + prompt_opts=( cr percent sp ) + + zstyle -e ':vcs_info:*' formats ' + reply=( "%u%c$( prompt_newuser_format start branch repo )" ) + ' + zstyle -e ':vcs_info:*' actionformats ' + reply=( "%u%c$( prompt_newuser_format start action repo )" ) + ' + zstyle -e ':vcs_info:*' stagedstr ' + reply=( "$( prompt_newuser_format start staged )" ) + ' + zstyle -e ':vcs_info:*' unstagedstr ' + reply=( "$( prompt_newuser_format start unstaged )" ) + ' + PS4=$'# ?=%(?,%F{green},%B%F{red}%S)%?%b%f%s e=%e %F{green}%1N%f:%I %(1_,%F{yellow}%K{black}%_%f%k ,)' + SPROMPT='Correct %B%F{red}%U%R%b%f%u to %B%F{green}%r%b%f? [%Sy%ses|%Sn%so|%Se%sdit|%Sa%sbort] ' + PROMPT_EOL_MARK='%S%F{cyan}%#%s%f' + zle_highlight=( + isearch:fg=black,bg=yellow + special:fg=cyan,bold + region:bg=blue + suffix:bg=blue + paste:none + ) + zle -N prompt_newuser_async + + add-zsh-hook chpwd prompt_newuser_chpwd + add-zsh-hook precmd prompt_newuser_precmd + add-zle-hook-widget line-init prompt_newuser_line-init + add-zle-hook-widget line-finish prompt_newuser_line-finish + + prompt_newuser_chpwd +} + +prompt_newuser_setup "$@" diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit index 37d69f100..6d3c5272c 100644 --- a/Functions/Prompts/promptinit +++ b/Functions/Prompts/promptinit @@ -14,6 +14,8 @@ prompt_themes=() promptinit () { emulate -L zsh setopt extendedglob + autoload -Uz add-zsh-hook add-zle-hook-widget + local ppath='' name theme local -a match mbegin mend @@ -32,9 +34,6 @@ promptinit () { fi done - # To manipulate precmd and preexec hooks... - autoload -Uz add-zsh-hook - # Variables common to all prompt styles prompt_newline=$'\n%{\r%}' } @@ -113,80 +112,91 @@ Use prompt -h for help on specific themes.' ;; esac case "$opt" in - c) if [[ -n $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 - 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 _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 - else - 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 - ;; - l) print Currently available prompt themes: - print $prompt_themes - return - ;; - p) preview=( $prompt_themes ) - (( $#* > 1 )) && preview=( "$@[2,-1]" ) - for theme in $preview; do - [[ "$theme" == "$prompt_theme[*]" ]] && continue - prompt_preview_safely "$=theme" - done - print -P "%b%f%k" - ;; - s) print "Set and save not yet implemented. Please ensure your ~/.zshrc" - print "contains something similar to the following:\n" - print " autoload -Uz promptinit" - print " promptinit" - print " prompt $*[2,-1]" - shift - ;& - *) 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 + c ) + if [[ -n $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 + 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 _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 + else + 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 + ;; + l ) + print Currently available prompt themes: + print $prompt_themes + return + ;; + p ) + preview=( $prompt_themes ) + (( $#* > 1 )) && preview=( "$@[2,-1]" ) + for theme in $preview; do + [[ "$theme" == "$prompt_theme[*]" ]] && continue + prompt_preview_safely "$=theme" + done + print -P "%b%f%k" + ;; + s ) + print "Set and save not yet implemented. Please ensure your ~/.zshrc" + print "contains something similar to the following:\n" + print " autoload -Uz promptinit" + print " promptinit" + print " prompt $*[2,-1]" + shift + ;& + * ) + 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 - # Reset some commonly altered bits to the default - local hook - for hook in chpwd precmd preexec periodic zshaddhistory zshexit; do - add-zsh-hook -D "${hook}" "prompt_*_${hook}" - done - typeset -ga zle_highlight=( ${zle_highlight:#default:*} ) - (( ${#zle_highlight} )) || unset zle_highlight + # Reset some commonly altered bits to the default + local hook + for hook in chpwd precmd preexec periodic zshaddhistory zshexit \ + 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 + typeset -ga zle_highlight=( ${zle_highlight:#default:*} ) + (( ${#zle_highlight} )) || unset zle_highlight - zstyle -t :prompt-theme cleanup - prompt_$1_setup "$@[2,-1]" && prompt_theme=( "$@" ) - ;; + zstyle -t :prompt-theme cleanup + prompt_$1_setup "$@[2,-1]" && prompt_theme=( "$@" ) + ;; esac } @@ -269,11 +279,11 @@ prompt_preview_theme () { (( ${#prompt_opts} )) && setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}" [[ -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" [[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] && - prompt_${1}_preexec + prompt_${1}_preexec } [[ -o kshautoload ]] || promptinit "$@" -- 2.31.0