From 41ffe718d7d58411254dc35f9618ae4fb0906aa6 Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Wed, 9 Jun 2021 15:53:47 +0300 Subject: [PATCH] Add customizable `vcs` prompt theme --- Functions/Prompts/prompt_vcs_setup | 180 +++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 Functions/Prompts/prompt_vcs_setup diff --git a/Functions/Prompts/prompt_vcs_setup b/Functions/Prompts/prompt_vcs_setup new file mode 100644 index 000000000..8adc7c04d --- /dev/null +++ b/Functions/Prompts/prompt_vcs_setup @@ -0,0 +1,180 @@ +## +# Prompt that can be customized through vcs_info +# + +autoload -Uz add-zsh-hook vcs_info + +# Prompt segments +readonly -gHA _prompt_vcs_ps1=( + chpwd $'\n%B%F{blue}%~%%b%f/' + left $'%%(?,%F{green},%F{red})%#%%b%f%%s ' + right '%B%F{blue}%n%b%f%k@%F{magenta}%m%f' + staged '%B%F{green}+%b%f' + unstaged '%B%F{red}*%b%f' + action '%B%F{red}%a%%b%f' + branch '%B%F{cyan}%b%%b%f' + repo '|%B%F{blue}%r%%b%f' +) + +prompt_vcs_help() { + print -r -- \ +"This prompt theme can by customized by copy-pasting any of the code below to +your .zshrc file and editing it there: + + # For each of the following three entries: + # 1st string is printed after changing dirs. + # 2nd string is the left prompt. + # 3rd string is the right prompt and updated asynchronously. + + # Normal prompt: + zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \\ + "${(q+)_prompt_vcs_ps1[chpwd]//'%%'/%}" \\ + "${(q+)_prompt_vcs_ps1[left]//'%%'/%}" \\ + "${(q+)_prompt_vcs_ps1[right]//'%%'/%}" + + # Prompt inside VCS repo: + zstyle ':vcs_info:*:prompt_vcs:*' formats \\ + ${(q+)_prompt_vcs_ps1[chpwd]} \\ + ${(q+)_prompt_vcs_ps1[left]} \\ + ${(q+):-%u%c$_prompt_vcs_ps1[branch]$_prompt_vcs_ps1[repo]} + + # Prompt during an ongoing VCS action: + zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\ + ${(q+)_prompt_vcs_ps1[chpwd]} \\ + ${(q+)_prompt_vcs_ps1[left]} \\ + ${(q+):-%u%c$_prompt_vcs_ps1[action]$_prompt_vcs_ps1[repo]} + + # These set the values of %c and %u, respectively: + zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_ps1[staged]} + zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_ps1[unstaged]} + +For more info on the settings above, 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" +} + +# Sets a style if it hasn't been set yet. +_prompt_vcs_zstyle() { + local -a val + zstyle -g val "$1" "$2" + (( $#val )) || + zstyle "$@" +} + +_prompt_vcs_info() { + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' max-exports 3 # Default is 2. + + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \ + "${_prompt_vcs_ps1[chpwd]//'%%'/%}" \ + "${_prompt_vcs_ps1[left]//'%%'/%}" \ + "${_prompt_vcs_ps1[right]//'%%'/%}" + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \ + "$_prompt_vcs_ps1[chpwd]" \ + "$_prompt_vcs_ps1[left]" \ + "%u%c$_prompt_vcs_ps1[branch]$_prompt_vcs_ps1[repo]" + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \ + "$_prompt_vcs_ps1[chpwd]" \ + "$_prompt_vcs_ps1[left]" \ + "%u%c$_prompt_vcs_ps1[action]$_prompt_vcs_ps1[repo]" + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \ + "$_prompt_vcs_ps1[staged]" + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \ + "$_prompt_vcs_ps1[unstaged]" + + vcs_info prompt_vcs # Call with namespace. + + print -rNC1 -- \ + "${(q+)vcs_info_msg_0_}" "${(q+)vcs_info_msg_1_}" "${(q+)vcs_info_msg_2_}" +} + +prompt_vcs_chpwd() { + emulate -L zsh + + # Don't check for changes at this point, for performance reasons. + typeset -ga _prompt_vcs_info_msg_=( "${(0@Q)$( + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes no + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes no + _prompt_vcs_info + )}" ) + shift -p _prompt_vcs_info_msg_ + print -Pr -- "$_prompt_vcs_info_msg_[1]" + PS1="$_prompt_vcs_info_msg_[2]" + RPS1="$_prompt_vcs_info_msg_[3]" +} + +prompt_vcs_precmd() { + emulate -L zsh + + # Kill any unfinished process before starting a new one. + if [[ -n $prompt_vcs_fd ]] && { : <&$prompt_vcs_fd } 2>/dev/null; then + zle -F "$prompt_vcs_fd" 2> /dev/null + exec {prompt_vcs_fd}<&- + fi + + # Asynchronously check for changes. + typeset -gH prompt_vcs_fd= + exec {prompt_vcs_fd}< <( + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes + _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes + _prompt_vcs_info + print -r -- "$PWD" + ) + + # Add callback. Needs to be a widget, so we can refresh the prompt. + zle -Fw "$prompt_vcs_fd" prompt_vcs_fd-widget +} + +# Callback widget function for our async fetch of VCS changes +prompt_vcs_fd-widget() { + emulate -L zsh + + [[ -n $1 ]] || + return # Don't accidentally close fd 0. + { + local -i fd=$1 + zle -F "$fd" # Detach ourselves, so we don't get called more than once. + + [[ -z $2 ]] || + return # Error occured. + + local -a reply + IFS=$'\0' read -Aru "$fd" + } always { + exec {fd}<&- + } + [[ $reply[-1] == $PWD ]] || + return # Info is not for current dir. + + shift -p reply + typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" ) + RPS1="$_prompt_vcs_info_msg_[3]" + zle .reset-prompt +} + +prompt_vcs_setup() { + prompt_opts=( cr percent sp ) # Tell promptinit which options to set. + + # Indent left continuation prompt for each open shell construct. + local -a indent=( '%('{1..36}'_, ,)' ) + PS2="${(j::)indent}" + + RPS2='%F{yellow}# %^%f' + PS4=$'#->%(?,%F{green},%B%F{red}%S)%?%b%f%s\t%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:fg=white,bg=blue,bold + suffix:fg=white,bg=blue,bold + paste:bold + ) + + add-zsh-hook chpwd prompt_vcs_chpwd + add-zsh-hook precmd prompt_vcs_precmd + zle -N prompt_vcs_fd-widget # Callback widget for async VCS update. + + prompt_vcs_chpwd +} + +prompt_vcs_setup "$@" -- 2.30.1 (Apple Git-130)