zsh-workers
 help / color / mirror / code / Atom feed
* [RFC][PATCH] `newuser` prompt theme
@ 2021-04-13 19:41 Marlon
  2021-04-13 20:31 ` Roman Perepelitsa
  2021-04-13 20:44 ` Bart Schaefer
  0 siblings, 2 replies; 65+ messages in thread
From: Marlon @ 2021-04-13 19:41 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 236 bytes --]

This is a new prompt theme that is intended to be used in a rewrite of `zsh-newuser-install` (see 47955 and descendants), but it should work well as a standalone theme, too. It includes an update to `promptinit` to handle ZLE hooks.


[-- Attachment #2: 0001-Add-newuser-prompt-theme.txt --]
[-- Type: text/plain, Size: 13378 bytes --]

From eaa9bebe782489434ecb1d2841da4ee6cb03dcd3 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
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 <theme> 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


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-13 19:41 [RFC][PATCH] `newuser` prompt theme Marlon
@ 2021-04-13 20:31 ` Roman Perepelitsa
  2021-04-13 20:44 ` Bart Schaefer
  1 sibling, 0 replies; 65+ messages in thread
From: Roman Perepelitsa @ 2021-04-13 20:31 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

On Tue, Apr 13, 2021 at 9:41 PM Marlon <marlon.richert@gmail.com> wrote:
>
> This is a new prompt theme that is intended to be used in a rewrite
> of `zsh-newuser-install` (see 47955 and descendants), but it should
> work well as a standalone theme, too. It includes an update to
> `promptinit` to handle ZLE hooks.

IMO the default theme shouldn't invoke external programs. Especially
not something as heavy-weight as git, svn or hg.

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-13 19:41 [RFC][PATCH] `newuser` prompt theme Marlon
  2021-04-13 20:31 ` Roman Perepelitsa
@ 2021-04-13 20:44 ` Bart Schaefer
  2021-04-14  5:09   ` Marlon Richert
  1 sibling, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-04-13 20:44 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

On Tue, Apr 13, 2021 at 12:42 PM Marlon <marlon.richert@gmail.com> wrote:
>
> It includes an update to `promptinit` to handle ZLE hooks.

Is it possible to do that without the massive re-indent of the
existing "case" branches?


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-13 20:44 ` Bart Schaefer
@ 2021-04-14  5:09   ` Marlon Richert
  2021-04-14  5:17     ` Bart Schaefer
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-04-14  5:09 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list


> On 13 Apr 2021, at 23:45, Bart Schaefer <schaefer@brasslantern.com> wrote:
> 
> On Tue, Apr 13, 2021 at 12:42 PM Marlon <marlon.richert@gmail.com> wrote:
>> 
>> It includes an update to `promptinit` to handle ZLE hooks.
> 
> Is it possible to do that without the massive re-indent of the
> existing "case" branches?

Sure. The original indent was an odd number of spaces, though. I thought that didn’t fit the style guide/code conventions?



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14  5:09   ` Marlon Richert
@ 2021-04-14  5:17     ` Bart Schaefer
  2021-04-14  5:45       ` Marlon
  0 siblings, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-04-14  5:17 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

On Tue, Apr 13, 2021 at 10:09 PM Marlon Richert
<marlon.richert@gmail.com> wrote:
>
> > On 13 Apr 2021, at 23:45, Bart Schaefer <schaefer@brasslantern.com> wrote:
> >
> > Is it possible to do that without the massive re-indent of the
> > existing "case" branches?
>
> Sure. The original indent was an odd number of spaces, though. I thought that didn’t fit the style guide/code conventions?

Possibly, but we prefer to keep functional changes separate from
whitespace changes for semantic clarity.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14  5:17     ` Bart Schaefer
@ 2021-04-14  5:45       ` Marlon
  2021-04-14 12:05         ` Daniel Shahaf
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon @ 2021-04-14  5:45 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 674 bytes --]

On 14 Apr 2021, at 08:17, Bart Schaefer <schaefer@brasslantern.com> wrote:
> 
> On Tue, Apr 13, 2021 at 10:09 PM Marlon Richert
> <marlon.richert@gmail.com> wrote:
>> 
>>> On 13 Apr 2021, at 23:45, Bart Schaefer <schaefer@brasslantern.com> wrote:
>>> 
>>> Is it possible to do that without the massive re-indent of the
>>> existing "case" branches?
>> 
>> Sure. The original indent was an odd number of spaces, though. I thought that didn’t fit the style guide/code conventions?
> 
> Possibly, but we prefer to keep functional changes separate from
> whitespace changes for semantic clarity.

OK, here’s the patch without the reindent. See attachment.


[-- Attachment #2: 0001-Add-newuser-prompt-theme.txt --]
[-- Type: text/plain, Size: 7814 bytes --]

From 86bffc40bdd3676e4f90b8604e68356799fd6e63 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Wed, 14 Apr 2021 08:39:51 +0300
Subject: [PATCH] Add `newuser` prompt theme

---
 Functions/Prompts/prompt_newuser_setup | 197 +++++++++++++++++++++++++
 Functions/Prompts/promptinit           |  14 +-
 2 files changed, 206 insertions(+), 5 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..b9d833c4b 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%}'
 }
@@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
 
        # 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}"
+       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
-- 
2.31.1


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14  5:45       ` Marlon
@ 2021-04-14 12:05         ` Daniel Shahaf
  2021-04-14 13:17           ` Marlon
                             ` (2 more replies)
  0 siblings, 3 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-14 12:05 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

> new file mode 100644
> +++ b/Functions/Prompts/prompt_newuser_setup

At the risk of bikeshedding, I don't think that's a good name.  A name
should describe what a thing *is*, not what its intended use is; and I'm
not particularly fond of the implication that new users should be wary
of trying _other_ themes.  Besides, what if someone else were to come
along and post an alternative theme aimed at new users?

> @@ -0,0 +1,197 @@
> +readonly -ga sysexits=(
> +    USAGE
> +    CONFIG

Two interrelated scripts on zsh.org hardcode these constants too.
I wonder if we should provide these constants in a standard autoloaded
function or preset variable.

> +prompt_newuser_precmd() {
> +  local exitstatus=$?

It's not documented that precmd hooks can rely on $? to be the exit code
of the last command.  That does work, though (because callhookfunc()
calls doshfunc(noreturnval=1)), and seems useful, and I guess we won't
want to change it, so shall we document it?

> +  emulate -L zsh
> +
> +  psvar[1]=
> +  case $exitstatus in
> +    <128-> )
> +      psvar[1]="SIG$signals[exitstatus-127] "
> +      ;|
> +    <64-78> )
> +      psvar[1]="EX_$sysexits[exitstatus-63] "

Nice, I might adopt this.  Or, come to think of it, I might teach
PRINT_EXIT_VALUE to do this ☺

> +      ;|
> +    <1-> )
> +      psvar[1]+="($exitstatus)"
> +  esac
> +
> +  if ! [[ -v vcs_info_msg_0_ ]]; then
> +    zstyle ':vcs_info:*' check-for-staged-changes yes

First, no other prompt theme sets styles, so I'm not sure prompt themes
should be doing that.

Second, even if a prompt were to set styles, doing so in a precmd and
behind what _looks_ like a "first run" condition but is actually a "we
just changed directory" condition isn't exactly best practice.

Also, there are literally zero comments in the code.  That makes it
rather unmaintainable by anyone other than you — and I wonder if I
shouldn't say "other than present-you", since future-you may not fare
any better than present-me at understanding the code without comments.

> +    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 )

Nitpick, but could we please use both parentheses in new code?  That
helps my $EDITOR's jump-to-matching-paren functionality happier.

> +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 )" )
> +  '

Your theme does _nothing_ with the 'unstaged' style other than
pass it through verbatim.  That appears to be NIH.  Why shouldn't the
theme just advise people to set the vcs_info directly?

> +prompt_newuser_setup "$@"

Sorry, but I'm not at all sure I support accepting this part of the
patch.

More below.

> +++ b/Functions/Prompts/promptinit
> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
>  
>         # 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}"
> +       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"

All these should be documented, like prompt_${foo}_preview is.

Recommend to name these prompt_${foo}_bar-{isearch-exit,isearch-update,…,keymap-select}
for some fixed value of «bar» to avoid namespace issues (i.e., name
collisions between existing prompts and future hooks).

The promptinit changes are independent of the new theme.  They should be
a separate patch and could conceivably be applied separately.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 12:05         ` Daniel Shahaf
@ 2021-04-14 13:17           ` Marlon
  2021-04-14 14:09             ` Daniel Shahaf
                               ` (2 more replies)
  2021-04-14 14:00           ` precmd hooks and $? Bart Schaefer
  2021-04-15 18:54           ` [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon
  2 siblings, 3 replies; 65+ messages in thread
From: Marlon @ 2021-04-14 13:17 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> 
>> new file mode 100644
>> +++ b/Functions/Prompts/prompt_newuser_setup
> 
> At the risk of bikeshedding, I don't think that's a good name.  A name
> should describe what a thing *is*, not what its intended use is; and I'm
> not particularly fond of the implication that new users should be wary
> of trying _other_ themes.  Besides, what if someone else were to come
> along and post an alternative theme aimed at new users?

Sure, but what should I call it, then? Just `marlon`? (Seeing as we already have `adam`, `bart`, etc. themes.)


>> @@ -0,0 +1,197 @@
>> +readonly -ga sysexits=(
>> +    USAGE
> ⋮
>> +    CONFIG
> 
> Two interrelated scripts on zsh.org hardcode these constants too.
> I wonder if we should provide these constants in a standard autoloaded
> function or preset variable.

A preset variable would be great. In C code, you can get the names and values from `sysexits.h`, which is available in both GNU and BSD.


>> +  emulate -L zsh
>> +
>> +  psvar[1]=
>> +  case $exitstatus in
>> +    <128-> )
>> +      psvar[1]="SIG$signals[exitstatus-127] "
>> +      ;|
>> +    <64-78> )
>> +      psvar[1]="EX_$sysexits[exitstatus-63] "
> 
> Nice, I might adopt this.  Or, come to think of it, I might teach
> PRINT_EXIT_VALUE to do this ☺

It would be great if, besides printing the name, it could also add a short description of what the exit code actually means. Something like “SIGPIPE (140): write on a pipe with no reader”.


>> +      ;|
>> +    <1-> )
>> +      psvar[1]+="($exitstatus)"
>> +  esac
>> +
>> +  if ! [[ -v vcs_info_msg_0_ ]]; then
>> +    zstyle ':vcs_info:*' check-for-staged-changes yes
> 
> First, no other prompt theme sets styles, so I'm not sure prompt themes
> should be doing that.

Please show me another way to theme the VCS part of the prompt and I will use that.


> Second, even if a prompt were to set styles, doing so in a precmd and
> behind what _looks_ like a "first run" condition but is actually a "we
> just changed directory" condition isn't exactly best practice.

What would be a better practice?


> Also, there are literally zero comments in the code.  That makes it
> rather unmaintainable by anyone other than you — and I wonder if I
> shouldn't say "other than present-you", since future-you may not fare
> any better than present-me at understanding the code without comments.

Sure, I will add those.


>> +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 )" )
>> +  '
> 
> Your theme does _nothing_ with the 'unstaged' style other than
> pass it through verbatim.  

After setting it to '%B%F{red}*%b%f’, yes.


> That appears to be NIH.  

Sorry, but what does NIH stand for? (I’m guessing you don’t mean the National Institutes of Health.)


> Why shouldn't the
> theme just advise people to set the vcs_info directly?

Because it’s a theme? If people wanted to style their vcs_info directly, then why would they use a theme? Conversely, VCS info is the number one thing that new users want to add to their prompt. I don’t think it’s unreasonable to expect that to be included out of the box. Nearly all of 3rd-party prompt themes in the wild include at least Git info.


> The promptinit changes are independent of the new theme.  They should be
> a separate patch and could conceivably be applied separately.

Sure, I’ll start a separate patch thread for those.




^ permalink raw reply	[flat|nested] 65+ messages in thread

* precmd hooks and $?
  2021-04-14 12:05         ` Daniel Shahaf
  2021-04-14 13:17           ` Marlon
@ 2021-04-14 14:00           ` Bart Schaefer
  2021-04-14 15:18             ` docs patches for precmd hooks and $?, and vcs_info Daniel Shahaf
  2021-04-15 18:54           ` [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon
  2 siblings, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-04-14 14:00 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 485 bytes --]

On Wed, Apr 14, 2021 at 5:06 AM Daniel Shahaf <d.s@daniel.shahaf.name>
wrote:

>
> > +prompt_newuser_precmd() {
> > +  local exitstatus=$?
>
> It's not documented that precmd hooks can rely on $? to be the exit code
> of the last command.  That does work, though (because callhookfunc()
> calls doshfunc(noreturnval=1)), and seems useful, and I guess we won't
> want to change it, so shall we document it?


It's intentional and as far as I recall has always been assumed, so ... yes.

[-- Attachment #2: Type: text/html, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 13:17           ` Marlon
@ 2021-04-14 14:09             ` Daniel Shahaf
  2021-04-15  1:07               ` Bart Schaefer
                                 ` (2 more replies)
  2021-04-14 14:09             ` sysexits.h codes? (was: " Daniel Shahaf
  2021-04-14 15:30             ` [RFC][PATCH] `newuser` prompt theme Arseny Maslennikov
  2 siblings, 3 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-14 14:09 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

Marlon wrote on Wed, Apr 14, 2021 at 16:17:02 +0300:
> On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > 
> >> new file mode 100644
> >> +++ b/Functions/Prompts/prompt_newuser_setup
> > 
> > At the risk of bikeshedding, I don't think that's a good name.  A name
> > should describe what a thing *is*, not what its intended use is; and I'm
> > not particularly fond of the implication that new users should be wary
> > of trying _other_ themes.  Besides, what if someone else were to come
> > along and post an alternative theme aimed at new users?
> 
> Sure, but what should I call it, then? Just `marlon`? (Seeing as we already have `adam`, `bart`, etc. themes.)

That'd work.  A name that describes the theme itself rather than its
origin would be even better (if the theme is accepted into zsh.git).

> >> +      ;|
> >> +    <1-> )
> >> +      psvar[1]+="($exitstatus)"
> >> +  esac
> >> +
> >> +  if ! [[ -v vcs_info_msg_0_ ]]; then
> >> +    zstyle ':vcs_info:*' check-for-staged-changes yes
> > 
> > First, no other prompt theme sets styles, so I'm not sure prompt themes
> > should be doing that.
> 
> Please show me another way to theme the VCS part of the prompt and I will use that.

You seem to have checked your manners in at the door.

In any case, what you've implemented is that you re-set a style on the
first precmd after every chdir.  I don't think these semantics should be
implemented in the first place.

> > Second, even if a prompt were to set styles, doing so in a precmd and
> > behind what _looks_ like a "first run" condition but is actually a "we
> > just changed directory" condition isn't exactly best practice.
> 
> What would be a better practice?

Don't surprise/mislead code readers.

Don't surprise/mislead users.

Document your code.

Make defaults overridable.

Don't trample user settings (e.g., someone explicitly setting that style
to a false value for that same context, or for the context «:vcs_info*»,
which is less specific than the context you use and thus would be shadowed).

These are all such ground rules that I'm surprised I have to spell them out.

> >> +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 )" )
> >> +  '
> > 
> > Your theme does _nothing_ with the 'unstaged' style other than
> > pass it through verbatim.  
> 
> After setting it to '%B%F{red}*%b%f’, yes.
> 

Hmm.  That's a good question: how _should_ a theme set an overrideable
default for stagedstr?

> 
> > That appears to be NIH.  
> 
> Sorry, but what does NIH stand for? (I’m guessing you don’t mean the National Institutes of Health.)
> 

Not Invented Here syndrome; cf. EEE :P

> > Why shouldn't the theme just advise people to set the vcs_info
> > directly?
> 
> Because it’s a theme? If people wanted to style their vcs_info
> directly, then why would they use a theme?

The point is, you're making people learn a different syntax for
identical functionality for zero benefit.

> Conversely, VCS info is the number one thing that new users want to
> add to their prompt. I don’t think it’s unreasonable to expect that to
> be included out of the box.  Nearly all of 3rd-party prompt themes in
> the wild include at least Git info.

The question remains whether or not for a prompt theme to set vcs_info
styles does or doesn't violate the principle of least surprise.

> > The promptinit changes are independent of the new theme.  They should be
> > a separate patch and could conceivably be applied separately.
> 
> Sure, I’ll start a separate patch thread for those.

Thanks.

>

Daniel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* sysexits.h codes?  (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-14 13:17           ` Marlon
  2021-04-14 14:09             ` Daniel Shahaf
@ 2021-04-14 14:09             ` Daniel Shahaf
  2021-04-30 19:40               ` Marlon Richert
  2021-04-14 15:30             ` [RFC][PATCH] `newuser` prompt theme Arseny Maslennikov
  2 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-14 14:09 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

> >> @@ -0,0 +1,197 @@
> >> +readonly -ga sysexits=(
> >> +    USAGE
> > ⋮
> >> +    CONFIG
> > 
> > Two interrelated scripts on zsh.org hardcode these constants too.
> > I wonder if we should provide these constants in a standard autoloaded
> > function or preset variable.
> 
> A preset variable would be great. In C code, you can get the names and values from `sysexits.h`, which is available in both GNU and BSD.

An associative array mapping symbolic names to integers?  Just those
available on the target system, or?

> >> +  emulate -L zsh
> >> +
> >> +  psvar[1]=
> >> +  case $exitstatus in
> >> +    <128-> )
> >> +      psvar[1]="SIG$signals[exitstatus-127] "
> >> +      ;|
> >> +    <64-78> )
> >> +      psvar[1]="EX_$sysexits[exitstatus-63] "
> > 
> > Nice, I might adopt this.  Or, come to think of it, I might teach
> > PRINT_EXIT_VALUE to do this ☺
> 
> It would be great if, besides printing the name, it could also add a
> short description of what the exit code actually means. Something like
> “SIGPIPE (140): write on a pipe with no reader”.

There's precedent to work with:

    % =pwd | true 
    zsh: broken pipe  =pwd

I suppose the default should be about this level of verbosity.

Other degrees of verbosity could be considered.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* docs patches for precmd hooks and $?, and vcs_info
  2021-04-14 14:00           ` precmd hooks and $? Bart Schaefer
@ 2021-04-14 15:18             ` Daniel Shahaf
  2021-04-15  2:35               ` Bart Schaefer
  2021-04-15 16:17               ` Archives render attachments as first-class messages (was: docs patches for precmd hooks and $?, and vcs_info) Daniel Shahaf
  0 siblings, 2 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-14 15:18 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 925 bytes --]

Bart Schaefer wrote on Wed, Apr 14, 2021 at 07:00:32 -0700:
> On Wed, Apr 14, 2021 at 5:06 AM Daniel Shahaf <d.s@daniel.shahaf.name>
> wrote:
> 
> >
> > > +prompt_newuser_precmd() {
> > > +  local exitstatus=$?
> >
> > It's not documented that precmd hooks can rely on $? to be the exit code
> > of the last command.  That does work, though (because callhookfunc()
> > calls doshfunc(noreturnval=1)), and seems useful, and I guess we won't
> > want to change it, so shall we document it?
> 
> 
> It's intentional and as far as I recall has always been assumed, so ... yes.

Done.  Attached as 4/8.  Also did a few other things while I was in the
area, and things that I noticed while auditing for other instances of
the bugs fixed by the the former things.

Split to rather small pieces, but in exchange, the log messages are
informative.  (Also, I do review my own patches to the same standard as
others'.)

Cheers,

Daniel

[-- Attachment #2: 0001-docs-Minor-markup-tweak.patch.txt --]
[-- Type: text/plain, Size: 1036 bytes --]

From ef53ae6286714123845ce80b5b8c2d1c8b7ce37c Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:12:25 +0000
Subject: [PATCH 1/8] docs: Minor markup tweak

---
 Doc/Zsh/func.yo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo
index d500a78ae..0944380b9 100644
--- a/Doc/Zsh/func.yo
+++ b/Doc/Zsh/func.yo
@@ -212,7 +212,7 @@ example, if tt($chpwd_functions) is an array containing the values
 execute the functions `tt(chpwd)', `tt(mychpwd)' and
 `tt(chpwd_save_dirstack)', in that order.  Any function that does not exist
 is silently ignored.  A function found by this mechanism is referred to
-elsewhere as a `hook function'.  An error in any function causes subsequent
+elsewhere as a em(hook function).  An error in any function causes subsequent
 functions not to be run.  Note further that an error in a tt(precmd) hook
 causes an immediately following tt(periodic) function not to run (though
 it may run at the next opportunity).

[-- Attachment #3: 0002-docs-Fix-example-rendering-in-the-man-page-outpu.patch.txt --]
[-- Type: text/plain, Size: 979 bytes --]

From 4017180dcd861fed2e054de946d7612b13249dde Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:20:23 +0000
Subject: [PATCH 2/8] docs: Fix example rendering in the man page output

The texi output was unaffected.  However, in the man page on my system,
everything after the example() was underlined and not indented.
---
 Doc/Zsh/contrib.yo | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 586ac06f5..55ea06f34 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2028,7 +2028,9 @@ 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.

[-- Attachment #4: 0003-docs-Fix-rendering-in-the-man-page-output.patch.txt --]
[-- Type: text/plain, Size: 1459 bytes --]

From 49f9bb8ebe2a5ad0fc463930c6c8cf76a8eac8f9 Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:23:58 +0000
Subject: [PATCH 3/8] docs: Fix rendering in the man page output

In the man page output, the text was underlined from the var()
to the end of the paragraph.

The texi output in affected.  For instance, the text `name' in TeX
is now slanted Roman (\slshape\rmfamily) rather than slanted teletype
(\slshape\ttfamily).
---
 Doc/Zsh/contrib.yo | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 55ea06f34..5e91f9a8d 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2036,13 +2036,13 @@ 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
+Define or autoload a function tt(prompt_)var(name)tt(_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
+Define or autoload a function tt(prompt_)var(name)tt(_help) to display
 documentation or help text for your theme.
 This help function is called by `tt(prompt -h)'.
 )

[-- Attachment #5: 0004-docs-Document-that-hook-functions-may-rely-on-se.patch.txt --]
[-- Type: text/plain, Size: 1099 bytes --]

From 20a22e5a4d7cd881c88554f87e571e1607612b28 Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:27:10 +0000
Subject: [PATCH 4/8] docs: Document that hook functions may rely on $? (see
 workers/48570).

---
 Doc/Zsh/func.yo | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo
index 0944380b9..7edad7f23 100644
--- a/Doc/Zsh/func.yo
+++ b/Doc/Zsh/func.yo
@@ -206,7 +206,8 @@ findex(hook functions)
 For the functions below, it is possible to define an array that has the
 same name as the function with `tt(_functions)' appended.  Any element in
 such an array is taken as the name of a function to execute; it is executed
-in the same context and with the same arguments as the basic function.  For
+in the same context and with the same arguments and same initial value of tt($?)
+as the basic function.  For
 example, if tt($chpwd_functions) is an array containing the values
 `tt(mychpwd)', `tt(chpwd_save_dirstack)', then the shell attempts to
 execute the functions `tt(chpwd)', `tt(mychpwd)' and

[-- Attachment #6: 0005-vcs_info-docs-Recommend-use-of-prompt-expandos-r.patch.txt --]
[-- Type: text/plain, Size: 1581 bytes --]

From 0057f30bf04f8d0f5e855846805ca261a3c6c4a7 Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:49:13 +0000
Subject: [PATCH 5/8] vcs_info docs: Recommend use of prompt expandos rather
 than terminal escape sequences.

---
 Doc/Zsh/contrib.yo | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 5e91f9a8d..07bf4e054 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -1826,10 +1826,22 @@ example(zstyle ':vcs_info:bzr:*' use-simple true)
 If you do use tt(use-simple), please report if it does `the-right-thing[tm]'.
 
 Display the revision number in yellow for tt(bzr) and tt(svn):
+example(zstyle ':vcs_info:(svn|bzr):*' \ 
+       branchformat '%b%%F{yellow}:%r')
+
+The doubled percent sign is explained in
+ifzman(the bf(Oddities) section)ifnzman(noderef(vcs_info Oddities)).
+
+Alternatively, one can use the raw colour codes directly:
+
 example(zstyle ':vcs_info:(svn|bzr):*' \ 
        branchformat '%b%{'${fg[yellow]}'%}:%r')
 
-If you want colors, make sure you enclose the color codes in tt(%{)var(...)tt(%})
+Normally when a variable is interpolated into a format string, the variable
+needs to be tt(%)-escaped. In this example we skipped that because we assume
+the value of tt(${fg[yellow]}) doesn't contain any tt(%) signs.
+
+Make sure you enclose the color codes in tt(%{)var(...)tt(%})
 if you want to use the string provided by tt(vcs_info) in prompts.
 
 Here is how to print the VCS information as a command (not in a prompt):

[-- Attachment #7: 0006-vcs_info-docs-Change-user-context-name-in-an-exa.patch.txt --]
[-- Type: text/plain, Size: 1207 bytes --]

From 53a5e2b920e16d398e7869aaeb7077ebad049b9f Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 14:50:34 +0000
Subject: [PATCH 6/8] vcs_info docs: Change user-context name in an example, to
 avoid confusion with the special-casing of the value `command' in
 vcs_info_lastmsg.

---
 Doc/Zsh/contrib.yo | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 07bf4e054..ef992bdeb 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -1845,10 +1845,10 @@ Make sure you enclose the color codes in tt(%{)var(...)tt(%})
 if you want to use the string provided by tt(vcs_info) in prompts.
 
 Here is how to print the VCS information as a command (not in a prompt):
-example(alias vcsi='vcs_info command; vcs_info_lastmsg')
+example(alias vcsi='vcs_info interactive; vcs_info_lastmsg')
 
 This way, you can even define different formats for output via
-tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:command:*)' namespace.
+tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:interactive:*)' namespace.
 
 Now as promised, some code that uses hooks:
 say, you'd like to replace the string `svn' by `subversion' in

[-- Attachment #8: 0007-vcs_info-docs-vcs_info_lastmsg-Correct-an-ambigu.patch.txt --]
[-- Type: text/plain, Size: 822 bytes --]

From 22b629e8a2cfe237ed6ec2fddfa8826d67ea6f93 Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 15:10:03 +0000
Subject: [PATCH 7/8] vcs_info docs: vcs_info_lastmsg: Correct an
 ambiguous/wrong description.

---
 Doc/Zsh/contrib.yo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index ef992bdeb..5fe5601a7 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -1510,7 +1510,7 @@ below for details.
 )
 findex(vcs_info_lastmsg)
 item(tt(vcs_info_lastmsg))(
-Outputs the last tt(${vcs_info_msg_*_}) value.
+Outputs the current values of tt(${vcs_info_msg_*_}).
 Takes into account the value of the tt(use-prompt-escapes) style in
 tt(':vcs_info:formats:command:-all-'). It also only prints tt(max-exports)
 values.

[-- Attachment #9: 0008-vcs_info-git-Use-best-practices-in-an-example.patch.txt --]
[-- Type: text/plain, Size: 1021 bytes --]

From 41f058912791b55b18de5e71f3426c3af1a5be8c Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <d.s@daniel.shahaf.name>
Date: Wed, 14 Apr 2021 15:11:01 +0000
Subject: [PATCH 8/8] vcs_info git: Use best practices in an example

The alias was vulnerable to SHORT_LOOPS syntax, not invokable from
scripts, etc..
---
 Doc/Zsh/contrib.yo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 5fe5601a7..3c4fdded0 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -1845,7 +1845,7 @@ Make sure you enclose the color codes in tt(%{)var(...)tt(%})
 if you want to use the string provided by tt(vcs_info) in prompts.
 
 Here is how to print the VCS information as a command (not in a prompt):
-example(alias vcsi='vcs_info interactive; vcs_info_lastmsg')
+example(vcsi+LPAR()+RPAR() { vcs_info interactive; vcs_info_lastmsg })
 
 This way, you can even define different formats for output via
 tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:interactive:*)' namespace.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 13:17           ` Marlon
  2021-04-14 14:09             ` Daniel Shahaf
  2021-04-14 14:09             ` sysexits.h codes? (was: " Daniel Shahaf
@ 2021-04-14 15:30             ` Arseny Maslennikov
  2021-04-14 18:52               ` Daniel Shahaf
  2 siblings, 1 reply; 65+ messages in thread
From: Arseny Maslennikov @ 2021-04-14 15:30 UTC (permalink / raw)
  To: Marlon; +Cc: Daniel Shahaf, Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]

On Wed, Apr 14, 2021 at 04:17:02PM +0300, Marlon wrote:
> > Why shouldn't the
> > theme just advise people to set the vcs_info directly?
> 
> Because it’s a theme? If people wanted to style their vcs_info directly, then why would they use a theme? Conversely, VCS info is the number one thing that new users want to add to their prompt. I don’t think it’s unreasonable to expect that to be included out of the box.

This has not been brought up in this thread, but prompt themes do accept
command line arguments. So we could have «prompt marlon» which does not
include vcs_info in the prompt for the users that want a more responsive
prompt or use rotational storage, and «prompt marlon --vcs-info» which does.

vcs_info is designed just so it is configured separately with its own
zstyles, though; IMHO it's unfair for a prompt theme to modify that
configuration, but OK to make a decision to use/unuse it.

> Nearly all of 3rd-party prompt themes in the wild include at least Git info.

They do that mainly to advertise to people that zsh + vcs_info can do
this, and to encourage them to use their shell creatively.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 15:30             ` [RFC][PATCH] `newuser` prompt theme Arseny Maslennikov
@ 2021-04-14 18:52               ` Daniel Shahaf
  0 siblings, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-14 18:52 UTC (permalink / raw)
  To: Arseny Maslennikov, Marlon Richert; +Cc: Zsh hackers list

Arseny Maslennikov wrote on Wed, 14 Apr 2021 15:30 +00:00:
> On Wed, Apr 14, 2021 at 04:17:02PM +0300, Marlon wrote:
> > > Why shouldn't the
> > > theme just advise people to set the vcs_info directly?
> > 
> > Because it’s a theme? If people wanted to style their vcs_info directly, then why would they use a theme? Conversely, VCS info is the number one thing that new users want to add to their prompt. I don’t think it’s unreasonable to expect that to be included out of the box.
> 
> This has not been brought up in this thread, but prompt themes do accept
> command line arguments. So we could have «prompt marlon» which does not
> include vcs_info in the prompt for the users that want a more responsive
> prompt or use rotational storage, and «prompt marlon --vcs-info» which does.
> 
> vcs_info is designed just so it is configured separately with its own
> zstyles, though; IMHO it's unfair for a prompt theme to modify that
> configuration, but OK to make a decision to use/unuse it.

Well, the «vcs_info $user_context» usage does exist.  Perhaps a prompt
theme could use that and then set appropriate styles…


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 14:09             ` Daniel Shahaf
@ 2021-04-15  1:07               ` Bart Schaefer
  2021-04-15  3:50               ` Marlon Richert
  2021-04-15 11:11               ` Mikael Magnusson
  2 siblings, 0 replies; 65+ messages in thread
From: Bart Schaefer @ 2021-04-15  1:07 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Marlon, Zsh hackers list

On Wed, Apr 14, 2021 at 7:09 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Make defaults overridable.
>
> Don't trample user settings (e.g., someone explicitly setting that style
> to a false value for that same context, or for the context «:vcs_info*»,
> which is less specific than the context you use and thus would be shadowed).

I have a half-finished script to initialize interesting completion
styles.  In that script I test the styles to be set by using "zstyle
-g", and then only if that fails, set the value I want.

emulate zsh -o extendedglob -c 'default_zstyle() {
  local -a patstyle defn
  if [[ "$1" = (-e|-|--) ]]
  then patstyle=( "$2" "$3" )
  else patstyle=( "$1" "$2" )
  fi
  ! zstyle -T "${patstyle[@]}" ||
   zstyle -g defn "${patstyle[@]}" ||
    zstyle "$@"
}'

Thus:

default_zstyle -e ':vcs_info:*' formats '
  reply=( "%u%c$( prompt_newuser_format start branch repo )" )
'

The "zstyle -T" treats the new style's pattern as a context and tries
to look up an existing style; that mostly works.  "zstyle -g" is just
a failsafe.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: docs patches for precmd hooks and $?, and vcs_info
  2021-04-14 15:18             ` docs patches for precmd hooks and $?, and vcs_info Daniel Shahaf
@ 2021-04-15  2:35               ` Bart Schaefer
  2021-04-15 16:17               ` Archives render attachments as first-class messages (was: docs patches for precmd hooks and $?, and vcs_info) Daniel Shahaf
  1 sibling, 0 replies; 65+ messages in thread
From: Bart Schaefer @ 2021-04-15  2:35 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Wed, Apr 14, 2021 at 8:19 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Split to rather small pieces, but in exchange, the log messages are
> informative.

These all look OK.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 14:09             ` Daniel Shahaf
  2021-04-15  1:07               ` Bart Schaefer
@ 2021-04-15  3:50               ` Marlon Richert
  2021-04-15 20:27                 ` Daniel Shahaf
  2021-04-15 23:42                 ` Daniel Shahaf
  2021-04-15 11:11               ` Mikael Magnusson
  2 siblings, 2 replies; 65+ messages in thread
From: Marlon Richert @ 2021-04-15  3:50 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Wed, Apr 14, 2021 at 5:09 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > Sure, but what should I call it, then? Just `marlon`? (Seeing as we already have `adam`, `bart`, etc. themes.)
>
> That'd work.  A name that describes the theme itself rather than its
> origin would be even better (if the theme is accepted into zsh.git).

How about `simple` or `minimal` or something like that?

> > > First, no other prompt theme sets styles, so I'm not sure prompt themes
> > > should be doing that.
> >
> > Please show me another way to theme the VCS part of the prompt and I will use that.
>
> You seem to have checked your manners in at the door.

I don't know your background, but where I'm from, saying "please"
means being polite. I don't think I've given you any reason to think
otherwise. Have I?

However, if you do think I'm doing something wrong, then please make
your criticism more constructive.
* You imply I was being rude, but what in my sentence made you think
so? Without knowing that, I cannot correct the way I write.
* You said my prompt theme should not set styles, but what methods
should I then use to style the VCS part of the prompt? I cannot know
how you want me to change my code, if you don't tell me.

I would appreciate it if you could try to keep your code review
comments actionable and on topic, please. Thank you.

> In any case, what you've implemented is that you re-set a style on the
> first precmd after every chdir.  I don't think these semantics should be
> implemented in the first place.

So, what do you think I should I do instead?

> > > Second, even if a prompt were to set styles, doing so in a precmd and
> > > behind what _looks_ like a "first run" condition but is actually a "we
> > > just changed directory" condition isn't exactly best practice.
> >
> > What would be a better practice?
>
> Don't surprise/mislead code readers.
>
> Don't surprise/mislead users.

I would appreciate it if you could use less loaded words than
"surprise" and "mislead". I am not trying to surprise my
readers/users, let alone "mislead" them. Please try to stick to the
facts and write actionable comments. How do you think I can improve my
code to be less "surprising"?

> Document your code.

I try to write my code to be self-documenting. However, as with all
writing, one easily becomes blond to one's own typos. It would help a
lot if you could tell me exactly what parts of the code you think need
comments. For which sections in particular would you like me to
explain my motives?

> Make defaults overridable.

Did you read prompt_newuser_help() / the output of `prompt -h
newuser`? It explains the mechanisms I've prodiv to override the
defaults.

> Don't trample user settings

It's one thing to tell me not to override a user settings, but quite
another to tell me that I "trample" them.

> (e.g., someone explicitly setting that style
> to a false value for that same context, or for the context «:vcs_info*»,
> which is less specific than the context you use and thus would be shadowed).

This theme is intended for persons who don't want to manually
configure their VCS info separately from their prompt. My theme is
also setting [R]PS(1|2|4). Do you see that, too, as overriding the
user's settings? If the user wants to configure those manually, then
they can choose not to use this theme.

> These are all such ground rules that I'm surprised I have to spell them out.

I would appreciate it if you could refrain from insulting my
intellect. I am new as an open source contributor in general and to
Zsh in particular. So, please bear in mind that I might not be used to
the "ground rules" under which you operate.

I have, however, written code for nearly 30 years and worked
professionally in the software industry for over 20 years. Yet, I have
never seen so much unconstructive criticism in a code review as I've
now read in your email. I would appreciate it if you could adjust your
tone of voice, please, and show a bit more respect for your fellow
programmer.

> > > That appears to be NIH.
> >
> > Sorry, but what does NIH stand for? (I’m guessing you don’t mean the National Institutes of Health.)
>
> Not Invented Here syndrome; cf. EEE :P

What exactly makes you think I have Not Invented Here syndrome? I am
reusing vcs_info instead of rolling my own Git inspection code, am I
not? To quote one famous comedic duo from New Zealand: "Be more
constructive with your feedback, please." Also, I have no idea what
EEE stands for. Should I look it up in the jargon file? You're not
making it easy to understand you.

> > > Why shouldn't the theme just advise people to set the vcs_info
> > > directly?
> >
> > Because it’s a theme? If people wanted to style their vcs_info
> > directly, then why would they use a theme?
>
> The point is, you're making people learn a different syntax for
> identical functionality for zero benefit.

"Zero" benefit? vcs_info's documentation is not easy to read. I am
creating a simpler abstraction layer on top of a rather tricky API. If
I thought there was "zero" benefit in what I was doing, then I
wouldn't have programmed it that way, would?

You said it yourself: "Make defaults overridable." That's what I'm
trying to do here. I am open to suggestions for improvements, but
simply telling me that it has "zero benefit" and leaving it at that is
not being helpful.

Overall, I have to say I'm quite disappointed with your tone of voice
in this email. Perhaps you were having a bad day? I'm hoping that we
can be more pleasant to each other again next time.

Kind regards,
—Marlon


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-14 14:09             ` Daniel Shahaf
  2021-04-15  1:07               ` Bart Schaefer
  2021-04-15  3:50               ` Marlon Richert
@ 2021-04-15 11:11               ` Mikael Magnusson
  2021-04-15 16:44                 ` vcs_info's global variables (was: Re: [RFC][PATCH] `newuser` prompt theme) Daniel Shahaf
  2021-04-16 16:04                 ` [RFC][PATCH] `newuser` prompt theme Marlon
  2 siblings, 2 replies; 65+ messages in thread
From: Mikael Magnusson @ 2021-04-15 11:11 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Marlon, Zsh hackers list

[only vcs_info]
On 4/14/21, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> Marlon wrote on Wed, Apr 14, 2021 at 16:17:02 +0300:
>> On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>> >> +
>> >> +  if ! [[ -v vcs_info_msg_0_ ]]; then
>> >> +    zstyle ':vcs_info:*' check-for-staged-changes yes
>> >
>> > First, no other prompt theme sets styles, so I'm not sure prompt themes
>> > should be doing that.
>>
>> Please show me another way to theme the VCS part of the prompt and I will
>> use that.
>
> You seem to have checked your manners in at the door.
>
> In any case, what you've implemented is that you re-set a style on the
> first precmd after every chdir.  I don't think these semantics should be
> implemented in the first place.
>
>> > Second, even if a prompt were to set styles, doing so in a precmd and
>> > behind what _looks_ like a "first run" condition but is actually a "we
>> > just changed directory" condition isn't exactly best practice.
>>
>> What would be a better practice?
>
> Don't surprise/mislead code readers.
>
> Don't surprise/mislead users.
>
> Document your code.
>
> Make defaults overridable.
>
> Don't trample user settings (e.g., someone explicitly setting that style
> to a false value for that same context, or for the context «:vcs_info*»,
> which is less specific than the context you use and thus would be
> shadowed).
>
> These are all such ground rules that I'm surprised I have to spell them
> out.
>
>> >> +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 )" )
>> >> +  '
>> >
>> > Your theme does _nothing_ with the 'unstaged' style other than
>> > pass it through verbatim.
>>
>> After setting it to '%B%F{red}*%b%f’, yes.
>>
>
> Hmm.  That's a good question: how _should_ a theme set an overrideable
> default for stagedstr?

It's actually very easy to do so (somewhat pseudocodified actual code):
setup() {
  zstyle ':vcs_info:*:prompt-mikachu:*' actionformats %b %a
  zstyle ':vcs_info:*:prompt-mikachu:*' formats %b
  zstyle ':vcs_info:*:prompt-mikachu:*' max-exports 2
  zstyle ':vcs_info:(hg|svn):prompt-mikachu:*' formats '%b[%s]'

  autoload -Uz vcs_info
}

precmd() {

  local vcs_info_msg_{0..1}_
  vcs_info prompt-mikachu
  psvar[3]=( "${vcs_info_msg_0_:-}" )
  psvar[4]=( "${vcs_info_msg_1_:-}" )
}

eg, the first argument to vcs_info is used as a context to look up
values of styles, so you can very easily namespace all your settings
to your theme. localing vcs_info_msg_*_ is also important so that you
don't interfere with any commandline usage of vcs_info (I didn't check
if you do this).

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Archives render attachments as first-class messages (was: docs patches for precmd hooks and $?, and vcs_info)
  2021-04-14 15:18             ` docs patches for precmd hooks and $?, and vcs_info Daniel Shahaf
  2021-04-15  2:35               ` Bart Schaefer
@ 2021-04-15 16:17               ` Daniel Shahaf
  1 sibling, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-15 16:17 UTC (permalink / raw)
  To: zsh-workers

Daniel Shahaf wrote on Wed, Apr 14, 2021 at 15:18:22 +0000:
> Attached as 4/8.

To people reading the parent message in the https://www.zsh.org/mla/
archives, note its attachments don't show up as attachments but as
first-order messages, here:

1/8 https://www.zsh.org/mla/workers/2021/msg00793.html
2/8 https://www.zsh.org/mla/workers/2021/msg00794.html
3/8 https://www.zsh.org/mla/workers/2021/msg00795.html
4/8 https://www.zsh.org/mla/workers/2021/msg00796.html
5/8 https://www.zsh.org/mla/workers/2021/msg00797.html
6/8 https://www.zsh.org/mla/workers/2021/msg00798.html
7/8 https://www.zsh.org/mla/workers/2021/msg00799.html
8/8 https://www.zsh.org/mla/workers/2021/msg00800.html

That's presumably because the attachments look like email messages
with From_ lines.

----

We should fix this for new messages.  We're using mhonarc 2.6.24 from
FreeBSD ports, invoked as shown hereunder.  If anyone knows the fix off
the top of their heads, please let us know (offlist is fine), thanks.

	/usr/local/bin/mhonarc \
		-quiet \
		-definevar listlocalpartsansprefix=${listlocalpart#zsh-} \
		-title  "${title}" \
		-ttitle "${title}" \
		-tlevels 9999 \
		-rcfile /usr/local/www/mhonarc.zsh \
		-add \
		-- "$munged_tmpfile" \

Cheers,

Daniel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* vcs_info's global variables (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-15 11:11               ` Mikael Magnusson
@ 2021-04-15 16:44                 ` Daniel Shahaf
  2021-04-16 16:04                 ` [RFC][PATCH] `newuser` prompt theme Marlon
  1 sibling, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-15 16:44 UTC (permalink / raw)
  To: Mikael Magnusson; +Cc: Marlon, Zsh hackers list

Mikael Magnusson wrote on Thu, Apr 15, 2021 at 13:11:16 +0200:
> precmd() {
>   local vcs_info_msg_{0..1}_
>   vcs_info prompt-mikachu
> }
> localing vcs_info_msg_*_ is also important so that you
> don't interfere with any commandline usage of vcs_info.

Good point.  That's not an easy-to-use API design.  Perhaps vcs_info
should start setting $reply and deprecate those global variables?  They
_are_ needed for the PROMPT_SUBST way of using vcs_info, though…

Cheers,

Daniel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-14 12:05         ` Daniel Shahaf
  2021-04-14 13:17           ` Marlon
  2021-04-14 14:00           ` precmd hooks and $? Bart Schaefer
@ 2021-04-15 18:54           ` Marlon
  2021-04-15 21:34             ` Daniel Shahaf
  2 siblings, 1 reply; 65+ messages in thread
From: Marlon @ 2021-04-15 18:54 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1699 bytes --]

Patch attached, but not yet including Daniel’s suggested change below (since I still have questions about it). It includes an update to the docs, but note that I am not able to build those myself. I would much appreciate it f someone else could do that to test whether I did it correctly.

On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>> +++ b/Functions/Prompts/promptinit
>> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
>> 
>>        # 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}"
>> +       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"
> 
> All these should be documented, like prompt_${foo}_preview is.
> 
> Recommend to name these prompt_${foo}_bar-{isearch-exit,isearch-update,…,keymap-select}
> for some fixed value of «bar» to avoid namespace issues (i.e., name
> collisions between existing prompts and future hooks).

Wouldn’t that be a breaking change in the API, though? I mean, there are already 3rd party prompt themes that use the current prompt_${foo}_{isearch-exit,isearch-update,…,keymap-select} naming scheme. Also, isn’t the prefix prompt_${foo}_ already a namespace of sorts? Why change this?


[-- Attachment #2: 0001-Reset-ZLE-hooks-when-changing-prompt-themes.txt --]
[-- Type: text/plain, Size: 2722 bytes --]

From b60bfd135ae2631a3b28aaf81074594d0ec1f967 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Thu, 15 Apr 2021 21:50:36 +0300
Subject: [PATCH] Reset ZLE hooks when changing prompt themes

---
 Doc/Zsh/contrib.yo           |  8 ++++----
 Functions/Prompts/promptinit | 14 +++++++++-----
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 3c4fdded0..01809c0c4 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2032,10 +2032,10 @@ 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(Modify hooks)(
+Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended.  All hooks
+that follow the naming pattern tt(prompt_<theme>_<hook>) are automatically
+removed when the prompt theme changes or is disabled.
 )
 item(Declare cleanup)(
 If your function makes any other changes that should be undone when the
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index 37d69f100..b9d833c4b 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%}'
 }
@@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
 
        # 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}"
+       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
-- 
2.31.1


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-15  3:50               ` Marlon Richert
@ 2021-04-15 20:27                 ` Daniel Shahaf
  2021-04-15 23:42                 ` Daniel Shahaf
  1 sibling, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-15 20:27 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

[ The parent message made both technical points and meta/personnel/communication
points.  In this message I respond only to the former. ]

Marlon Richert wrote on Thu, Apr 15, 2021 at 06:50:47 +0300:
> On Wed, Apr 14, 2021 at 5:09 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > > Sure, but what should I call it, then? Just `marlon`? (Seeing as we already have `adam`, `bart`, etc. themes.)
> >
> > That'd work.  A name that describes the theme itself rather than its
> > origin would be even better (if the theme is accepted into zsh.git).
> 
> How about `simple` or `minimal` or something like that?
> 

These wouldn't be my first choices, given prompt_off_setup's contents.

> * You said my prompt theme should not set styles, but what methods
> should I then use to style the VCS part of the prompt?

workers/48577 and workers/48586 give one idea.

> > In any case, what you've implemented is that you re-set a style on the
> > first precmd after every chdir.  I don't think these semantics should be
> > implemented in the first place.
> 
> So, what do you think I should I do instead?

Instead of what?

> How do you think I can improve my code to be less "surprising"?

First, the semantics are surprising in themselves.  There's no obvious
reason why the theme would re-set check-for-staged-changes after every
chdir (and overwrite any user-set value of the style under that context
pattern).

Second, vcs_info_msg_0_ normally neither gets unset nor is used as a flag.

> > Document your code.
> 
> For which sections in particular would you like me to explain my
> motives?

None.  It's not the purpose of comments to explain the author's motives.
${histchars[3]} does not introduce whodunits ;-)

> I try to write my code to be self-documenting. However, as with all
> writing, one easily becomes blond to one's own typos. It would help a
> lot if you could tell me exactly what parts of the code you think need
> comments.

For starters, note that ${(v)_prompt_newuser_formats[(R)start:*]} don't
all undergo the same sequence of expansions, but there's zero hints to
that.  (And while there, compare 48574/0005.)

> > Make defaults overridable.
> 
> Did you read prompt_newuser_help() / the output of `prompt -h
> newuser`? It explains the mechanisms I've prodiv to override the
> defaults.
> 

Some of them, but see check-for-changes for a counter-example (which is
specifically documented as expensive, and has been mentioned in workers/48402
and in discussions about your proposed default zshrc in workers/48544).

Speaking of which, the help output is wrong because it instructs to set
styles for context patterns that aren't specific to that prompt theme.

> > (e.g., someone explicitly setting that style
> > to a false value for that same context, or for the context «:vcs_info*»,
> > which is less specific than the context you use and thus would be shadowed).
> 
> This theme is intended for persons who don't want to manually
> configure their VCS info separately from their prompt.

The point remains that the «:vcs_info:*» context patterns zstyle space
is global settings.  As it stands, the prompt theme will affect all uses
of vcs_info whilst the prompt theme is in effect, and even affect uses
of vcs_info after another prompt theme is loaded.

> My theme is also setting [R]PS(1|2|4). Do you see that, too, as
> overriding the user's settings?

No.  Per prompt_default_setup, for a prompt theme to set PS1 is as for
«echo hello world» to print «hello world
».

> If the user wants to configure those manually, then they can choose
> not to use this theme.

For PS1, sure, but PS1 isn't to a prompt theme as the «:vcs_info:*»
zstyle space is to a prompt theme.

> > > > That appears to be NIH.
> > >
> > > Sorry, but what does NIH stand for? (I’m guessing you don’t mean the National Institutes of Health.)
> >
> > Not Invented Here syndrome; cf. EEE :P
> 
> What exactly makes you think I have Not Invented Here syndrome? I am
> reusing vcs_info instead of rolling my own Git inspection code, am I
> not?

Here's the context again:

> > > > Your theme does _nothing_ with the 'unstaged' style other than
> > > > pass it through verbatim.  That appears to be NIH.

> > > > Why shouldn't the theme just advise people to set the vcs_info
> > > > directly?
> > >
> > > Because it’s a theme? If people wanted to style their vcs_info
> > > directly, then why would they use a theme?
> >
> > The point is, you're making people learn a different syntax for
> > identical functionality for zero benefit.
> 
> "Zero" benefit? vcs_info's documentation is not easy to read.

Then send a bug report.

> I am creating a simpler abstraction layer on top of a rather tricky
> API.

The *one* thing which your styles provide is the equivalent of «zstyle …
formats $a$b; zstyle … actionformats $a$c»; there's no other case where
«prompt_newuser_format» is called with ≥3 arguments.  For unstagedstr,
you provide just a rename; and for cont:left and cont:indent, which are
two knobs that are concatenated to each other and aren't used in any
other way, you just _add_ complexity.

No comment on whether or not vcs_info's API is "tricky".

> If I thought there was "zero" benefit in what I was doing, then I
> wouldn't have programmed it that way, would?

Presumably you _thought_ there was benefit in that approach — but your
reviewers don't happen to agree.  Don't take that personally.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-15 18:54           ` [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon
@ 2021-04-15 21:34             ` Daniel Shahaf
  2021-04-16 22:34               ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-15 21:34 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

Marlon wrote on Thu, Apr 15, 2021 at 21:54:48 +0300:
> Patch attached, but not yet including Daniel’s suggested change below (since I still have questions about it). It includes an update to the docs, but note that I am not able to build those myself. I would much appreciate it f someone else could do that to test whether I did it correctly.
> 
> On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> >> +++ b/Functions/Prompts/promptinit
> >> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
> >> 
> >>        # 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}"
> >> +       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"
> > 
> > All these should be documented, like prompt_${foo}_preview is.
> > 
> > Recommend to name these prompt_${foo}_bar-{isearch-exit,isearch-update,…,keymap-select}
> > for some fixed value of «bar» to avoid namespace issues (i.e., name
> > collisions between existing prompts and future hooks).
> 
> Wouldn’t that be a breaking change in the API, though?

No, it wouldn't, because those are add-zle-hook-widget hooks and the
current API only deals with add-zsh-hook hooks.

We could even recommend that add-zsh-hook hooks be named
prompt_${foo}_baz_{chpwd,…} for some fixed value of baz.  We don't even
have to change the code to support this (because the asterisk will match
«${foo}_baz» just fine); we just need to document the recommendation and
deprecate the previous recommended naming pattern.

> I mean, there are already 3rd party prompt themes that use the current prompt_${foo}_{isearch-exit,isearch-update,…,keymap-select} naming scheme.

And you're arguing that avoiding breaking code of third parties that
relied on a patch that (presumably) hadn't even been posted to
-workers@, never mind merged to master and released in a stable release,
trumps preventing namespace collisions for future users?

> Also, isn’t the prefix prompt_${foo}_ already a namespace of sorts? Why change this?

What if the foo theme declares a function called prompt_foo_lorem (or
even prompt_foo_ipsum_lorem) that _isn't_ an «add-*-hook lorem» hook
function, and later we start to to auto-register functions matching the
name pattern?

Or if we were to make «add-zsh-hook bar lorem» and «add-zle-hook-widget
bar ipsum» both valid, for a single value of bar, and a prompt theme
wanted to install both hooks _and_ name the functions «lorem» and «ipsum»
conventionally?

Or if someone wanted to quickly grep for add-zle-hook-widget callbacks?

> From b60bfd135ae2631a3b28aaf81074594d0ec1f967 Mon Sep 17 00:00:00 2001
> From: Marlon Richert <marlon.richert@gmail.com>
> Date: Thu, 15 Apr 2021 21:50:36 +0300
> Subject: [PATCH] Reset ZLE hooks when changing prompt themes
> 

Your mail didn't trigger workers/48587 (that's good).  I wonder why.
Probably because your MUA quoted-printable-escaped the first byte of the
From_ line.

> +++ b/Doc/Zsh/contrib.yo
> @@ -2032,10 +2032,10 @@ 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(Modify hooks)(
> +Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended.  All hooks
> +that follow the naming pattern tt(prompt_<theme>_<hook>) are automatically

This should be tt(prompt_)var(theme)tt(_)var(hook).

> +removed when the prompt theme changes or is disabled.

Add a pointer to the relevant section?  Something like
.
    ifzman(… Manipulating Hook Functions … above)ifnzman(noderef(Manipulating Hook Functions))
.
plus appropriate markup in the first branch.

> +++ 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%}'
>  }
> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
>  
>         # 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}"
> +       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

Hmm.  I'm not at all sure that this is sufficient.  There's a bunch of
reference to precmd and preexec in promptinit; it's possible that some
of these should also handle chpwd,periodic,zshaddhistory,zshexit
(a preëxisting issue) and the add-zle-hook-widget hook classes (an issue
this patch might be introducing).

Cheers,

Daniel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-15  3:50               ` Marlon Richert
  2021-04-15 20:27                 ` Daniel Shahaf
@ 2021-04-15 23:42                 ` Daniel Shahaf
  1 sibling, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-15 23:42 UTC (permalink / raw)
  To: Zsh hackers list

I responded to the meta/personnel/communication parts offlist, including
the parts that were posted under a new subject line.

% < $my_response perl -nE 'print unless 1.../^$/' | grep -v '^>' | wc | xargs -n1
112
564
3526

The one on-topic part was that I pointed out that start:staged should
use %%b for forward compatibility.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-15 11:11               ` Mikael Magnusson
  2021-04-15 16:44                 ` vcs_info's global variables (was: Re: [RFC][PATCH] `newuser` prompt theme) Daniel Shahaf
@ 2021-04-16 16:04                 ` Marlon
  2021-04-16 17:13                   ` Daniel Shahaf
  1 sibling, 1 reply; 65+ messages in thread
From: Marlon @ 2021-04-16 16:04 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list, Mikael Magnusson, Bart Schaefer

[-- Attachment #1: Type: text/plain, Size: 853 bytes --]

Alright, attached is a new attempt at this patch. Hopefully, this version is more to your liking.

Changes:
* The primary prompt can now be configured completely through `zstyle ':vcs_info:*:prompt_vcs:*’` statements.
* Accordingly, I renamed the theme to `vcs`. (Naming is hard.)
* I removed customization of the secondary prompt.
* I removed the weird shenanigans with $vcs_info_msg_0_ between chpwd & precmd. (I think I must’ve been tired when I originally wrote that code. It makes no sense to me now.)
* I added plenty of comments everywhere.

My thanks to Daniel for his thorough review and to Bart & Mikael for their zstyle/vcs_info tips. :)

Question for Daniel: If you’re going to add sysexits(3) to PRINT_EXIT_VALUE anyway (workers/48564), should I just get rid of prompt_vcs_precmd()? Or do you think it still adds value?


[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 26499 bytes --]

From 172e2a886fcb499fd1f0712836721366dc66cb74 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Thu, 15 Apr 2021 23:28:56 +0300
Subject: [PATCH] Add customizable `vcs` prompt theme

---
 0001-Add-customizable-vcs-prompt-theme.patch | 499 +++++++++++++++++++
 Functions/Prompts/prompt_vcs_setup           | 227 +++++++++
 2 files changed, 726 insertions(+)
 create mode 100644 0001-Add-customizable-vcs-prompt-theme.patch
 create mode 100644 Functions/Prompts/prompt_vcs_setup

diff --git a/0001-Add-customizable-vcs-prompt-theme.patch b/0001-Add-customizable-vcs-prompt-theme.patch
new file mode 100644
index 000000000..fde38a197
--- /dev/null
+++ b/0001-Add-customizable-vcs-prompt-theme.patch
@@ -0,0 +1,499 @@
+From 1d557059a1ae35be86f17832526198abde8d949d Mon Sep 17 00:00:00 2001
+From: Marlon Richert <marlon.richert@gmail.com>
+Date: Thu, 15 Apr 2021 23:28:56 +0300
+Subject: [PATCH] Add customizable `vcs` prompt theme
+
+---
+ 0001-Add-customizable-vcs-prompt-theme.txt | 245 +++++++++++++++++++++
+ Functions/Prompts/prompt_vcs_setup         | 227 +++++++++++++++++++
+ 2 files changed, 472 insertions(+)
+ create mode 100644 0001-Add-customizable-vcs-prompt-theme.txt
+ create mode 100644 Functions/Prompts/prompt_vcs_setup
+
+diff --git a/0001-Add-customizable-vcs-prompt-theme.txt b/0001-Add-customizable-vcs-prompt-theme.txt
+new file mode 100644
+index 000000000..980f4a317
+--- /dev/null
++++ b/0001-Add-customizable-vcs-prompt-theme.txt
+@@ -0,0 +1,245 @@
++From 1d34a81c3b09228deaf9de599e42611ec4fe21dd Mon Sep 17 00:00:00 2001
++From: Marlon Richert <marlon.richert@gmail.com>
++Date: Thu, 15 Apr 2021 23:28:56 +0300
++Subject: [PATCH] Add customizable `vcs` prompt theme
++
++---
++ Functions/Prompts/prompt_vcs_setup | 226 +++++++++++++++++++++++++++++
++ 1 file changed, 226 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..218e6a5e2
++--- /dev/null
+++++ b/Functions/Prompts/prompt_vcs_setup
++@@ -0,0 +1,226 @@
+++##
+++# Prompt that can be customized through vcs_info
+++#
+++
+++autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+++
+++# Standardized exit codes. See `man 3 sysexits`.
+++if [[ ${(t)sysexits} != *readonly* ]]; then
+++  # Avoid error in case this has been set already.
+++  readonly -ga sysexits=(
+++      USAGE
+++      DATAERR
+++      NOINPUT
+++      NOUSER
+++      NOHOST
+++      UNAVAILABLE
+++      SOFTWARE
+++      OSERR
+++      OSFILE
+++      CANTCREAT
+++      IOERR
+++      TEMPFAIL
+++      PROTOCOL
+++      NOPERM
+++      CONFIG
+++  )
+++fi
+++
+++# Prompt segments
+++readonly -gHA _prompt_vcs_defaults=(
+++    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'
+++)
+++
+++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 these,
+++  # * the first string is used for \$PS1 after changing dirs,
+++  # * the second string is used for \$PS1 otherwise, and
+++  # * the third string is used for \$RPS1 and updated asynchronously.
+++  # In these, %v expands to the name (if any) & number of the last exit code.
+++  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \
+++      "${${:-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+++      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+++      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+++  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+++      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+++      ${(q+)_prompt_vcs_defaults[start:left]} \\
+++      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
+++  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+++      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+++      ${(q+)_prompt_vcs_defaults[start:left]} \\
+++      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
+++
+++  # These set the values of %c and %u, respectively:
+++  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
+++  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
+++
+++For more info on the config 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_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+++      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+++      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+++      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+++      "$_prompt_vcs_defaults[start:left]" \
+++      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
+++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+++      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+++      "$_prompt_vcs_defaults[start:left]" \
+++      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
+++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+++      "$_prompt_vcs_defaults[start:staged]"
+++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+++      "$_prompt_vcs_defaults[start: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
+++
+++  local -i fd=-1; local -a reply
+++  exec {fd}< <(
+++    # Fetch only staged changes at this point, for performance reasons.
+++    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
+++    _prompt_vcs_info
+++  )
+++  IFS=$'\0' read -Aru "$fd"
+++  typeset -ga __prompt_vcs_info_msg_=( "${(@Q)reply}" )
+++  exec {fd}<&-
+++
+++  PS1="$__prompt_vcs_info_msg_[1]"
+++  RPS1="$__prompt_vcs_info_msg_[3]"
+++}
+++
+++prompt_vcs_precmd() {
+++  local exitstatus=$? # Exit status of last command
+++  emulate -L zsh
+++
+++  # Assign human-friendly exit status name to %v.
+++  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
+++}
+++
+++prompt_vcs_line-init() {
+++  emulate -L zsh
+++
+++  case $CONTEXT in
+++    start ) # (R)PS1
+++      # Asynchronously check for unstaged changes. Do this here & not in
+++      # precmd, so you can press Enter on an empty line to update VCS info.
+++      local -i fd=-1
+++      exec {fd}< <(
+++        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
+++        _prompt_vcs_info
+++        print -r -- "$PWD"
+++      )
+++
+++      # Add callback. Needs to be a widget, so we can refresh the prompt.
+++      zle -Fw "$fd" prompt_vcs_fd-handler
+++      ;;
+++    cont )  # (R)PS2
+++      # Indent left continuation prompt for each open shell construct.
+++      local fmt="$_prompt_vcs_defaults[cont:indent]"
+++      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
+++      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
+++
+++      RPS2="$_prompt_vcs_defaults[cont:right]"
+++      ;;
+++  esac
+++}
+++
+++# Callback widget function for our async fetch of unstaged VCS changes
+++prompt_vcs_fd-handler() {
+++  emulate -L zsh
+++
+++  local -i fd=$1; local sig=$2; local -a reply
+++  {
+++    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+++
+++    [[ $sig != (|hup) ]] &&
+++        return  # Error occured
+++
+++    IFS=$'\0' read -Aru "$fd"
+++
+++    [[ $reply[-1] != $PWD ]] &&
+++        return  # Abort if the info is not for the current dir.
+++  } always {
+++    exec {fd}<&-
+++  }
+++  shift -p reply
+++  typeset -ga __prompt_vcs_info_msg_=( "${(@Q)reply}" )
+++  RPS1="$__prompt_vcs_info_msg_[3]"
+++  zle .reset-prompt
+++}
+++
+++prompt_vcs_line-finish() {
+++  emulate -L zsh
+++  PS1="$__prompt_vcs_info_msg_[2]"
+++}
+++
+++prompt_vcs_setup() {
+++  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
+++
+++  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
+++  )
+++
+++  add-zsh-hook chpwd  prompt_vcs_chpwd
+++  add-zsh-hook precmd prompt_vcs_precmd
+++  add-zle-hook-widget line-init   prompt_vcs_line-init
+++  add-zle-hook-widget line-finish prompt_vcs_line-finish
+++  zle -N prompt_vcs_fd-handler # Callback widget for async VCS update.
+++
+++  prompt_vcs_chpwd
+++}
+++
+++prompt_vcs_setup "$@"
++-- 
++2.31.1
++
+diff --git a/Functions/Prompts/prompt_vcs_setup b/Functions/Prompts/prompt_vcs_setup
+new file mode 100644
+index 000000000..66f167f49
+--- /dev/null
++++ b/Functions/Prompts/prompt_vcs_setup
+@@ -0,0 +1,227 @@
++##
++# Prompt that can be customized through vcs_info
++#
++
++autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
++
++# Standardized exit codes. See `man 3 sysexits`.
++if [[ ${(t)sysexits} != *readonly* ]]; then
++  # Avoid error in case this has been set already.
++  readonly -ga sysexits=(
++      USAGE
++      DATAERR
++      NOINPUT
++      NOUSER
++      NOHOST
++      UNAVAILABLE
++      SOFTWARE
++      OSERR
++      OSFILE
++      CANTCREAT
++      IOERR
++      TEMPFAIL
++      PROTOCOL
++      NOPERM
++      CONFIG
++  )
++fi
++
++# Prompt segments
++readonly -gHA _prompt_vcs_defaults=(
++    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'
++)
++
++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 these,
++  # * the first string is used for \$PS1 after changing dirs,
++  # * the second string is used for \$PS1 otherwise, and
++  # * the third string is used for \$RPS1 and updated asynchronously.
++  # In these, %v expands to the name (if any) & number of the last exit code.
++  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \
++      "${${:-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
++      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
++      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
++  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
++      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
++      ${(q+)_prompt_vcs_defaults[start:left]} \\
++      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
++  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
++      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
++      ${(q+)_prompt_vcs_defaults[start:left]} \\
++      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
++
++  # These set the values of %c and %u, respectively:
++  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
++  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
++
++For more info on the config 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_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
++      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
++      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
++      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
++      "$_prompt_vcs_defaults[start:left]" \
++      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
++      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
++      "$_prompt_vcs_defaults[start:left]" \
++      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
++      "$_prompt_vcs_defaults[start:staged]"
++  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
++      "$_prompt_vcs_defaults[start: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
++
++  local -i fd=-1; local -a reply
++  exec {fd}< <(
++    # Fetch only staged changes at this point, for performance reasons.
++    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
++    _prompt_vcs_info
++  )
++  IFS=$'\0' read -Aru "$fd"
++  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
++  exec {fd}<&-
++
++  PS1="$_prompt_vcs_info_msg_[1]"
++  RPS1="$_prompt_vcs_info_msg_[3]"
++}
++
++prompt_vcs_precmd() {
++  local exitstatus=$? # Exit status of last command
++  emulate -L zsh
++
++  # Assign human-friendly exit status string to %v.
++  psvar[1]=
++  case $exitstatus in
++    ( <128-> )
++      psvar[1]="SIG$signals[exitstatus-127] "
++      ;|
++    ( <64-78> )
++      psvar[1]="EX_$sysexits[exitstatus-63] "
++      ;|
++    ( <1-> )
++      psvar[1]+="($exitstatus)"
++      ;;
++    # No need to show EX_OK.
++  esac
++}
++
++prompt_vcs_line-init() {
++  emulate -L zsh
++
++  case $CONTEXT in
++    start ) # (R)PS1
++      # Asynchronously check for unstaged changes. Do this here & not in
++      # precmd, so you can press Enter on an empty line to update VCS info.
++      local -i fd=-1
++      exec {fd}< <(
++        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
++        _prompt_vcs_info
++        print -r -- "$PWD"
++      )
++
++      # Add callback. Needs to be a widget, so we can refresh the prompt.
++      zle -Fw "$fd" prompt_vcs_fd-handler
++      ;;
++    cont )  # (R)PS2
++      # Indent left continuation prompt for each open shell construct.
++      local fmt="$_prompt_vcs_defaults[cont:indent]"
++      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
++      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
++
++      RPS2="$_prompt_vcs_defaults[cont:right]"
++      ;;
++  esac
++}
++
++# Callback widget function for our async fetch of unstaged VCS changes
++prompt_vcs_fd-handler() {
++  emulate -L zsh
++
++  local -i fd=$1; local sig=$2; local -a reply
++  {
++    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
++
++    [[ $sig != (|hup) ]] &&
++        return  # Error occured
++
++    IFS=$'\0' read -Aru "$fd"
++
++    [[ $reply[-1] != $PWD ]] &&
++        return  # Abort if the info is not for the current dir.
++  } always {
++    exec {fd}<&-
++  }
++  shift -p reply
++  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
++  RPS1="$_prompt_vcs_info_msg_[3]"
++  zle .reset-prompt
++}
++
++prompt_vcs_line-finish() {
++  emulate -L zsh
++  PS1="$_prompt_vcs_info_msg_[2]"
++}
++
++prompt_vcs_setup() {
++  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
++
++  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
++  )
++
++  add-zsh-hook chpwd    prompt_vcs_chpwd
++  add-zsh-hook precmd   prompt_vcs_precmd
++  add-zle-hook-widget line-init   prompt_vcs_line-init
++  add-zle-hook-widget line-finish prompt_vcs_line-finish
++  zle -N prompt_vcs_fd-handler # Callback widget for async VCS update.
++
++  prompt_vcs_chpwd
++}
++
++prompt_vcs_setup "$@"
+-- 
+2.31.1
+
diff --git a/Functions/Prompts/prompt_vcs_setup b/Functions/Prompts/prompt_vcs_setup
new file mode 100644
index 000000000..66f167f49
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,227 @@
+##
+# Prompt that can be customized through vcs_info
+#
+
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Standardized exit codes. See `man 3 sysexits`.
+if [[ ${(t)sysexits} != *readonly* ]]; then
+  # Avoid error in case this has been set already.
+  readonly -ga sysexits=(
+      USAGE
+      DATAERR
+      NOINPUT
+      NOUSER
+      NOHOST
+      UNAVAILABLE
+      SOFTWARE
+      OSERR
+      OSFILE
+      CANTCREAT
+      IOERR
+      TEMPFAIL
+      PROTOCOL
+      NOPERM
+      CONFIG
+  )
+fi
+
+# Prompt segments
+readonly -gHA _prompt_vcs_defaults=(
+    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'
+)
+
+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 these,
+  # * the first string is used for \$PS1 after changing dirs,
+  # * the second string is used for \$PS1 otherwise, and
+  # * the third string is used for \$RPS1 and updated asynchronously.
+  # In these, %v expands to the name (if any) & number of the last exit code.
+  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \
+      "${${:-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
+
+  # These set the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
+
+For more info on the config 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_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_defaults[start:staged]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_defaults[start: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
+
+  local -i fd=-1; local -a reply
+  exec {fd}< <(
+    # Fetch only staged changes at this point, for performance reasons.
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
+    _prompt_vcs_info
+  )
+  IFS=$'\0' read -Aru "$fd"
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  exec {fd}<&-
+
+  PS1="$_prompt_vcs_info_msg_[1]"
+  RPS1="$_prompt_vcs_info_msg_[3]"
+}
+
+prompt_vcs_precmd() {
+  local exitstatus=$? # Exit status of last command
+  emulate -L zsh
+
+  # Assign human-friendly exit status string to %v.
+  psvar[1]=
+  case $exitstatus in
+    ( <128-> )
+      psvar[1]="SIG$signals[exitstatus-127] "
+      ;|
+    ( <64-78> )
+      psvar[1]="EX_$sysexits[exitstatus-63] "
+      ;|
+    ( <1-> )
+      psvar[1]+="($exitstatus)"
+      ;;
+    # No need to show EX_OK.
+  esac
+}
+
+prompt_vcs_line-init() {
+  emulate -L zsh
+
+  case $CONTEXT in
+    start ) # (R)PS1
+      # Asynchronously check for unstaged changes. Do this here & not in
+      # precmd, so you can press Enter on an empty line to update VCS info.
+      local -i fd=-1
+      exec {fd}< <(
+        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
+        _prompt_vcs_info
+        print -r -- "$PWD"
+      )
+
+      # Add callback. Needs to be a widget, so we can refresh the prompt.
+      zle -Fw "$fd" prompt_vcs_fd-handler
+      ;;
+    cont )  # (R)PS2
+      # Indent left continuation prompt for each open shell construct.
+      local fmt="$_prompt_vcs_defaults[cont:indent]"
+      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
+      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
+
+      RPS2="$_prompt_vcs_defaults[cont:right]"
+      ;;
+  esac
+}
+
+# Callback widget function for our async fetch of unstaged VCS changes
+prompt_vcs_fd-handler() {
+  emulate -L zsh
+
+  local -i fd=$1; local sig=$2; local -a reply
+  {
+    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+
+    [[ $sig != (|hup) ]] &&
+        return  # Error occured
+
+    IFS=$'\0' read -Aru "$fd"
+
+    [[ $reply[-1] != $PWD ]] &&
+        return  # Abort if the info is not for the current dir.
+  } always {
+    exec {fd}<&-
+  }
+  shift -p reply
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  RPS1="$_prompt_vcs_info_msg_[3]"
+  zle .reset-prompt
+}
+
+prompt_vcs_line-finish() {
+  emulate -L zsh
+  PS1="$_prompt_vcs_info_msg_[2]"
+}
+
+prompt_vcs_setup() {
+  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
+
+  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
+  )
+
+  add-zsh-hook chpwd    prompt_vcs_chpwd
+  add-zsh-hook precmd   prompt_vcs_precmd
+  add-zle-hook-widget line-init   prompt_vcs_line-init
+  add-zle-hook-widget line-finish prompt_vcs_line-finish
+  zle -N prompt_vcs_fd-handler # Callback widget for async VCS update.
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.31.1


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-16 16:04                 ` [RFC][PATCH] `newuser` prompt theme Marlon
@ 2021-04-16 17:13                   ` Daniel Shahaf
  2021-04-16 19:19                     ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-16 17:13 UTC (permalink / raw)
  To: Marlon; +Cc: Zsh hackers list

Marlon wrote on Fri, Apr 16, 2021 at 19:04:06 +0300:
> Question for Daniel: If you’re going to add sysexits(3) to PRINT_EXIT_VALUE anyway (workers/48564), should I just get rid of prompt_vcs_precmd()? Or do you think it still adds value?

IMO keep that function.  We can always simplify that function if and when
sysexits(3) PRINT_EXIT_VALUE support is added.

You seem to have sent the patch three times, nested.  Which one should
be reviewed?

> From 172e2a886fcb499fd1f0712836721366dc66cb74 Mon Sep 17 00:00:00 2001
> From: Marlon Richert <marlon.richert@gmail.com>
> Date: Thu, 15 Apr 2021 23:28:56 +0300
> Subject: [PATCH] Add customizable `vcs` prompt theme
> 
> ---
>  0001-Add-customizable-vcs-prompt-theme.patch | 499 +++++++++++++++++++
>  Functions/Prompts/prompt_vcs_setup           | 227 +++++++++
> 
> +++ b/0001-Add-customizable-vcs-prompt-theme.patch
> @@ -0,0 +1,499 @@
> +From 1d557059a1ae35be86f17832526198abde8d949d Mon Sep 17 00:00:00 2001
> +From: Marlon Richert <marlon.richert@gmail.com>
> +Date: Thu, 15 Apr 2021 23:28:56 +0300
> +Subject: [PATCH] Add customizable `vcs` prompt theme
> +
> +---
> + 0001-Add-customizable-vcs-prompt-theme.txt | 245 +++++++++++++++++++++
> + Functions/Prompts/prompt_vcs_setup         | 227 +++++++++++++++++++
> +
> +diff --git a/0001-Add-customizable-vcs-prompt-theme.txt b/0001-Add-customizable-vcs-prompt-theme.txt
> +new file mode 100644
> +index 000000000..980f4a317
> +--- /dev/null
> ++++ b/0001-Add-customizable-vcs-prompt-theme.txt
> +@@ -0,0 +1,245 @@
> ++From 1d34a81c3b09228deaf9de599e42611ec4fe21dd Mon Sep 17 00:00:00 2001
> ++From: Marlon Richert <marlon.richert@gmail.com>
> ++Date: Thu, 15 Apr 2021 23:28:56 +0300
> ++Subject: [PATCH] Add customizable `vcs` prompt theme
> ++
> +++++ b/Functions/Prompts/prompt_vcs_setup
> ++@@ -0,0 +1,226 @@
> ++++ b/Functions/Prompts/prompt_vcs_setup
> +@@ -0,0 +1,227 @@
> +++ b/Functions/Prompts/prompt_vcs_setup
> @@ -0,0 +1,227 @@


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-16 17:13                   ` Daniel Shahaf
@ 2021-04-16 19:19                     ` Marlon Richert
  2021-04-16 19:30                       ` Daniel Shahaf
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-04-16 19:19 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 615 bytes --]


> On 16 Apr 2021, at 20:13, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> 
> Marlon wrote on Fri, Apr 16, 2021 at 19:04:06 +0300:
>> Question for Daniel: If you’re going to add sysexits(3) to PRINT_EXIT_VALUE anyway (workers/48564), should I just get rid of prompt_vcs_precmd()? Or do you think it still adds value?
> 
> IMO keep that function.  We can always simplify that function if and when
> sysexits(3) PRINT_EXIT_VALUE support is added.
> 
> You seem to have sent the patch three times, nested.  Which one should
> be reviewed?

Whoops! Here’s the patch again, but this time just once.


[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 8348 bytes --]

From f11694bc0260de5d4572fdacb0f41fc748bd7155 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Thu, 15 Apr 2021 23:28:56 +0300
Subject: [PATCH] Add customizable `vcs` prompt theme

---
 Functions/Prompts/prompt_vcs_setup | 227 +++++++++++++++++++++++++++++
 1 file changed, 227 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..66f167f49
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,227 @@
+##
+# Prompt that can be customized through vcs_info
+#
+
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Standardized exit codes. See `man 3 sysexits`.
+if [[ ${(t)sysexits} != *readonly* ]]; then
+  # Avoid error in case this has been set already.
+  readonly -ga sysexits=(
+      USAGE
+      DATAERR
+      NOINPUT
+      NOUSER
+      NOHOST
+      UNAVAILABLE
+      SOFTWARE
+      OSERR
+      OSFILE
+      CANTCREAT
+      IOERR
+      TEMPFAIL
+      PROTOCOL
+      NOPERM
+      CONFIG
+  )
+fi
+
+# Prompt segments
+readonly -gHA _prompt_vcs_defaults=(
+    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'
+)
+
+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 these,
+  # * the first string is used for \$PS1 after changing dirs,
+  # * the second string is used for \$PS1 otherwise, and
+  # * the third string is used for \$RPS1 and updated asynchronously.
+  # In these, %v expands to the name (if any) & number of the last exit code.
+  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \
+      "${${:-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
+
+  # These set the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
+
+For more info on the config 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_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_defaults[start:staged]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_defaults[start: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
+
+  local -i fd=-1; local -a reply
+  exec {fd}< <(
+    # Fetch only staged changes at this point, for performance reasons.
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
+    _prompt_vcs_info
+  )
+  IFS=$'\0' read -Aru "$fd"
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  exec {fd}<&-
+
+  PS1="$_prompt_vcs_info_msg_[1]"
+  RPS1="$_prompt_vcs_info_msg_[3]"
+}
+
+prompt_vcs_precmd() {
+  local exitstatus=$? # Exit status of last command
+  emulate -L zsh
+
+  # Assign human-friendly exit status string to %v.
+  psvar[1]=
+  case $exitstatus in
+    ( <128-> )
+      psvar[1]="SIG$signals[exitstatus-127] "
+      ;|
+    ( <64-78> )
+      psvar[1]="EX_$sysexits[exitstatus-63] "
+      ;|
+    ( <1-> )
+      psvar[1]+="($exitstatus)"
+      ;;
+    # No need to show EX_OK.
+  esac
+}
+
+prompt_vcs_line-init() {
+  emulate -L zsh
+
+  case $CONTEXT in
+    start ) # (R)PS1
+      # Asynchronously check for unstaged changes. Do this here & not in
+      # precmd, so you can press Enter on an empty line to update VCS info.
+      local -i fd=-1
+      exec {fd}< <(
+        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
+        _prompt_vcs_info
+        print -r -- "$PWD"
+      )
+
+      # Add callback. Needs to be a widget, so we can refresh the prompt.
+      zle -Fw "$fd" prompt_vcs_fd-handler
+      ;;
+    cont )  # (R)PS2
+      # Indent left continuation prompt for each open shell construct.
+      local fmt="$_prompt_vcs_defaults[cont:indent]"
+      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
+      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
+
+      RPS2="$_prompt_vcs_defaults[cont:right]"
+      ;;
+  esac
+}
+
+# Callback widget function for our async fetch of unstaged VCS changes
+prompt_vcs_fd-handler() {
+  emulate -L zsh
+
+  local -i fd=$1; local sig=$2; local -a reply
+  {
+    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+
+    [[ $sig != (|hup) ]] &&
+        return  # Error occured
+
+    IFS=$'\0' read -Aru "$fd"
+
+    [[ $reply[-1] != $PWD ]] &&
+        return  # Abort if the info is not for the current dir.
+  } always {
+    exec {fd}<&-
+  }
+  shift -p reply
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  RPS1="$_prompt_vcs_info_msg_[3]"
+  zle .reset-prompt
+}
+
+prompt_vcs_line-finish() {
+  emulate -L zsh
+  PS1="$_prompt_vcs_info_msg_[2]"
+}
+
+prompt_vcs_setup() {
+  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
+
+  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
+  )
+
+  add-zsh-hook chpwd    prompt_vcs_chpwd
+  add-zsh-hook precmd   prompt_vcs_precmd
+  add-zle-hook-widget line-init   prompt_vcs_line-init
+  add-zle-hook-widget line-finish prompt_vcs_line-finish
+  zle -N prompt_vcs_fd-handler # Callback widget for async VCS update.
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.31.1


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-16 19:19                     ` Marlon Richert
@ 2021-04-16 19:30                       ` Daniel Shahaf
  2021-04-19 16:46                         ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-16 19:30 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

> +prompt_vcs_chpwd() {
> +  exec {fd}< <(
> +    # Fetch only staged changes at this point, for performance reasons.
> +    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes

Should this set «check-for-changes no», to override a «yes» that may
have been explicitly set on a less-specific context pattern?

> +    _prompt_vcs_info
> +  )


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-15 21:34             ` Daniel Shahaf
@ 2021-04-16 22:34               ` Marlon Richert
  2021-04-25 16:08                 ` Lawrence Velázquez
  2021-05-02 17:59                 ` Bart Schaefer
  0 siblings, 2 replies; 65+ messages in thread
From: Marlon Richert @ 2021-04-16 22:34 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1522 bytes --]

On 16 Apr 2021, at 00:34, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> Marlon wrote on Thu, Apr 15, 2021 at 21:54:48 +0300:
>> +that follow the naming pattern tt(prompt_<theme>_<hook>) are automatically
> 
> This should be tt(prompt_)var(theme)tt(_)var(hook).
> 
>> +removed when the prompt theme changes or is disabled.
> 
> Add a pointer to the relevant section?  Something like
> .
>    ifzman(… Manipulating Hook Functions … above)ifnzman(noderef(Manipulating Hook Functions))
> .
> plus appropriate markup in the first branch.

Done and done.


>> -       for hook in chpwd precmd preexec periodic zshaddhistory zshexit; do
>> -         add-zsh-hook -D "${hook}" "prompt_*_${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"
> Hmm.  I'm not at all sure that this is sufficient.  There's a bunch of
> reference to precmd and preexec in promptinit; it's possible that some
> of these should also handle chpwd,periodic,zshaddhistory,zshexit
> (a preëxisting issue) and the add-zle-hook-widget hook classes (an issue
> this patch might be introducing).


Attached is a new version of the patch that handles _all the things._ \o/




[-- Attachment #2.1: Type: text/html, Size: 13492 bytes --]

[-- Attachment #2.2: 0001-Reset-ZLE-hooks-when-changing-prompt-themes.txt --]
[-- Type: text/plain, Size: 10459 bytes --]

From ae73759d82da603e6e88e1a95d91274451defc91 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Fri, 16 Apr 2021 23:00:44 +0300
Subject: [PATCH] Reset ZLE hooks when changing prompt themes

---
 Doc/Zsh/contrib.yo           |  10 ++-
 Functions/Prompts/promptinit | 167 +++++++++++++++--------------------
 2 files changed, 79 insertions(+), 98 deletions(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 3c4fdded0..6e33cd6f9 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2032,10 +2032,12 @@ 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(Modify hooks)(
+Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended (see
+ifzman(the bf(Manipulating Hook Functions) section above)\
+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)(
 If your function makes any other changes that should be undone when the
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index 37d69f100..a6c9e31dd 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%}'
 }
@@ -47,38 +46,23 @@ prompt_preview_safely() {
     return
   fi
 
-  # This handles all the stuff from the default :prompt-theme restore
-  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 prompt_preview_restore
-  local -aLl +h zle_highlight
+  # 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
 
-  {
-    # Save and clear current restore-point if any
-    zstyle -g prompt_preview_restore :prompt-theme restore
-    {
-      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.
+    # If we can't find a _preview function, run the _setup function to see if
+    # it will create one.
+    typeset +f prompt_${1}_preview >&/dev/null ||
       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_restore )) &&
-      zstyle -e :prompt-theme restore "${prompt_preview_restore[@]}"
-  }
+    # ...then try again.
+    if typeset +f prompt_${1}_preview >&/dev/null; then
+      prompt_${1}_preview "$@[2,-1]"
+    else
+      prompt_preview_theme "$@"
+    fi
+  )
 }
 
 set_prompt() {
@@ -97,21 +81,6 @@ Options:
 Use prompt -h <theme> 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 +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
     c) if [[ -n $prompt_theme ]]; then
          print -n "Current prompt theme"
@@ -123,21 +92,26 @@ Use prompt -h <theme> for help on specific themes.'
        return
        ;;
     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
-           # 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."
+
+           # If we can't find a _help function, run the _setup function to see
+           # if it will create one.
+           typeset +f prompt_$2_help >/dev/null ||
+               prompt_$2_setup
+
+           # ...then try again.
+           if typeset +f 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
@@ -178,8 +152,13 @@ Use prompt -h <theme> for help on specific themes.'
 
        # 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}"
+       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
@@ -192,11 +171,8 @@ Use prompt -h <theme> for help on specific themes.'
 
 prompt_cleanup () {
   local -a cleanup_hooks theme_active
-  if ! zstyle -g cleanup_hooks :prompt-theme cleanup
-  then
-    (( $+prompt_preview_restore == 0 )) &&
-    if ! zstyle -g theme_active :prompt-theme restore
-    then
+  if ! zstyle -g cleanup_hooks :prompt-theme cleanup; then
+    if ! zstyle -g theme_active :prompt-theme restore; then
       print -u2 "prompt_cleanup: no prompt theme active"
       return 1
     fi
@@ -225,22 +201,23 @@ prompt () {
     [[ -o promptpercent ]] && prompt_opts+=(percent)
     [[ -o promptsp ]] && prompt_opts+=(sp)
     [[ -o promptsubst ]] && prompt_opts+=(subst)
-    zstyle -e :prompt-theme restore \
-        'zstyle -d :prompt-theme restore;' \
-	'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)'
+    zstyle -e :prompt-theme restore "
+        zstyle -d :prompt-theme restore
+        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}}
+        $( add-zsh-hook -L )
+        $( add-zle-hook-widget -L )
+        prompt_opts=( $prompt_opts[*] )
+        reply=( yes )
+    "
   }
   set_prompt "$@"
 
@@ -253,12 +230,6 @@ prompt () {
 prompt_preview_theme () {
   emulate -L zsh
 
-  # Check for proper state handling
-  (( $+prompt_preview_restore )) || {
-    prompt_preview_safely "$@"
-    return
-  }
-
   # Minimal preview for prompts that don't supply one
   local -a prompt_opts
   print -n "$1 theme"
@@ -268,12 +239,20 @@ prompt_preview_theme () {
   prompt_${1}_setup "$@[2,-1]"
   (( ${#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]} ]] &&
-    prompt_${1}_precmd
-  [[ -o promptcr ]] && print -n $'\r'; :
-  print -P "${PS1}command arg1 arg2 ... argn"
+      prompt_${1}_precmd
+
+  # 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]} ]] &&
-    prompt_${1}_preexec
+      prompt_${1}_preexec
 }
 
 [[ -o kshautoload ]] || promptinit "$@"
-- 
2.31.1


[-- Attachment #2.3: Type: text/html, Size: 272 bytes --]

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-16 19:30                       ` Daniel Shahaf
@ 2021-04-19 16:46                         ` Marlon Richert
  2021-05-02 17:18                           ` Lawrence Velázquez
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-04-19 16:46 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 485 bytes --]

On 16 Apr 2021, at 22:30, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> 
>> +prompt_vcs_chpwd() {
>> +  exec {fd}< <(
>> +    # Fetch only staged changes at this point, for performance reasons.
>> +    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
> 
> Should this set «check-for-changes no», to override a «yes» that may
> have been explicitly set on a less-specific context pattern?

Yes, that would make sense. Added. See attachment.


[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 8421 bytes --]

From 12867d2439f3c3f550190438b8b7cb53441bfc42 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Mon, 19 Apr 2021 19:43:16 +0300
Subject: [PATCH] Add customizable `vcs` prompt theme

---
 Functions/Prompts/prompt_vcs_setup | 228 +++++++++++++++++++++++++++++
 1 file changed, 228 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..1ab73da2b
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,228 @@
+##
+# Prompt that can be customized through vcs_info
+#
+
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Standardized exit codes. See `man 3 sysexits`.
+if [[ ${(t)sysexits} != *readonly* ]]; then
+  # Avoid error in case this has been set already.
+  readonly -ga sysexits=(
+      USAGE
+      DATAERR
+      NOINPUT
+      NOUSER
+      NOHOST
+      UNAVAILABLE
+      SOFTWARE
+      OSERR
+      OSFILE
+      CANTCREAT
+      IOERR
+      TEMPFAIL
+      PROTOCOL
+      NOPERM
+      CONFIG
+  )
+fi
+
+# Prompt segments
+readonly -gHA _prompt_vcs_defaults=(
+    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'
+)
+
+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 these,
+  # * the first string is used for \$PS1 after changing dirs,
+  # * the second string is used for \$PS1 otherwise, and
+  # * the third string is used for \$RPS1 and updated asynchronously.
+  # In these, %v expands to the name (if any) & number of the last exit code.
+  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \
+      "${${:-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+):-$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
+
+  # These set the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
+
+For more info on the config 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_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]}//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_defaults[start:chpwd]$_prompt_vcs_defaults[start:left]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_defaults[start:staged]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_defaults[start: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
+
+  local -i fd=-1; local -a reply
+  exec {fd}< <(
+    # Fetch only staged changes at this point, for performance reasons.
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes no
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
+    _prompt_vcs_info
+  )
+  IFS=$'\0' read -Aru "$fd"
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  exec {fd}<&-
+
+  PS1="$_prompt_vcs_info_msg_[1]"
+  RPS1="$_prompt_vcs_info_msg_[3]"
+}
+
+prompt_vcs_precmd() {
+  local exitstatus=$? # Exit status of last command
+  emulate -L zsh
+
+  # Assign human-friendly exit status string to %v.
+  psvar[1]=
+  case $exitstatus in
+    ( <128-> )
+      psvar[1]="SIG$signals[exitstatus-127] "
+      ;|
+    ( <64-78> )
+      psvar[1]="EX_$sysexits[exitstatus-63] "
+      ;|
+    ( <1-> )
+      psvar[1]+="($exitstatus)"
+      ;;
+    # No need to show EX_OK.
+  esac
+}
+
+prompt_vcs_line-init() {
+  emulate -L zsh
+
+  case $CONTEXT in
+    start ) # (R)PS1
+      # Asynchronously check for unstaged changes. Do this here & not in
+      # precmd, so you can press Enter on an empty line to update VCS info.
+      local -i fd=-1
+      exec {fd}< <(
+        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
+        _prompt_vcs_info
+        print -r -- "$PWD"
+      )
+
+      # Add callback. Needs to be a widget, so we can refresh the prompt.
+      zle -Fw "$fd" prompt_vcs_fd-handler
+      ;;
+    cont )  # (R)PS2
+      # Indent left continuation prompt for each open shell construct.
+      local fmt="$_prompt_vcs_defaults[cont:indent]"
+      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
+      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
+
+      RPS2="$_prompt_vcs_defaults[cont:right]"
+      ;;
+  esac
+}
+
+# Callback widget function for our async fetch of unstaged VCS changes
+prompt_vcs_fd-handler() {
+  emulate -L zsh
+
+  local -i fd=$1; local sig=$2; local -a reply
+  {
+    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+
+    [[ $sig != (|hup) ]] &&
+        return  # Error occured
+
+    IFS=$'\0' read -Aru "$fd"
+
+    [[ $reply[-1] != $PWD ]] &&
+        return  # Abort if the info is not for the current dir.
+  } always {
+    exec {fd}<&-
+  }
+  shift -p reply
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  RPS1="$_prompt_vcs_info_msg_[3]"
+  zle .reset-prompt
+}
+
+prompt_vcs_line-finish() {
+  emulate -L zsh
+  PS1="$_prompt_vcs_info_msg_[2]"
+}
+
+prompt_vcs_setup() {
+  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
+
+  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
+  )
+
+  add-zsh-hook chpwd    prompt_vcs_chpwd
+  add-zsh-hook precmd   prompt_vcs_precmd
+  add-zle-hook-widget line-init   prompt_vcs_line-init
+  add-zle-hook-widget line-finish prompt_vcs_line-finish
+  zle -N prompt_vcs_fd-handler # Callback widget for async VCS update.
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.31.1


[-- Attachment #3: Type: text/plain, Size: 2 bytes --]




^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-16 22:34               ` Marlon Richert
@ 2021-04-25 16:08                 ` Lawrence Velázquez
  2021-05-02 17:03                   ` Lawrence Velázquez
  2021-05-02 17:59                 ` Bart Schaefer
  1 sibling, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-04-25 16:08 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

On Fri, Apr 16, 2021, at 6:34 PM, Marlon Richert wrote:
> Attached is a new version of the patch that handles _all the things._ \o/

ping for re-review

vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-14 14:09             ` sysexits.h codes? (was: " Daniel Shahaf
@ 2021-04-30 19:40               ` Marlon Richert
  2021-04-30 21:16                 ` Daniel Shahaf
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-04-30 19:40 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Wed, Apr 14, 2021 at 5:09 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > >> @@ -0,0 +1,197 @@
> > >> +readonly -ga sysexits=(
> > >> +    USAGE
> > > ⋮
> > >> +    CONFIG
> > >
> > > Two interrelated scripts on zsh.org hardcode these constants too.
> > > I wonder if we should provide these constants in a standard autoloaded
> > > function or preset variable.
> >
> > A preset variable would be great. In C code, you can get the names and values from `sysexits.h`, which is available in both GNU and BSD.
>
> An associative array mapping symbolic names to integers?

I think we could settle for just an array of names, to be consistent
with $signals.


> Just those available on the target system, or?

sysexits.h tries to standardize exit codes. Having different $sysexits
on different target systems would defeat its purpose.


> > It would be great if, besides printing the name, it could also add a
> > short description of what the exit code actually means. Something like
> > “SIGPIPE (140): write on a pipe with no reader”.
>
> There's precedent to work with:
>
>     % =pwd | true
>     zsh: broken pipe  =pwd
>
> I suppose the default should be about this level of verbosity.
>
> Other degrees of verbosity could be considered.

Having an option to make error messages more verbose would be great
for new users. "broken pipe", for example, sounds a lot worse than it
really is. :)

Verbose descriptions could be copied from BSD's signal.h or man 2
sigaction. I think those are pretty decent.

Speaking of which, this reminds me of what Paul wrote in workers/48236:

On Wed, Mar 24, 2021 at 4:29 PM Paul <GammaFunction@vivaldi.net> wrote:
> - I half-agree with not unsetting clobber. noclobber is better default
>   behavior (it prevents much more damaging surprises), but just seeing
>   "file exists" or "no such file or directory" without any '>|' or '>>|'
>   suggestion is frustrating.

That could use a more helpful message, too.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-30 19:40               ` Marlon Richert
@ 2021-04-30 21:16                 ` Daniel Shahaf
  2021-04-30 21:34                   ` Bart Schaefer
                                     ` (2 more replies)
  0 siblings, 3 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-04-30 21:16 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

Marlon Richert wrote on Fri, 30 Apr 2021 19:40 +00:00:
> On Wed, Apr 14, 2021 at 5:09 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > > >> @@ -0,0 +1,197 @@
> > > >> +readonly -ga sysexits=(
> > > >> +    USAGE
> > > > ⋮
> > > >> +    CONFIG
> > > >
> > > > Two interrelated scripts on zsh.org hardcode these constants too.
> > > > I wonder if we should provide these constants in a standard autoloaded
> > > > function or preset variable.
> > >
> > > A preset variable would be great. In C code, you can get the names and values from `sysexits.h`, which is available in both GNU and BSD.
> >
> > An associative array mapping symbolic names to integers?
> 
> I think we could settle for just an array of names, to be consistent
> with $signals.

With $signals there's the annoyance that there's an off-by-one between
the signals' value and its array index.

With a $sysexits that's just an array of names there'd be an off-by-64.
That'd be a magic number.

Not a deal breaker, but not ideal either.

> 
> > Just those available on the target system, or?
> 
> sysexits.h tries to standardize exit codes. Having different $sysexits
> on different target systems would defeat its purpose.
> 

That's two separate issues: one, whether sysexits.h should define the
same numeric values everywhere; two, whether $sysexits should reflect
the local sysexits.h or a "well-known" one, in case they're different.

> > > It would be great if, besides printing the name, it could also add a
> > > short description of what the exit code actually means. Something like
> > > “SIGPIPE (140): write on a pipe with no reader”.
> >
> > There's precedent to work with:
> >
> >     % =pwd | true
> >     zsh: broken pipe  =pwd
> >
> > I suppose the default should be about this level of verbosity.
> >
> > Other degrees of verbosity could be considered.
> 
> Having an option to make error messages more verbose would be great
> for new users. "broken pipe", for example, sounds a lot worse than it
> really is. :)
> 

"broken pipe" is just what libc gives, so, shouldn't such an option be
implemented in libc itself?  Besides, libc's message may be localized,
and there's no reason to require users to choose between a verbose
message and a localized one.

> Verbose descriptions could be copied from BSD's signal.h or man 2
> sigaction. I think those are pretty decent.
> 
> Speaking of which, this reminds me of what Paul wrote in workers/48236:
> 
> On Wed, Mar 24, 2021 at 4:29 PM Paul <GammaFunction@vivaldi.net> wrote:
> > - I half-agree with not unsetting clobber. noclobber is better default
> >   behavior (it prevents much more damaging surprises), but just seeing
> >   "file exists" or "no such file or directory" without any '>|' or '>>|'
> >   suggestion is frustrating.
> 
> That could use a more helpful message, too.

Yeah.  The code should say what it was trying to do when it called the
syscall which returned that error; i.e., «zerrnam(foo, "while doing bar:
%e", errno)» rather than «zerrnam(foo, "%e", errno)».

Daniel
(replying out of order)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-30 21:16                 ` Daniel Shahaf
@ 2021-04-30 21:34                   ` Bart Schaefer
  2021-05-01 15:09                     ` Daniel Shahaf
  2021-04-30 21:40                   ` Bart Schaefer
  2021-05-01 13:39                   ` Marlon Richert
  2 siblings, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-04-30 21:34 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Fri, Apr 30, 2021 at 2:17 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> With $signals there's the annoyance that there's an off-by-one between
> the signals' value and its array index.

The only reason $signals is as it is, is because it existed before
associative arrays did.

I wonder if we could do a trick sort of like we do when declaring
SECONDS as float, i.e., convert signals into a hash if one runs
  typeset -A signals


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-30 21:16                 ` Daniel Shahaf
  2021-04-30 21:34                   ` Bart Schaefer
@ 2021-04-30 21:40                   ` Bart Schaefer
  2021-05-01 13:39                   ` Marlon Richert
  2 siblings, 0 replies; 65+ messages in thread
From: Bart Schaefer @ 2021-04-30 21:40 UTC (permalink / raw)
  To: Zsh hackers list

On Fri, Apr 30, 2021 at 2:17 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> > > An associative array mapping symbolic names to integers?
>
> With $signals there's the annoyance that there's an off-by-one between
> the signals' value and its array index.

Incidentally it would have to be either an associative array mapping
numbers to names (perhaps with the sort of ordering guarantee that is
applied to $history), or an associative array with mappings in both
directions, sort of like $color as set up by the colors function.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-30 21:16                 ` Daniel Shahaf
  2021-04-30 21:34                   ` Bart Schaefer
  2021-04-30 21:40                   ` Bart Schaefer
@ 2021-05-01 13:39                   ` Marlon Richert
  2021-05-01 14:43                     ` Daniel Shahaf
  2 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-01 13:39 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Sat, May 1, 2021 at 12:16 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Marlon Richert wrote on Fri, 30 Apr 2021 19:40 +00:00:
> >
> > On Wed, Mar 24, 2021 at 4:29 PM Paul <GammaFunction@vivaldi.net> wrote:
> > > - I half-agree with not unsetting clobber. noclobber is better default
> > >   behavior (it prevents much more damaging surprises), but just seeing
> > >   "file exists" or "no such file or directory" without any '>|' or '>>|'
> > >   suggestion is frustrating.
> >
> > That could use a more helpful message, too.
>
> Yeah.  The code should say what it was trying to do when it called the
> syscall which returned that error; i.e., «zerrnam(foo, "while doing bar:
> %e", errno)» rather than «zerrnam(foo, "%e", errno)».

That still wouldn't help the user understand why this happens (because
NOCLOBBER is set) and it still doesn't tell them what to do about it
(use '>|' to override NOCLOBBER or just write to another file).

As for your other points: Your call. I've laid out my arguments; I
have nothing further to add.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-01 13:39                   ` Marlon Richert
@ 2021-05-01 14:43                     ` Daniel Shahaf
  2021-05-03 11:36                       ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-05-01 14:43 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

Marlon Richert wrote on Sat, May 01, 2021 at 16:39:06 +0300:
> On Sat, May 1, 2021 at 12:16 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> >
> > Marlon Richert wrote on Fri, 30 Apr 2021 19:40 +00:00:
> > >
> > > On Wed, Mar 24, 2021 at 4:29 PM Paul <GammaFunction@vivaldi.net> wrote:
> > > > - I half-agree with not unsetting clobber. noclobber is better default
> > > >   behavior (it prevents much more damaging surprises), but just seeing
> > > >   "file exists" or "no such file or directory" without any '>|' or '>>|'
> > > >   suggestion is frustrating.
> > >
> > > That could use a more helpful message, too.
> >
> > Yeah.  The code should say what it was trying to do when it called the
> > syscall which returned that error; i.e., «zerrnam(foo, "while doing bar:
> > %e", errno)» rather than «zerrnam(foo, "%e", errno)».
> 
> That still wouldn't help the user understand why this happens (because
> NOCLOBBER is set)

NO_CLOBBER being set could be an action at a distance, so it'd be
reasonable for stderr to mention it.  Feel free to propose new text.

> and it still doesn't tell them what to do about it
> (use '>|' to override NOCLOBBER or just write to another file).

> As for your other points: Your call. I've laid out my arguments; I
> have nothing further to add.

What, are you asking me to make all design decisions myself?  That's not
how this list works.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-30 21:34                   ` Bart Schaefer
@ 2021-05-01 15:09                     ` Daniel Shahaf
  0 siblings, 0 replies; 65+ messages in thread
From: Daniel Shahaf @ 2021-05-01 15:09 UTC (permalink / raw)
  To: Zsh hackers list

Bart Schaefer wrote on Fri, Apr 30, 2021 at 14:34:15 -0700:
> I wonder if we could do a trick sort of like we do when declaring
> SECONDS as float, i.e., convert signals into a hash if one runs
>   typeset -A signals

${SECONDS}'s type is lexically scoped.  This is implemented by
special-casing ${SECONDS} in scanendscope().  I'm not sure I like adding
even more special cases; if anything, I'd rather have fewer (e.g., make
$SECONDS always a float in zsh 6.0).

Bart Schaefer wrote on Fri, Apr 30, 2021 at 14:40:06 -0700:
> Incidentally it would have to be either an associative array mapping
> numbers to names (perhaps with the sort of ordering guarantee that is
> applied to $history), or an associative array with mappings in both
> directions, sort of like $color as set up by the colors function.

Or it could be an assoc mapping symbolic names to integer values, and 
named something other than ${signals}.

> 

By the way:

diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 36c1ae4c2..2f84e5728 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -840,8 +840,9 @@ will be the value that was assigned plus the number of seconds
 since the assignment.
 
 Unlike other special parameters, the type of the tt(SECONDS) parameter can
-be changed using the tt(typeset) command.  Only integer and one of the
-floating point types are allowed.  For example, `tt(typeset -F SECONDS)'
+be changed using the tt(typeset) command.  The type may be changed only
+to one of the floating point types or back to integer.  For example,
+`tt(typeset -F SECONDS)'
 causes the value to be reported as a floating point number.  The
 value is available to microsecond accuracy, although the shell may
 show more or fewer digits depending on the use of tt(typeset).  See



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-25 16:08                 ` Lawrence Velázquez
@ 2021-05-02 17:03                   ` Lawrence Velázquez
  0 siblings, 0 replies; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-02 17:03 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

On Sun, Apr 25, 2021, at 12:08 PM, Lawrence Velázquez wrote:
> On Fri, Apr 16, 2021, at 6:34 PM, Marlon Richert wrote:
> > Attached is a new version of the patch that handles _all the things._ \o/
> 
> ping for re-review

ping II: the wrath of khan

-- 
vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-04-19 16:46                         ` Marlon Richert
@ 2021-05-02 17:18                           ` Lawrence Velázquez
  2021-05-03  2:38                             ` Bart Schaefer
  0 siblings, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-02 17:18 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

On Mon, Apr 19, 2021, at 12:46 PM, Marlon Richert wrote:
> On 16 Apr 2021, at 22:30, Daniel Shahaf <d.s@daniel.shahaf.name 
> <mailto:d.s%40daniel.shahaf.name>> wrote:
> > 
> >> +prompt_vcs_chpwd() {
> >> +  exec {fd}< <(
> >> +    # Fetch only staged changes at this point, for performance reasons.
> >> +    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
> > 
> > Should this set «check-for-changes no», to override a «yes» that may
> > have been explicitly set on a less-specific context pattern?
> 
> Yes, that would make sense. Added. See attachment.

ping for further review

-- 
vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-04-16 22:34               ` Marlon Richert
  2021-04-25 16:08                 ` Lawrence Velázquez
@ 2021-05-02 17:59                 ` Bart Schaefer
  2021-05-05  6:10                   ` Marlon Richert
  1 sibling, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-05-02 17:59 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Daniel Shahaf, Zsh hackers list

On Fri, Apr 16, 2021 at 3:38 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> Attached is a new version of the patch that handles _all the things._ \o/

This looks OK, with two questions:
1.  Subshells have been introduced.  Those won't be treated as
interactive shells.  Does that matter?
2.  This bit in the restore style:
+        $( add-zsh-hook -L )
+        $( add-zle-hook-widget -L )
There may not be anything to be done about this, but unless I'm
mistaken that just re-adds all the previous hooks, it doesn't remove
any?  The code it is replacing clobbered the entire list of precmd and
preexec hooks, which I suppose also might also be wrong if anything
other than the prompt theme was manipulating them.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-05-02 17:18                           ` Lawrence Velázquez
@ 2021-05-03  2:38                             ` Bart Schaefer
  2021-05-03  4:11                               ` Lawrence Velázquez
  0 siblings, 1 reply; 65+ messages in thread
From: Bart Schaefer @ 2021-05-03  2:38 UTC (permalink / raw)
  To: Lawrence Velázquez; +Cc: Zsh hackers list, Marlon Richert

On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org> wrote:
>
> ping for further review

I've lost track of what we're reviewing here:  "prompt newuser" or
"prompt vcs" or ...?


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] `newuser` prompt theme
  2021-05-03  2:38                             ` Bart Schaefer
@ 2021-05-03  4:11                               ` Lawrence Velázquez
  2021-05-03 11:38                                 ` [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-03  4:11 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers, Marlon Richert

On Sun, May 2, 2021, at 10:38 PM, Bart Schaefer wrote:
> On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> >
> > ping for further review
> 
> I've lost track of what we're reviewing here:  "prompt newuser" or
> "prompt vcs" or ...?

The patch in workers/48620, which as I understand it used to be
"newuser" but is "vcs" now?  I think?

-- 
vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-01 14:43                     ` Daniel Shahaf
@ 2021-05-03 11:36                       ` Marlon Richert
  2021-05-03 16:04                         ` Daniel Shahaf
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-03 11:36 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Sat, May 1, 2021 at 5:43 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Marlon Richert wrote on Sat, May 01, 2021 at 16:39:06 +0300:
> > > Yeah.  The code should say what it was trying to do when it called the
> > > syscall which returned that error; i.e., «zerrnam(foo, "while doing bar:
> > > %e", errno)» rather than «zerrnam(foo, "%e", errno)».
> >
> > That still wouldn't help the user understand why this happens (because
> > NOCLOBBER is set)
>
> NO_CLOBBER being set could be an action at a distance, so it'd be
> reasonable for stderr to mention it.  Feel free to propose new text.

Is there any precedent for warnings/errors that mention a shell option
being (un)set? If so, then we could use that as a template for this
one.

Otherwise, maybe something like this?

zsh: NO_CLOBBER: file exists; use >| to override

It would give you the right keywords to use in a web search.


> > As for your other points: Your call. I've laid out my arguments; I
> > have nothing further to add.
>
> What, are you asking me to make all design decisions myself?  That's not
> how this list works.

Sorry, I don't feel strongly enough about this to feel like debating it. :)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-03  4:11                               ` Lawrence Velázquez
@ 2021-05-03 11:38                                 ` Marlon Richert
  2021-05-09 18:04                                   ` Lawrence Velázquez
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-03 11:38 UTC (permalink / raw)
  To: Lawrence Velázquez; +Cc: Bart Schaefer, Zsh hackers list

On Mon, May 3, 2021 at 7:11 AM Lawrence Velázquez <larryv@zsh.org> wrote:
>
> On Sun, May 2, 2021, at 10:38 PM, Bart Schaefer wrote:
> > On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> > >
> > > ping for further review
> >
> > I've lost track of what we're reviewing here:  "prompt newuser" or
> > "prompt vcs" or ...?
>
> The patch in workers/48620, which as I understand it used to be
> "newuser" but is "vcs" now?  I think?

Yes, that is correct, but it appears I forgot to update the subject
line to reflect this. That's fixed now.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-03 11:36                       ` Marlon Richert
@ 2021-05-03 16:04                         ` Daniel Shahaf
  2021-05-04 11:13                           ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Daniel Shahaf @ 2021-05-03 16:04 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

Marlon Richert wrote on Mon, May 03, 2021 at 14:36:01 +0300:
> On Sat, May 1, 2021 at 5:43 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> >
> > Marlon Richert wrote on Sat, May 01, 2021 at 16:39:06 +0300:
> > > > Yeah.  The code should say what it was trying to do when it called the
> > > > syscall which returned that error; i.e., «zerrnam(foo, "while doing bar:
> > > > %e", errno)» rather than «zerrnam(foo, "%e", errno)».
> > >
> > > That still wouldn't help the user understand why this happens (because
> > > NOCLOBBER is set)
> >
> > NO_CLOBBER being set could be an action at a distance, so it'd be
> > reasonable for stderr to mention it.  Feel free to propose new text.
> 
> Is there any precedent for warnings/errors that mention a shell option
> being (un)set? If so, then we could use that as a template for this
> one.

None comes to mind, and grepping the output of `strings =zsh` doesn't
turn up any, either.

> Otherwise, maybe something like this?
> 
> zsh: NO_CLOBBER: file exists; use >| to override
> 
> It would give you the right keywords to use in a web search.

+1 on putting the option name first.

Not sure whether putting the strerror(3) string in the middle would
work well in all cases.  Convention — codified in errx(3) and friends,
and compare Perl's «die "foo"» without a trailing newline — is that
extra information is appended, rather than surrounded.  The latter could
also lead to ambiguous or unclear grammatical structures.

Furthermore, the extra advice in the error wouldn't always be
appropriate — for instance, when the error is EACCES ("Permission
denied").

> > > As for your other points: Your call. I've laid out my arguments; I
> > > have nothing further to add.
> >
> > What, are you asking me to make all design decisions myself?  That's not
> > how this list works.
> 
> Sorry, I don't feel strongly enough about this to feel like debating it. :)

Well, suit yourself, but unless someone else shows up to drive the
discussion, it'll likely be left at that.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-03 16:04                         ` Daniel Shahaf
@ 2021-05-04 11:13                           ` Marlon Richert
  2021-05-21 11:38                             ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-04 11:13 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh hackers list

On Mon, May 3, 2021 at 7:04 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Marlon Richert wrote on Mon, May 03, 2021 at 14:36:01 +0300:
> >
> > zsh: NO_CLOBBER: file exists; use >| to override
> >
> > It would give you the right keywords to use in a web search.
>
> +1 on putting the option name first.
>
> Not sure whether putting the strerror(3) string in the middle would
> work well in all cases.  Convention — codified in errx(3) and friends,
> and compare Perl's «die "foo"» without a trailing newline — is that
> extra information is appended, rather than surrounded.  The latter could
> also lead to ambiguous or unclear grammatical structures.
>
> Furthermore, the extra advice in the error wouldn't always be
> appropriate — for instance, when the error is EACCES ("Permission
> denied").

Well, of course not. The advice above is specific to NO_CLOBBER. ;)

In all seriousness, though: I'm fine with not providing advice for
errors like EACCES, because those are not specific to the shell. For
all errors specific to shell features, though, (such as NO_CLOBBER,)
having a short, error-specific piece of advice would be a tremendous
help in making the shell's features easier to discover and easier to
understand.


> Well, suit yourself,

Tweet or plaid? ;)

> but unless someone else shows up to drive the discussion, it'll likely be left at that.

All right, if you insist… :)

I've given it some more thought and the best option, I think, would be
as follows:
* Have an associative array $sysexits.
* Let the keys be the return codes and the values be the exact
descriptions that PRINT_EXIT_VALUE shows (minus the 'zsh: ' prefix and
command suffix, of course).
* Include all of 0 (success), 1 (failure), 2 (error), 64 - 78
(sysexits.h), 126 (command not executable), 127 (command not found),
and 129 - 159 (signal.h). (Anything else I'm forgetting?)
* $sysexits could either be built in, like $signals, or be available
through a module.

Additional features for consideration:
* Make $sysexits editable, so that you can modify what PRINT_EXIT_VALUE outputs.
* Let PRINT_EXIT_VALUE support formatting in the form of prompt escape
sequences.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-02 17:59                 ` Bart Schaefer
@ 2021-05-05  6:10                   ` Marlon Richert
  2021-05-16 15:27                     ` Lawrence Velázquez
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-05  6:10 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Daniel Shahaf, Zsh hackers list

On Sun, May 2, 2021 at 8:59 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Fri, Apr 16, 2021 at 3:38 PM Marlon Richert <marlon.richert@gmail.com> wrote:
> >
> > Attached is a new version of the patch that handles _all the things._ \o/
>
> This looks OK, with two questions:
> 1.  Subshells have been introduced.  Those won't be treated as
> interactive shells.

Are you sure about that? When I do `foo() { ( setopt ) }; foo`, it
still lists 'interactive' (though not 'monitor' or 'zle').

> Does that matter?

It doesn't appear to matter. The prompt previews look the same as
before. Try `prompt -p` (without further args). Doesn

> 2.  This bit in the restore style:
> +        $( add-zsh-hook -L )
> +        $( add-zle-hook-widget -L )
> There may not be anything to be done about this, but unless I'm
> mistaken that just re-adds all the previous hooks, it doesn't remove
> any?  The code it is replacing clobbered the entire list of precmd and
> preexec hooks, which I suppose also might also be wrong if anything
> other than the prompt theme was manipulating them.

`add-zsh-hook -L` outputs statements in the form of `typeset -g -a
<hook>_functions=( <func> ... )`, while `add-zle-hook-widget -L`
outputs statements in the form of `zstyle zle-<hook> widgets
<nr>:<widget> ...` (which is where add-zle-hook-widget stores the hook
widgets to call internally). eval'ing either of these results in the
same good, old-fashioned clobbering as in the old code. So, no
functional change there. :)

I just realized, though, that these lines (new and old) don't actually
do anything useful:
* When you call `prompt`, it will not unhook anything not called
`prompt_*_<hook>`. So, whatever hooks you've set up that don't follow
the naming scheme will still be there when you call `prompt restore`.
No need to restore them.
* When you call `prompt`, it will unhook everything called
`prompt_*_<hook>`. So, if a prompt theme correctly implements the
prompt system contract, its hook functions will already get unhooked
when switching themes. Again, no need to do anything special when
calling `prompt restore`.

The only case I can think of that would need special handling is if
you already had hooks installed that follow the `prompt_*_<hook>`
naming convention before calling `prompt` for the first time.

Should we just get rid of this part of the "restore" logic? And
instead just document clearly that `prompt` will auto-remove all hooks
that follow its naming scheme?


And speaking of prompt hooks and naming schemes:

On Fri, Apr 16, 2021 at 12:34 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> Marlon wrote on Thu, Apr 15, 2021 at 21:54:48 +0300:
> > On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > >> +++ b/Functions/Prompts/promptinit
> > >> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
> > >>
> > >>        # 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}"
> > >> +       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"
> > >
> > > Recommend to name these prompt_${foo}_bar-{isearch-exit,isearch-update,…,keymap-select}
> > > for some fixed value of «bar» to avoid namespace issues (i.e., name
> > > collisions between existing prompts and future hooks).
> >
> > Wouldn’t that be a breaking change in the API, though?
>
> No, it wouldn't, because those are add-zle-hook-widget hooks and the
> current API only deals with add-zsh-hook hooks.
>
> We could even recommend that add-zsh-hook hooks be named
> prompt_${foo}_baz_{chpwd,…} for some fixed value of baz.  We don't even
> have to change the code to support this (because the asterisk will match
> «${foo}_baz» just fine); we just need to document the recommendation and
> deprecate the previous recommended naming pattern.
>
> > Also, isn’t the prefix prompt_${foo}_ already a namespace of sorts? Why change this?
>
> What if the foo theme declares a function called prompt_foo_lorem (or
> even prompt_foo_ipsum_lorem) that _isn't_ an «add-*-hook lorem» hook
> function, and later we start to to auto-register functions matching the
> name pattern?
>
> Or if we were to make «add-zsh-hook bar lorem» and «add-zle-hook-widget
> bar ipsum» both valid, for a single value of bar, and a prompt theme
> wanted to install both hooks _and_ name the functions «lorem» and «ipsum»
> conventionally?
>
> Or if someone wanted to quickly grep for add-zle-hook-widget callbacks?

If we're going to change the prompt function naming scheme anyway, can
we change it to something that starts with . or _? Because then
`zstyle ':completion:*' prefix-needed yes` will conveniently hide
these.

How about .prompt.<theme>.<hook>? And then auto-register these
functions as hooks?

And should all of this go into the same patch? If `prompt`
automatically unregisters all hooks that follow a naming pattern
(regardless of how they've been registered), then I think it would
make sense for it to automatically register them, too.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-03 11:38                                 ` [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon Richert
@ 2021-05-09 18:04                                   ` Lawrence Velázquez
  2021-05-31  1:01                                     ` Lawrence Velázquez
  0 siblings, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-09 18:04 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

On Mon, May 3, 2021, at 7:38 AM, Marlon Richert wrote:
> On Mon, May 3, 2021 at 7:11 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> >
> > On Sun, May 2, 2021, at 10:38 PM, Bart Schaefer wrote:
> > > On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> > > >
> > > > ping for further review
> > >
> > > I've lost track of what we're reviewing here:  "prompt newuser" or
> > > "prompt vcs" or ...?
> >
> > The patch in workers/48620, which as I understand it used to be
> > "newuser" but is "vcs" now?  I think?
> 
> Yes, that is correct, but it appears I forgot to update the subject
> line to reflect this. That's fixed now.

second ping for review of workers/48620

-- 
vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-05  6:10                   ` Marlon Richert
@ 2021-05-16 15:27                     ` Lawrence Velázquez
  2021-05-16 19:31                       ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-16 15:27 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

Hi,

Is workers/48609 ready to commit, or should Marlon make further
changes, or...?

vq

On Wed, May 5, 2021, at 2:10 AM, Marlon Richert wrote:
> On Sun, May 2, 2021 at 8:59 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
> >
> > On Fri, Apr 16, 2021 at 3:38 PM Marlon Richert <marlon.richert@gmail.com> wrote:
> > >
> > > Attached is a new version of the patch that handles _all the things._ \o/
> >
> > This looks OK, with two questions:
> > 1.  Subshells have been introduced.  Those won't be treated as
> > interactive shells.
> 
> Are you sure about that? When I do `foo() { ( setopt ) }; foo`, it
> still lists 'interactive' (though not 'monitor' or 'zle').
> 
> > Does that matter?
> 
> It doesn't appear to matter. The prompt previews look the same as
> before. Try `prompt -p` (without further args). Doesn
> 
> > 2.  This bit in the restore style:
> > +        $( add-zsh-hook -L )
> > +        $( add-zle-hook-widget -L )
> > There may not be anything to be done about this, but unless I'm
> > mistaken that just re-adds all the previous hooks, it doesn't remove
> > any?  The code it is replacing clobbered the entire list of precmd and
> > preexec hooks, which I suppose also might also be wrong if anything
> > other than the prompt theme was manipulating them.
> 
> `add-zsh-hook -L` outputs statements in the form of `typeset -g -a
> <hook>_functions=( <func> ... )`, while `add-zle-hook-widget -L`
> outputs statements in the form of `zstyle zle-<hook> widgets
> <nr>:<widget> ...` (which is where add-zle-hook-widget stores the hook
> widgets to call internally). eval'ing either of these results in the
> same good, old-fashioned clobbering as in the old code. So, no
> functional change there. :)
> 
> I just realized, though, that these lines (new and old) don't actually
> do anything useful:
> * When you call `prompt`, it will not unhook anything not called
> `prompt_*_<hook>`. So, whatever hooks you've set up that don't follow
> the naming scheme will still be there when you call `prompt restore`.
> No need to restore them.
> * When you call `prompt`, it will unhook everything called
> `prompt_*_<hook>`. So, if a prompt theme correctly implements the
> prompt system contract, its hook functions will already get unhooked
> when switching themes. Again, no need to do anything special when
> calling `prompt restore`.
> 
> The only case I can think of that would need special handling is if
> you already had hooks installed that follow the `prompt_*_<hook>`
> naming convention before calling `prompt` for the first time.
> 
> Should we just get rid of this part of the "restore" logic? And
> instead just document clearly that `prompt` will auto-remove all hooks
> that follow its naming scheme?
> 
> 
> And speaking of prompt hooks and naming schemes:
> 
> On Fri, Apr 16, 2021 at 12:34 AM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > Marlon wrote on Thu, Apr 15, 2021 at 21:54:48 +0300:
> > > On 14 Apr 2021, at 15:05, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > > >> +++ b/Functions/Prompts/promptinit
> > > >> @@ -178,8 +177,13 @@ Use prompt -h <theme> for help on specific themes.'
> > > >>
> > > >>        # 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}"
> > > >> +       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"
> > > >
> > > > Recommend to name these prompt_${foo}_bar-{isearch-exit,isearch-update,…,keymap-select}
> > > > for some fixed value of «bar» to avoid namespace issues (i.e., name
> > > > collisions between existing prompts and future hooks).
> > >
> > > Wouldn’t that be a breaking change in the API, though?
> >
> > No, it wouldn't, because those are add-zle-hook-widget hooks and the
> > current API only deals with add-zsh-hook hooks.
> >
> > We could even recommend that add-zsh-hook hooks be named
> > prompt_${foo}_baz_{chpwd,…} for some fixed value of baz.  We don't even
> > have to change the code to support this (because the asterisk will match
> > «${foo}_baz» just fine); we just need to document the recommendation and
> > deprecate the previous recommended naming pattern.
> >
> > > Also, isn’t the prefix prompt_${foo}_ already a namespace of sorts? Why change this?
> >
> > What if the foo theme declares a function called prompt_foo_lorem (or
> > even prompt_foo_ipsum_lorem) that _isn't_ an «add-*-hook lorem» hook
> > function, and later we start to to auto-register functions matching the
> > name pattern?
> >
> > Or if we were to make «add-zsh-hook bar lorem» and «add-zle-hook-widget
> > bar ipsum» both valid, for a single value of bar, and a prompt theme
> > wanted to install both hooks _and_ name the functions «lorem» and «ipsum»
> > conventionally?
> >
> > Or if someone wanted to quickly grep for add-zle-hook-widget callbacks?
> 
> If we're going to change the prompt function naming scheme anyway, can
> we change it to something that starts with . or _? Because then
> `zstyle ':completion:*' prefix-needed yes` will conveniently hide
> these.
> 
> How about .prompt.<theme>.<hook>? And then auto-register these
> functions as hooks?
> 
> And should all of this go into the same patch? If `prompt`
> automatically unregisters all hooks that follow a naming pattern
> (regardless of how they've been registered), then I think it would
> make sense for it to automatically register them, too.
> 
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-16 15:27                     ` Lawrence Velázquez
@ 2021-05-16 19:31                       ` Marlon Richert
  2021-05-17  4:19                         ` Bart Schaefer
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-05-16 19:31 UTC (permalink / raw)
  To: Lawrence Velázquez; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 2443 bytes --]

Here's at least a new version of the patch that does away with the two
lines discussed below.

On Sun, May 16, 2021 at 6:27 PM Lawrence Velázquez <larryv@zsh.org> wrote:
>
> Hi,
>
> Is workers/48609 ready to commit, or should Marlon make further
> changes, or...?
>
> vq
>
> On Wed, May 5, 2021, at 2:10 AM, Marlon Richert wrote:
> > On Sun, May 2, 2021 at 8:59 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
> > > 2.  This bit in the restore style:
> > > +        $( add-zsh-hook -L )
> > > +        $( add-zle-hook-widget -L )
> > > There may not be anything to be done about this, but unless I'm
> > > mistaken that just re-adds all the previous hooks, it doesn't remove
> > > any?  The code it is replacing clobbered the entire list of precmd and
> > > preexec hooks, which I suppose also might also be wrong if anything
> > > other than the prompt theme was manipulating them.
> >
> > `add-zsh-hook -L` outputs statements in the form of `typeset -g -a
> > <hook>_functions=( <func> ... )`, while `add-zle-hook-widget -L`
> > outputs statements in the form of `zstyle zle-<hook> widgets
> > <nr>:<widget> ...` (which is where add-zle-hook-widget stores the hook
> > widgets to call internally). eval'ing either of these results in the
> > same good, old-fashioned clobbering as in the old code. So, no
> > functional change there. :)
> >
> > I just realized, though, that these lines (new and old) don't actually
> > do anything useful:
> > * When you call `prompt`, it will not unhook anything not called
> > `prompt_*_<hook>`. So, whatever hooks you've set up that don't follow
> > the naming scheme will still be there when you call `prompt restore`.
> > No need to restore them.
> > * When you call `prompt`, it will unhook everything called
> > `prompt_*_<hook>`. So, if a prompt theme correctly implements the
> > prompt system contract, its hook functions will already get unhooked
> > when switching themes. Again, no need to do anything special when
> > calling `prompt restore`.
> >
> > The only case I can think of that would need special handling is if
> > you already had hooks installed that follow the `prompt_*_<hook>`
> > naming convention before calling `prompt` for the first time.
> >
> > Should we just get rid of this part of the "restore" logic? And
> > instead just document clearly that `prompt` will auto-remove all hooks
> > that follow its naming scheme?

[-- Attachment #2: 0001-Reset-ZLE-hooks-when-changing-prompt-themes.txt --]
[-- Type: text/plain, Size: 10117 bytes --]

From c117e63baaf9b4add8ed2ded89c0820d223104ad Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Sun, 16 May 2021 22:26:46 +0300
Subject: [PATCH] Reset ZLE hooks when changing prompt themes

---
 Doc/Zsh/contrib.yo           |  10 ++-
 Functions/Prompts/promptinit | 165 +++++++++++++++--------------------
 2 files changed, 77 insertions(+), 98 deletions(-)

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index b777703b3..1d20fe520 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -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
 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(Modify hooks)(
+Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended (see
+ifzman(the bf(Manipulating Hook Functions) section above)\
+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)(
 If your function makes any other changes that should be undone when the
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index 37d69f100..20503d78b 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%}'
 }
@@ -47,38 +46,23 @@ prompt_preview_safely() {
     return
   fi
 
-  # This handles all the stuff from the default :prompt-theme restore
-  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 prompt_preview_restore
-  local -aLl +h zle_highlight
+  # 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
 
-  {
-    # Save and clear current restore-point if any
-    zstyle -g prompt_preview_restore :prompt-theme restore
-    {
-      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.
+    # If we can't find a _preview function, run the _setup function to see if
+    # it will create one.
+    typeset +f prompt_${1}_preview >&/dev/null ||
       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_restore )) &&
-      zstyle -e :prompt-theme restore "${prompt_preview_restore[@]}"
-  }
+    # ...then try again.
+    if typeset +f prompt_${1}_preview >&/dev/null; then
+      prompt_${1}_preview "$@[2,-1]"
+    else
+      prompt_preview_theme "$@"
+    fi
+  )
 }
 
 set_prompt() {
@@ -97,21 +81,6 @@ Options:
 Use prompt -h <theme> 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 +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
     c) if [[ -n $prompt_theme ]]; then
          print -n "Current prompt theme"
@@ -123,21 +92,26 @@ Use prompt -h <theme> for help on specific themes.'
        return
        ;;
     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
-           # 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."
+
+           # If we can't find a _help function, run the _setup function to see
+           # if it will create one.
+           typeset +f prompt_$2_help >/dev/null ||
+               prompt_$2_setup
+
+           # ...then try again.
+           if typeset +f 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
@@ -178,8 +152,13 @@ Use prompt -h <theme> for help on specific themes.'
 
        # 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}"
+       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
@@ -192,11 +171,8 @@ Use prompt -h <theme> for help on specific themes.'
 
 prompt_cleanup () {
   local -a cleanup_hooks theme_active
-  if ! zstyle -g cleanup_hooks :prompt-theme cleanup
-  then
-    (( $+prompt_preview_restore == 0 )) &&
-    if ! zstyle -g theme_active :prompt-theme restore
-    then
+  if ! zstyle -g cleanup_hooks :prompt-theme cleanup; then
+    if ! zstyle -g theme_active :prompt-theme restore; then
       print -u2 "prompt_cleanup: no prompt theme active"
       return 1
     fi
@@ -225,22 +201,21 @@ prompt () {
     [[ -o promptpercent ]] && prompt_opts+=(percent)
     [[ -o promptsp ]] && prompt_opts+=(sp)
     [[ -o promptsubst ]] && prompt_opts+=(subst)
-    zstyle -e :prompt-theme restore \
-        'zstyle -d :prompt-theme restore;' \
-	'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)'
+    zstyle -e :prompt-theme restore "
+        zstyle -d :prompt-theme restore
+        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}}
+        prompt_opts=( $prompt_opts[*] )
+        reply=( yes )
+    "
   }
   set_prompt "$@"
 
@@ -253,12 +228,6 @@ prompt () {
 prompt_preview_theme () {
   emulate -L zsh
 
-  # Check for proper state handling
-  (( $+prompt_preview_restore )) || {
-    prompt_preview_safely "$@"
-    return
-  }
-
   # Minimal preview for prompts that don't supply one
   local -a prompt_opts
   print -n "$1 theme"
@@ -268,12 +237,20 @@ prompt_preview_theme () {
   prompt_${1}_setup "$@[2,-1]"
   (( ${#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]} ]] &&
-    prompt_${1}_precmd
-  [[ -o promptcr ]] && print -n $'\r'; :
-  print -P "${PS1}command arg1 arg2 ... argn"
+      prompt_${1}_precmd
+
+  # 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]} ]] &&
-    prompt_${1}_preexec
+      prompt_${1}_preexec
 }
 
 [[ -o kshautoload ]] || promptinit "$@"
-- 
2.31.1


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-16 19:31                       ` Marlon Richert
@ 2021-05-17  4:19                         ` Bart Schaefer
  0 siblings, 0 replies; 65+ messages in thread
From: Bart Schaefer @ 2021-05-17  4:19 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Lawrence Velázquez, Zsh hackers list

On Sun, May 16, 2021 at 12:32 PM Marlon Richert
<marlon.richert@gmail.com> wrote:
>
> Here's at least a new version of the patch that does away with the two
> lines discussed below.

I've committed this.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: sysexits.h codes? (was: Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-04 11:13                           ` Marlon Richert
@ 2021-05-21 11:38                             ` Marlon Richert
  0 siblings, 0 replies; 65+ messages in thread
From: Marlon Richert @ 2021-05-21 11:38 UTC (permalink / raw)
  To: Zsh hackers list

On Tue, May 4, 2021 at 2:13 PM Marlon Richert <marlon.richert@gmail.com> wrote:
> I've given it some more thought and the best option, I think, would be
> as follows:
> * Have an associative array $sysexits.
> * Let the keys be the return codes and the values be the exact
> descriptions that PRINT_EXIT_VALUE shows (minus the 'zsh: ' prefix and
> command suffix, of course).
> * Include all of 0 (success), 1 (failure), 2 (error), 64 - 78
> (sysexits.h), 126 (command not executable), 127 (command not found),
> and 129 - 159 (signal.h). (Anything else I'm forgetting?)
> * $sysexits could either be built in, like $signals, or be available
> through a module.
>
> Additional features for consideration:
> * Make $sysexits editable, so that you can modify what PRINT_EXIT_VALUE outputs.
> * Let PRINT_EXIT_VALUE support formatting in the form of prompt escape
> sequences.

Actually, I think it would be pretty nice to have something like
$TIMEFMT but for exit codes. And adding support to both of these for
prompt escape sequences would be great. :)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-09 18:04                                   ` Lawrence Velázquez
@ 2021-05-31  1:01                                     ` Lawrence Velázquez
  2021-06-09 12:58                                       ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Lawrence Velázquez @ 2021-05-31  1:01 UTC (permalink / raw)
  To: zsh-workers; +Cc: Marlon Richert

On Sun, May 9, 2021, at 2:04 PM, Lawrence Velázquez wrote:
> On Mon, May 3, 2021, at 7:38 AM, Marlon Richert wrote:
> > On Mon, May 3, 2021 at 7:11 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> > >
> > > On Sun, May 2, 2021, at 10:38 PM, Bart Schaefer wrote:
> > > > On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org> wrote:
> > > > >
> > > > > ping for further review
> > > >
> > > > I've lost track of what we're reviewing here:  "prompt newuser" or
> > > > "prompt vcs" or ...?
> > >
> > > The patch in workers/48620, which as I understand it used to be
> > > "newuser" but is "vcs" now?  I think?
> > 
> > Yes, that is correct, but it appears I forgot to update the subject
> > line to reflect this. That's fixed now.
> 
> second ping for review of workers/48620

Ping III: The Search for Review

-- 
vq


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-05-31  1:01                                     ` Lawrence Velázquez
@ 2021-06-09 12:58                                       ` Marlon Richert
  2021-06-09 13:22                                         ` Roman Perepelitsa
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-06-09 12:58 UTC (permalink / raw)
  To: Zsh hackers list, Bart Schaefer


[-- Attachment #1.1: Type: text/plain, Size: 982 bytes --]

On Mon, May 31, 2021 at 4:01 AM Lawrence Velázquez <larryv@zsh.org> wrote:

> On Sun, May 9, 2021, at 2:04 PM, Lawrence Velázquez wrote:
> > On Mon, May 3, 2021, at 7:38 AM, Marlon Richert wrote:
> > > On Mon, May 3, 2021 at 7:11 AM Lawrence Velázquez <larryv@zsh.org>
> wrote:
> > > >
> > > > On Sun, May 2, 2021, at 10:38 PM, Bart Schaefer wrote:
> > > > > On Sun, May 2, 2021 at 10:22 AM Lawrence Velázquez <larryv@zsh.org>
> wrote:
> > > > > >
> > > > > > ping for further review
> > > > >
> > > > > I've lost track of what we're reviewing here:  "prompt newuser" or
> > > > > "prompt vcs" or ...?
> > > >
> > > > The patch in workers/48620, which as I understand it used to be
> > > > "newuser" but is "vcs" now?  I think?
> > >
> > > Yes, that is correct, but it appears I forgot to update the subject
> > > line to reflect this. That's fixed now.
>

I decided to make some simplifications to this prompt theme. Here's a new
version of the patch.

[-- Attachment #1.2: Type: text/html, Size: 1635 bytes --]

[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 7220 bytes --]

From 78c0c003c022a457921d6dd54dcef211c565e783 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Wed, 9 Jun 2021 15:53:47 +0300
Subject: [PATCH] Add customizable `vcs` prompt theme

---
 Functions/Prompts/prompt_vcs_setup | 194 +++++++++++++++++++++++++++++
 1 file changed, 194 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..4a17b3ff2
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,194 @@
+##
+# Prompt that can be customized through vcs_info
+#
+
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Prompt segments
+readonly -gHA _prompt_vcs_defaults=(
+    start:chpwd     $'\n%B%F{blue}%~%%b%f/'
+    start:left      $'%%(?,%F{green},%F{red})%#%%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{yellow}# %^%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_defaults[start:chpwd]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_defaults[start:left]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_defaults[start:right]//'%%'/%}"
+
+  # Prompt inside VCS repo:
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+)_prompt_vcs_defaults[start:chpwd]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]}
+  
+  # Prompt during an ongoing VCS action:
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+)_prompt_vcs_defaults[start:chpwd]} \\
+      ${(q+)_prompt_vcs_defaults[start:left]} \\
+      ${(q+):-%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]}
+
+  # These set the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_defaults[start:staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_defaults[start:unstaged]}
+
+For more info on the config 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_defaults[start:chpwd]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:left]//'%%'/%}" \
+      "${_prompt_vcs_defaults[start:right]//'%%'/%}"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_defaults[start:chpwd]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:branch]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_defaults[start:chpwd]" \
+      "$_prompt_vcs_defaults[start:left]" \
+      "%u%c$_prompt_vcs_defaults[start:action]$_prompt_vcs_defaults[start:repo]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_defaults[start:staged]"
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_defaults[start: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
+
+  local -i fd=-1; local -a reply
+  exec {fd}< <(
+    # Fetch only staged changes at this point, for performance reasons.
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes no
+    _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-staged-changes yes
+    _prompt_vcs_info
+  )
+  IFS=$'\0' read -Aru "$fd"
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  exec {fd}<&-
+
+  print -Pr -- "$_prompt_vcs_info_msg_[1]"
+  PS1="$_prompt_vcs_info_msg_[2]"
+  RPS1="$_prompt_vcs_info_msg_[3]"
+}
+
+prompt_vcs_line-init() {
+  emulate -L zsh
+
+  case $CONTEXT in
+    ( start ) # (R)PS1
+      # Asynchronously check for unstaged changes. Do this here & not in
+      # precmd, so you can press Enter on an empty line to update VCS info.
+      local -i fd=-1
+      exec {fd}< <(
+        _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' check-for-changes yes
+        _prompt_vcs_info
+        print -r -- "$PWD"
+      )
+
+      # Add callback. Needs to be a widget, so we can refresh the prompt.
+      zle -Fw "$fd" prompt_vcs_fd-widget
+    ;;
+    ( cont )  # (R)PS2
+      # Indent left continuation prompt for each open shell construct.
+      local fmt="$_prompt_vcs_defaults[cont:indent]"
+      local -a indent=( '%('{1..$(( COLUMNS / ${(m)#fmt} ))}"_,$fmt,)" )
+      PS2="${(j::)indent}$_prompt_vcs_defaults[cont:left]"
+
+      RPS2="$_prompt_vcs_defaults[cont:right]"
+    ;;
+  esac
+}
+
+# Callback widget function for our async fetch of unstaged 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  # Abort if the info is not for the current dir.
+      
+  shift -p reply
+  typeset -ga _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+  RPS1="$_prompt_vcs_info_msg_[3]"
+  zle .reset-prompt
+}
+
+prompt_vcs_line-finish() {
+  emulate -L zsh
+  PS1="$_prompt_vcs_info_msg_[2]"
+}
+
+prompt_vcs_setup() {
+  prompt_opts=( cr percent sp ) # Tell promptinit which options to set.
+
+  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-zle-hook-widget line-init   prompt_vcs_line-init
+  add-zle-hook-widget line-finish prompt_vcs_line-finish
+  zle -N prompt_vcs_fd-widget # Callback widget for async VCS update.
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.30.1 (Apple Git-130)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-09 12:58                                       ` Marlon Richert
@ 2021-06-09 13:22                                         ` Roman Perepelitsa
  2021-06-09 18:06                                           ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Roman Perepelitsa @ 2021-06-09 13:22 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list, Bart Schaefer

On Wed, Jun 9, 2021 at 2:59 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> I decided to make some simplifications to this prompt theme. Here's a new version of the patch.

A few questions/comments after a cursory look.

Why is prompt_vcs_chpwd using exec + read instead of $(...)?

Why hook zle-line-init instead of precmd? There is a comment saying
that it's "so you can press Enter on an empty line to update VCS info"
but I don't understand it. When I press Enter in zle with an empty
buffer, precmd does get called.

There is a race that may cause incorrect git status to be displayed.
For example, suppose I run these commands in quick succession in a
large git repository:

    git checkout -b foo
    git checkout -b bar

If the two background vcs processes finish out of order, prompt will
incorrectly display "foo" when the current branch is "bar". This error
will persist until another command (perhaps empty) is executed.

Pressing and holding Enter in a large repository may cause large (and
unbounded) strain on the machine.

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-09 13:22                                         ` Roman Perepelitsa
@ 2021-06-09 18:06                                           ` Marlon Richert
  2021-06-10  9:30                                             ` Roman Perepelitsa
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-06-09 18:06 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1282 bytes --]

On Wed, Jun 9, 2021 at 4:22 PM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> A few questions/comments after a cursory look.
>
> Why is prompt_vcs_chpwd using exec + read instead of $(...)?

Because I apparently forgot that $(...) runs in a subshell, too. ^_^;

> Why hook zle-line-init instead of precmd? There is a comment saying
> that it's "so you can press Enter on an empty line to update VCS info"
> but I don't understand it. When I press Enter in zle with an empty
> buffer, precmd does get called.

I could've sworn that precmd doesn't get called under those
conditions, but I guess I confused it with preexec.

> There is a race that may cause incorrect git status to be displayed.
> For example, suppose I run these commands in quick succession in a
> large git repository:
>
>     git checkout -b foo
>     git checkout -b bar
>
> If the two background vcs processes finish out of order, prompt will
> incorrectly display "foo" when the current branch is "bar". This error
> will persist until another command (perhaps empty) is executed.
>
> Pressing and holding Enter in a large repository may cause large (and
> unbounded) strain on the machine.

Thanks for the review! Here's a new version of the patch that
hopefully addresses the concerns you raised.

[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 6449 bytes --]

From 41ffe718d7d58411254dc35f9618ae4fb0906aa6 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
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)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-09 18:06                                           ` Marlon Richert
@ 2021-06-10  9:30                                             ` Roman Perepelitsa
  2021-06-10 13:47                                               ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Roman Perepelitsa @ 2021-06-10  9:30 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

On Wed, Jun 9, 2021 at 8:06 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> Thanks for the review! Here's a new version of the patch that
> hopefully addresses the concerns you raised.

There is //'%%'/% in a few places. What's the logic behind it?

I think invoking prompt_vcs_setup twice in the same shell will produce
an error. I haven't tried it though.

prompt_vcs_chpwd always prints at least one line to the TTY regardless
of configuration options. Is this intended?

Why is prompt_vcs_precmd checking whether prompt_vcs_fd is a readable
fd? How can it not be?

There is a comment in prompt_vcs_precmd that says it's going to kill a
process while in fact it closes the file descriptor. That may
*eventually* kill the process when it decides to print something
(assuming it hasn't blocked SIGPIPE or is checking for write errors).

What is the purpose of the "Info is not for current dir" check? Is
this to account for the possibility of `cd` from a zle widget? If so,
perhaps handle this by hooking chpwd?

prompt_vcs_fd-widget has a check for [[ -n $1 ]]. When is it false?

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-10  9:30                                             ` Roman Perepelitsa
@ 2021-06-10 13:47                                               ` Marlon Richert
  2021-06-10 14:01                                                 ` Marlon Richert
  2021-06-10 17:45                                                 ` Roman Perepelitsa
  0 siblings, 2 replies; 65+ messages in thread
From: Marlon Richert @ 2021-06-10 13:47 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1952 bytes --]

On Thu, Jun 10, 2021 at 12:30 PM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> There is //'%%'/% in a few places. What's the logic behind it?

Some prompt escape codes (such as %b for bold) need %% when used in
vcs_info -- except when they are used in nvcsformats.


> I think invoking prompt_vcs_setup twice in the same shell will produce
> an error. I haven't tried it though.

I just tried it and I didn't get any errors. Why do you think it would
produce an error?


> prompt_vcs_chpwd always prints at least one line to the TTY regardless
> of configuration options. Is this intended?

Yes, that was my intention, but I can see how it could be useful to be
able to customize that. I'll change it.


> Why is prompt_vcs_precmd checking whether prompt_vcs_fd is a readable
> fd? How can it not be?

I don't know how or why, but if I don't check for that, then I get
this error repeatedly:

prompt_vcs_precmd:6: failed to close file descriptor 11: bad file descriptor


> There is a comment in prompt_vcs_precmd that says it's going to kill a
> process while in fact it closes the file descriptor. That may
> *eventually* kill the process when it decides to print something
> (assuming it hasn't blocked SIGPIPE or is checking for write errors).

True. I'll change it to actually kill the process, too.


> What is the purpose of the "Info is not for current dir" check? Is
> this to account for the possibility of `cd` from a zle widget? If so,
> perhaps handle this by hooking chpwd?

The purpose is to account for the possibility that we receive the info
_after_ we've already changed to a new dir. However, if I correct the
piece of code you mentioned previously, then that shouldn't be
necessary.


> prompt_vcs_fd-widget has a check for [[ -n $1 ]]. When is it false?

When prompt_vcs_fd-widget is being called incorrectly. :) Perhaps it
should not return 1 in that case, though.


Thanks again. New version of the patch attached.

[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 7392 bytes --]

From 11f84b43e90854ae4c03aa072e110ec494da2d33 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Thu, 10 Jun 2021 16:45:30 +0300
Subject: [PATCH] Add customizable `vcs` prompt theme

---
 Functions/Prompts/prompt_vcs_setup | 199 +++++++++++++++++++++++++++++
 1 file changed, 199 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..c2f2e6cde
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,199 @@
+##
+# Prompt that can be customized through vcs_info
+#
+zmodload -F zsh/system p:sysparams
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Prompt segments
+# Normal %b and %(...) need extra % in vcs_info -- except in nvcsformats.
+readonly -gHA _prompt_vcs_ps1_default=(
+    left      $'%%(?,%F{green},%F{red})%#%%b%f%%s '
+    right     '%B%F{blue}%n%b%f%k@%F{magenta}%m%f'
+    chpwd     $'\n%B%F{blue}%~%%b%f/\n'
+    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 -- \
+"Customizable prompt theme that includes VCS info for the current dir (for
+example, git status) and asynchronously checks for repo changes.
+
+To customize it, copy-paste any of the code below to your .zshrc file and edit
+it there:
+
+  # For each of the following three entries:
+  #   1st string is the left prompt.
+  #   2nd string is the right prompt.
+  #   3rd string is printed whenever you change dirs (before the left prompt).
+
+  # Normal prompt:
+  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \\
+      "${(q+)_prompt_vcs_ps1_default[left]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_ps1_default[right]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_ps1_default[chpwd]//'%%'/%}"
+
+  # Prompt inside VCS repo:
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+)_prompt_vcs_ps1_default[left]} \\
+      ${(q+):-%u%c$_prompt_vcs_ps1_default[branch]$_prompt_vcs_ps1_default[repo]} \\
+      ${(q+)_prompt_vcs_ps1_default[chpwd]}
+
+  # Prompt during ongoing VCS action:
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+)_prompt_vcs_ps1_default[left]} \\
+      ${(q+):-%u%c$_prompt_vcs_ps1_default[action]$_prompt_vcs_ps1_default[repo]} \\
+      ${(q+)_prompt_vcs_ps1_default[chpwd]}
+
+  # These customize the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_ps1_default[staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_ps1_default[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_default[left]//'%%'/%}" \
+      "${_prompt_vcs_ps1_default[right]//'%%'/%}" \
+      "${_prompt_vcs_ps1_default[chpwd]//'%%'/%}"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_ps1_default[left]" \
+      "%u%c$_prompt_vcs_ps1_default[branch]$_prompt_vcs_ps1_default[repo]" \
+      "$_prompt_vcs_ps1_default[chpwd]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_ps1_default[left]" \
+      "%u%c$_prompt_vcs_ps1_default[action]$_prompt_vcs_ps1_default[repo]" \
+      "$_prompt_vcs_ps1_default[chpwd]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_ps1_default[staged]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_ps1_default[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
+  )}" )
+  PS1="$_prompt_vcs_info_msg_[1]"
+  RPS1="$_prompt_vcs_info_msg_[2]"
+  print -nPr -- "$_prompt_vcs_info_msg_[3]"
+}
+
+# We need to use line-init instead of precmd, because any widget can
+# potentially change the state of the repo or change dir without accepting or
+# aborting the command line.
+prompt_vcs_line-init() {
+  emulate -L zsh
+
+  # Terminate any pending vcs_info request before starting a new one.
+  # Second test checks if fd is readable, to avoid this error being printed:
+  #   failed to close file descriptor XX: bad file descriptor
+  if (( prompt_vcs_fd )) && { : <&$prompt_vcs_fd } 2>/dev/null; then
+    zle -F "$prompt_vcs_fd" 2> /dev/null
+    exec {prompt_vcs_fd}<&-
+  fi
+  if (( prompt_vcs_pid )); then
+    [[ -o monitor ]] &&
+        (( prompt_vcs_pid *= -1 ))
+    kill -KILL $prompt_vcs_pid 2> /dev/null
+  fi
+
+  # Asynchronously check for changes.
+  typeset -gH prompt_vcs_fd=
+  exec {prompt_vcs_fd}< <(
+	  print -r -- $sysparams[pid]
+    _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
+  )
+  typeset -gH prompt_vcs_pid=
+  read -u $prompt_vcs_fd -- prompt_vcs_pid
+
+  # Add callback. Needs to be a widget, so we can refresh the prompt.
+  zle -Fw "$prompt_vcs_fd" prompt_vcs_fd-widget
+}
+
+# Callback widget for our async fetch of VCS changes
+zle -N prompt_vcs_fd-widget
+prompt_vcs_fd-widget() {
+  emulate -L zsh
+
+  (( $1 )) ||
+      return 64  # EX_USAGE; see man 3 sysexits
+
+  local -i fd=$1
+  local -a reply
+  {
+    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+
+    [[ -z $2 ]] ||
+        return 74  # EX_IOERR
+
+    IFS=$'\0' read -Aru "$fd"
+    typeset -gHa _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+    PS1="$_prompt_vcs_info_msg_[1]"
+    RPS1="$_prompt_vcs_info_msg_[2]"
+    zle .reset-prompt
+  } always {
+    exec {fd}<&-
+  }
+}
+
+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'
+  PS4+='  %(1_,%F{yellow}%K{black}%_%f%k ,)'
+  SPROMPT='Correct %B%F{red}%S%R%b%f%s to %B%F{green}%r%b%f?'
+  SPROMPT+=$'\n%{\e[2m%}%Uy%ues %Un%uo %Ue%udit %Ua%ubort%b '
+  PROMPT_EOL_MARK='%F{cyan}%S%#%f%s'
+  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-zle-hook-widget line-init prompt_vcs_line-init
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.30.1 (Apple Git-130)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-10 13:47                                               ` Marlon Richert
@ 2021-06-10 14:01                                                 ` Marlon Richert
  2021-06-10 17:45                                                 ` Roman Perepelitsa
  1 sibling, 0 replies; 65+ messages in thread
From: Marlon Richert @ 2021-06-10 14:01 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 2317 bytes --]

Actually, I just realized that what I was doing with line-init is not
actually solving my problem. So, here's a new version of the patch
that simply lets chpwd call precmd. See attachment.

On Thu, Jun 10, 2021 at 4:47 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> On Thu, Jun 10, 2021 at 12:30 PM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > There is //'%%'/% in a few places. What's the logic behind it?
>
> Some prompt escape codes (such as %b for bold) need %% when used in
> vcs_info -- except when they are used in nvcsformats.
>
>
> > I think invoking prompt_vcs_setup twice in the same shell will produce
> > an error. I haven't tried it though.
>
> I just tried it and I didn't get any errors. Why do you think it would
> produce an error?
>
>
> > prompt_vcs_chpwd always prints at least one line to the TTY regardless
> > of configuration options. Is this intended?
>
> Yes, that was my intention, but I can see how it could be useful to be
> able to customize that. I'll change it.
>
>
> > Why is prompt_vcs_precmd checking whether prompt_vcs_fd is a readable
> > fd? How can it not be?
>
> I don't know how or why, but if I don't check for that, then I get
> this error repeatedly:
>
> prompt_vcs_precmd:6: failed to close file descriptor 11: bad file descriptor
>
>
> > There is a comment in prompt_vcs_precmd that says it's going to kill a
> > process while in fact it closes the file descriptor. That may
> > *eventually* kill the process when it decides to print something
> > (assuming it hasn't blocked SIGPIPE or is checking for write errors).
>
> True. I'll change it to actually kill the process, too.
>
>
> > What is the purpose of the "Info is not for current dir" check? Is
> > this to account for the possibility of `cd` from a zle widget? If so,
> > perhaps handle this by hooking chpwd?
>
> The purpose is to account for the possibility that we receive the info
> _after_ we've already changed to a new dir. However, if I correct the
> piece of code you mentioned previously, then that shouldn't be
> necessary.
>
>
> > prompt_vcs_fd-widget has a check for [[ -n $1 ]]. When is it false?
>
> When prompt_vcs_fd-widget is being called incorrectly. :) Perhaps it
> should not return 1 in that case, though.
>
>
> Thanks again. New version of the patch attached.

[-- Attachment #2: 0001-Add-customizable-vcs-prompt-theme.txt --]
[-- Type: text/plain, Size: 7300 bytes --]

From f08adb8d99e3ec162aacb8a217028b7a2dc5d4ca Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@gmail.com>
Date: Thu, 10 Jun 2021 16:58:33 +0300
Subject: [PATCH] Add customizable 'vcs' prompt theme

---
 Functions/Prompts/prompt_vcs_setup | 199 +++++++++++++++++++++++++++++
 1 file changed, 199 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..5e3ecf615
--- /dev/null
+++ b/Functions/Prompts/prompt_vcs_setup
@@ -0,0 +1,199 @@
+##
+# Prompt that can be customized through vcs_info
+#
+zmodload -F zsh/system p:sysparams
+autoload -Uz add-zle-hook-widget add-zsh-hook vcs_info
+
+# Prompt segments
+# Normal %b and %(...) need extra % in vcs_info -- except in nvcsformats.
+readonly -gHA _prompt_vcs_ps1_default=(
+    left      $'%%(?,%F{green},%F{red})%#%%b%f%%s '
+    right     '%B%F{blue}%n%b%f%k@%F{magenta}%m%f'
+    chpwd     $'\n%B%F{blue}%~%%b%f/\n'
+    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 -- \
+"Customizable prompt theme that includes VCS info for the current dir (for
+example, git status) and asynchronously checks for repo changes.
+
+To customize it, copy-paste any of the code below to your .zshrc file and edit
+it there:
+
+  # For each of the following three entries:
+  #   1st string is the left prompt.
+  #   2nd string is the right prompt.
+  #   3rd string is printed whenever you change dirs (before the left prompt).
+
+  # Normal prompt:
+  zstyle ':vcs_info:*:prompt_vcs:*' nvcsformats \\
+      "${(q+)_prompt_vcs_ps1_default[left]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_ps1_default[right]//'%%'/%}" \\
+      "${(q+)_prompt_vcs_ps1_default[chpwd]//'%%'/%}"
+
+  # Prompt inside VCS repo:
+  zstyle ':vcs_info:*:prompt_vcs:*' formats \\
+      ${(q+)_prompt_vcs_ps1_default[left]} \\
+      ${(q+):-%u%c$_prompt_vcs_ps1_default[branch]$_prompt_vcs_ps1_default[repo]} \\
+      ${(q+)_prompt_vcs_ps1_default[chpwd]}
+
+  # Prompt during ongoing VCS action:
+  zstyle ':vcs_info:*:prompt_vcs:*' actionformats \\
+      ${(q+)_prompt_vcs_ps1_default[left]} \\
+      ${(q+):-%u%c$_prompt_vcs_ps1_default[action]$_prompt_vcs_ps1_default[repo]} \\
+      ${(q+)_prompt_vcs_ps1_default[chpwd]}
+
+  # These customize the values of %c and %u, respectively:
+  zstyle ':vcs_info:*:prompt_vcs:*' stagedstr ${(q+)_prompt_vcs_ps1_default[staged]}
+  zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr ${(q+)_prompt_vcs_ps1_default[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_default[left]//'%%'/%}" \
+      "${_prompt_vcs_ps1_default[right]//'%%'/%}" \
+      "${_prompt_vcs_ps1_default[chpwd]//'%%'/%}"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' formats \
+      "$_prompt_vcs_ps1_default[left]" \
+      "%u%c$_prompt_vcs_ps1_default[branch]$_prompt_vcs_ps1_default[repo]" \
+      "$_prompt_vcs_ps1_default[chpwd]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' actionformats \
+      "$_prompt_vcs_ps1_default[left]" \
+      "%u%c$_prompt_vcs_ps1_default[action]$_prompt_vcs_ps1_default[repo]" \
+      "$_prompt_vcs_ps1_default[chpwd]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' stagedstr \
+      "$_prompt_vcs_ps1_default[staged]"
+
+  _prompt_vcs_zstyle ':vcs_info:*:prompt_vcs:*' unstagedstr \
+      "$_prompt_vcs_ps1_default[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
+  )}" )
+  PS1="$_prompt_vcs_info_msg_[1]"
+  RPS1="$_prompt_vcs_info_msg_[2]"
+  print -nPr -- "$_prompt_vcs_info_msg_[3]"
+  
+  # Call precmd just in case, because chpwd can happen without a new prompt.
+  prompt_vcs_precmd
+}
+
+prompt_vcs_precmd() {
+  emulate -L zsh
+
+  # Terminate any pending vcs_info request before starting a new one.
+  # Second test checks if fd is readable, to avoid this error being printed:
+  #   failed to close file descriptor XX: bad file descriptor
+  if (( prompt_vcs_fd )) && { : <&$prompt_vcs_fd } 2>/dev/null; then
+    zle -F "$prompt_vcs_fd" 2> /dev/null
+    exec {prompt_vcs_fd}<&-
+  fi
+  if (( prompt_vcs_pid )); then
+    [[ -o monitor ]] &&
+        (( prompt_vcs_pid *= -1 ))
+    kill -KILL $prompt_vcs_pid 2> /dev/null
+  fi
+
+  # Asynchronously check for changes.
+  typeset -gH prompt_vcs_fd=
+  exec {prompt_vcs_fd}< <(
+	  print -r -- $sysparams[pid]
+    _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
+  )
+  typeset -gH prompt_vcs_pid=
+  read -u $prompt_vcs_fd -- prompt_vcs_pid
+
+  # Add callback. Needs to be a widget, so we can refresh the prompt.
+  zle -Fw "$prompt_vcs_fd" prompt_vcs_fd-widget
+}
+
+# Callback widget for our async fetch of VCS changes
+zle -N prompt_vcs_fd-widget
+prompt_vcs_fd-widget() {
+  emulate -L zsh
+
+  (( $1 )) ||
+      return 64  # EX_USAGE; see man 3 sysexits
+
+  local -i fd=$1
+  local -a reply
+  {
+    zle -F "$fd"  # Detach ourselves, so we don't get called more than once.
+
+    [[ -z $2 ]] ||
+        return 74  # EX_IOERR
+
+    IFS=$'\0' read -Aru "$fd"
+    typeset -gHa _prompt_vcs_info_msg_=( "${(@Q)reply}" )
+    PS1="$_prompt_vcs_info_msg_[1]"
+    RPS1="$_prompt_vcs_info_msg_[2]"
+    zle .reset-prompt
+  } always {
+    exec {fd}<&-
+  }
+}
+
+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'
+  PS4+='  %(1_,%F{yellow}%K{black}%_%f%k ,)'
+  SPROMPT='Correct %B%F{red}%S%R%b%f%s to %B%F{green}%r%b%f?'
+  SPROMPT+=$'\n%{\e[2m%}%Uy%ues %Un%uo %Ue%udit %Ua%ubort%b '
+  PROMPT_EOL_MARK='%F{cyan}%S%#%f%s'
+  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
+
+  prompt_vcs_chpwd
+}
+
+prompt_vcs_setup "$@"
-- 
2.30.1 (Apple Git-130)


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-10 13:47                                               ` Marlon Richert
  2021-06-10 14:01                                                 ` Marlon Richert
@ 2021-06-10 17:45                                                 ` Roman Perepelitsa
  2021-06-20 22:13                                                   ` Marlon Richert
  1 sibling, 1 reply; 65+ messages in thread
From: Roman Perepelitsa @ 2021-06-10 17:45 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

On Thu, Jun 10, 2021 at 3:48 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> Thanks again. New version of the patch attached.

Thanks! A few more comments/questions. Those that I'm not quoting can
be considered resolved.

> On Thu, Jun 10, 2021 at 12:30 PM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > I think invoking prompt_vcs_setup twice in the same shell will produce
> > an error. I haven't tried it though.
>
> I just tried it and I didn't get any errors. Why do you think it would
> produce an error?

I was expecting the readonly parameter at the top to print an error.

  % readonly -gHA _prompt_vcs_ps1_default=()
  % readonly -gHA _prompt_vcs_ps1_default=()
  zsh: read-only variable: _prompt_vcs_ps1_default

It's also unclear to me whether this prompt supports clean
deinitialization and repeated initialization. Doesn't look like it.
Does it?

> > Why is prompt_vcs_precmd checking whether prompt_vcs_fd is a readable
> > fd? How can it not be?
>
> I don't know how or why, but if I don't check for that, then I get
> this error repeatedly:
>
> prompt_vcs_precmd:6: failed to close file descriptor 11: bad file descriptor

Then the check must be masking a bug. This bug can result in the
closing of another file descriptor that is not owned by prompt_vcs.

I took a quick look and perhaps the bug is due to prompt_vcs_fd-widget
not unsetting prompt_vcs_fd?

> > There is a comment in prompt_vcs_precmd that says it's going to kill a
> > process while in fact it closes the file descriptor. That may
> > *eventually* kill the process when it decides to print something
> > (assuming it hasn't blocked SIGPIPE or is checking for write errors).
>
> True. I'll change it to actually kill the process, too.

I see that the code is sending SIGKILL now and not waiting for the
process to terminate. Both of these make me nervous. The code also
*looks like* it would work without monitor but it wouldn't (it would
result in unbounded background processes and zombies). What do you
think about not killing anything and ensuring that at most one
background process runs at once? This is what I do in my zsh theme and
it works well.

> > prompt_vcs_fd-widget has a check for [[ -n $1 ]]. When is it false?
>
> When prompt_vcs_fd-widget is being called incorrectly. :)

When can it be called incorrectly?

This is not a public function, it's a callback that is passed to `zle
-F`. Do you expect the latter to violate its contract in this specific
way? If not, I would remove the check. It's increasing the complexity
of the code without material gain.

> Perhaps it should not return 1 in that case, though.

The return code of `zle -F` callbacks is ignored. Adding specific
return codes makes it appear as if they matter. This makes the code
harder to understand similarly to conditions that are always false.

The file descriptor leaks to child processes. It's better to avoid
this. This can be done by using sysopen with cloexec instead of plain
exec.

Instead of printing the pid and reading it in the parent you can use
$sysparams[procsubstpid].

Why does _prompt_vcs_info quote its output? If it didn't quote, then
there would be no need to unquote after reading.

Handling errors from `read` would be nice.

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-10 17:45                                                 ` Roman Perepelitsa
@ 2021-06-20 22:13                                                   ` Marlon Richert
  2021-06-23 17:26                                                     ` Roman Perepelitsa
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2021-06-20 22:13 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

On Thu, Jun 10, 2021 at 8:45 PM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> I was expecting the readonly parameter at the top to print an error.
>
>   % readonly -gHA _prompt_vcs_ps1_default=()
>   % readonly -gHA _prompt_vcs_ps1_default=()
>   zsh: read-only variable: _prompt_vcs_ps1_default

That doesn't actually happen, because prompt_vcs_setup gets redefined
inside the first call to prompt_vcs_setup. $_prompt_vcs_ps1_default
gets set only the first time you call prompt_vcs_setup.


> It's also unclear to me whether this prompt supports clean
> deinitialization and repeated initialization. Doesn't look like it.
> Does it?

You're supposed to use this prompt theme with prompinit's `prompt`
function. If you do so, then deinitialization and repeated
initialization is pretty much clean, as far as I can tell. Is there
anything in particular that I should be checking?


> > > Why is prompt_vcs_precmd checking whether prompt_vcs_fd is a readable
> > > fd? How can it not be?
> >
> > I don't know how or why, but if I don't check for that, then I get
> > this error repeatedly:
> >
> > prompt_vcs_precmd:6: failed to close file descriptor 11: bad file descriptor
>
> Then the check must be masking a bug. This bug can result in the
> closing of another file descriptor that is not owned by prompt_vcs.
>
> I took a quick look and perhaps the bug is due to prompt_vcs_fd-widget
> not unsetting prompt_vcs_fd?

You're right: Unsetting prompt_vcs_fd in prompt_vcs_fd-widget fixes it. Thanks!


> I see that the code is sending SIGKILL now and not waiting for the
> process to terminate. Both of these make me nervous. The code also
> *looks like* it would work without monitor but it wouldn't (it would
> result in unbounded background processes and zombies). What do you
> think about not killing anything and ensuring that at most one
> background process runs at once? This is what I do in my zsh theme and
> it works well.

That sounds great, but I have no idea how to do that. :) Can you give
me some pointers?


> Handling errors from `read` would be nice.

What kind of errors?


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-20 22:13                                                   ` Marlon Richert
@ 2021-06-23 17:26                                                     ` Roman Perepelitsa
  2022-08-08 10:12                                                       ` Marlon Richert
  0 siblings, 1 reply; 65+ messages in thread
From: Roman Perepelitsa @ 2021-06-23 17:26 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

On Mon, Jun 21, 2021 at 12:14 AM Marlon Richert
<marlon.richert@gmail.com> wrote:
>
> On Thu, Jun 10, 2021 at 8:45 PM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > I was expecting the readonly parameter at the top to print an error.
> >
> >   % readonly -gHA _prompt_vcs_ps1_default=()
> >   % readonly -gHA _prompt_vcs_ps1_default=()
> >   zsh: read-only variable: _prompt_vcs_ps1_default
>
> That doesn't actually happen, because prompt_vcs_setup gets redefined
> inside the first call to prompt_vcs_setup. $_prompt_vcs_ps1_default
> gets set only the first time you call prompt_vcs_setup.

I see. Makes sense.

> > It's also unclear to me whether this prompt supports clean
> > deinitialization and repeated initialization. Doesn't look like it.
> > Does it?
>
> You're supposed to use this prompt theme with prompinit's `prompt`
> function.

Yes, I realize that.

> If you do so, then deinitialization and repeated
> initialization is pretty much clean, as far as I can tell.
> Is there anything in particular that I should be checking?

It's not obvious to me that deinitialization will happen. Imagine what
would happen if another theme is enabled while there is a process
running in the background from your theme. Won't your theme change
prompt when the background process finishes?

By the way, would running `prompt -p` unintentionally enabled your theme?

> > I see that the code is sending SIGKILL now and not waiting for the
> > process to terminate. Both of these make me nervous. The code also
> > *looks like* it would work without monitor but it wouldn't (it would
> > result in unbounded background processes and zombies). What do you
> > think about not killing anything and ensuring that at most one
> > background process runs at once? This is what I do in my zsh theme and
> > it works well.
>
> That sounds great, but I have no idea how to do that. :) Can you give
> me some pointers?

Start a new process in precmd if none are running. If one is already
running, don't start a new process but remember that its results are
"dirty". When a background process completes, display its results if
they aren't marked dirty. If they are marked dirty, don't display the
results but start a new process instead.

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2021-06-23 17:26                                                     ` Roman Perepelitsa
@ 2022-08-08 10:12                                                       ` Marlon Richert
  2022-08-08 10:17                                                         ` Roman Perepelitsa
  0 siblings, 1 reply; 65+ messages in thread
From: Marlon Richert @ 2022-08-08 10:12 UTC (permalink / raw)
  To: Roman Perepelitsa; +Cc: Zsh hackers list

On Wed, Jun 23, 2021 at 8:26 PM Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
>
> > > I see that the code is sending SIGKILL now and not waiting for the
> > > process to terminate. Both of these make me nervous. The code also
> > > *looks like* it would work without monitor but it wouldn't (it would
> > > result in unbounded background processes and zombies). What do you
> > > think about not killing anything and ensuring that at most one
> > > background process runs at once? This is what I do in my zsh theme and
> > > it works well.
> >
> > That sounds great, but I have no idea how to do that. :) Can you give
> > me some pointers?
>
> Start a new process in precmd if none are running. If one is already
> running, don't start a new process but remember that its results are
> "dirty". When a background process completes, display its results if
> they aren't marked dirty. If they are marked dirty, don't display the
> results but start a new process instead.

Using this approach, how would you deal with processes that (for all
practical purposes) might potentially never finish? In that case, your
callback function will never get called and you'll never start a new
process again.


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme)
  2022-08-08 10:12                                                       ` Marlon Richert
@ 2022-08-08 10:17                                                         ` Roman Perepelitsa
  0 siblings, 0 replies; 65+ messages in thread
From: Roman Perepelitsa @ 2022-08-08 10:17 UTC (permalink / raw)
  To: Marlon Richert; +Cc: Zsh hackers list

On Mon, Aug 8, 2022 at 12:13 PM Marlon Richert <marlon.richert@gmail.com> wrote:
>
> On Wed, Jun 23, 2021 at 8:26 PM Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> > Start a new process in precmd if none are running. If one is already
> > running, don't start a new process but remember that its results are
> > "dirty". When a background process completes, display its results if
> > they aren't marked dirty. If they are marked dirty, don't display the
> > results but start a new process instead.
>
> Using this approach, how would you deal with processes that (for all
> practical purposes) might potentially never finish? In that case, your
> callback function will never get called and you'll never start a new
> process again.

Correct. I consider this behavior desirable. There should be a visual
clue to indicate that the system is awaiting a background process to
complete. The fact that this indicator will stay forever will make it
clear that the process that is supposed to terminate has hung up.

Roman.


^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2022-08-08 10:18 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-13 19:41 [RFC][PATCH] `newuser` prompt theme Marlon
2021-04-13 20:31 ` Roman Perepelitsa
2021-04-13 20:44 ` Bart Schaefer
2021-04-14  5:09   ` Marlon Richert
2021-04-14  5:17     ` Bart Schaefer
2021-04-14  5:45       ` Marlon
2021-04-14 12:05         ` Daniel Shahaf
2021-04-14 13:17           ` Marlon
2021-04-14 14:09             ` Daniel Shahaf
2021-04-15  1:07               ` Bart Schaefer
2021-04-15  3:50               ` Marlon Richert
2021-04-15 20:27                 ` Daniel Shahaf
2021-04-15 23:42                 ` Daniel Shahaf
2021-04-15 11:11               ` Mikael Magnusson
2021-04-15 16:44                 ` vcs_info's global variables (was: Re: [RFC][PATCH] `newuser` prompt theme) Daniel Shahaf
2021-04-16 16:04                 ` [RFC][PATCH] `newuser` prompt theme Marlon
2021-04-16 17:13                   ` Daniel Shahaf
2021-04-16 19:19                     ` Marlon Richert
2021-04-16 19:30                       ` Daniel Shahaf
2021-04-19 16:46                         ` Marlon Richert
2021-05-02 17:18                           ` Lawrence Velázquez
2021-05-03  2:38                             ` Bart Schaefer
2021-05-03  4:11                               ` Lawrence Velázquez
2021-05-03 11:38                                 ` [PATCH] Add customizable `vcs` prompt theme (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon Richert
2021-05-09 18:04                                   ` Lawrence Velázquez
2021-05-31  1:01                                     ` Lawrence Velázquez
2021-06-09 12:58                                       ` Marlon Richert
2021-06-09 13:22                                         ` Roman Perepelitsa
2021-06-09 18:06                                           ` Marlon Richert
2021-06-10  9:30                                             ` Roman Perepelitsa
2021-06-10 13:47                                               ` Marlon Richert
2021-06-10 14:01                                                 ` Marlon Richert
2021-06-10 17:45                                                 ` Roman Perepelitsa
2021-06-20 22:13                                                   ` Marlon Richert
2021-06-23 17:26                                                     ` Roman Perepelitsa
2022-08-08 10:12                                                       ` Marlon Richert
2022-08-08 10:17                                                         ` Roman Perepelitsa
2021-04-14 14:09             ` sysexits.h codes? (was: " Daniel Shahaf
2021-04-30 19:40               ` Marlon Richert
2021-04-30 21:16                 ` Daniel Shahaf
2021-04-30 21:34                   ` Bart Schaefer
2021-05-01 15:09                     ` Daniel Shahaf
2021-04-30 21:40                   ` Bart Schaefer
2021-05-01 13:39                   ` Marlon Richert
2021-05-01 14:43                     ` Daniel Shahaf
2021-05-03 11:36                       ` Marlon Richert
2021-05-03 16:04                         ` Daniel Shahaf
2021-05-04 11:13                           ` Marlon Richert
2021-05-21 11:38                             ` Marlon Richert
2021-04-14 15:30             ` [RFC][PATCH] `newuser` prompt theme Arseny Maslennikov
2021-04-14 18:52               ` Daniel Shahaf
2021-04-14 14:00           ` precmd hooks and $? Bart Schaefer
2021-04-14 15:18             ` docs patches for precmd hooks and $?, and vcs_info Daniel Shahaf
2021-04-15  2:35               ` Bart Schaefer
2021-04-15 16:17               ` Archives render attachments as first-class messages (was: docs patches for precmd hooks and $?, and vcs_info) Daniel Shahaf
2021-04-15 18:54           ` [RFC][PATCH] Reset ZLE hooks when changing prompt themes (was Re: [RFC][PATCH] `newuser` prompt theme) Marlon
2021-04-15 21:34             ` Daniel Shahaf
2021-04-16 22:34               ` Marlon Richert
2021-04-25 16:08                 ` Lawrence Velázquez
2021-05-02 17:03                   ` Lawrence Velázquez
2021-05-02 17:59                 ` Bart Schaefer
2021-05-05  6:10                   ` Marlon Richert
2021-05-16 15:27                     ` Lawrence Velázquez
2021-05-16 19:31                       ` Marlon Richert
2021-05-17  4:19                         ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).