06753e8146332aa787857fc5cc41caa2b5f753f0

Author
Marc Cornellà <marc@mcornella.com>
Committer
Marc Cornellà <marc@mcornella.com>
Date

Message

fix(async): register the git prompt async handler correctly (#12267)

This fix conditionally registers the git prompt async handler only
if `git_prompt_info` is used anywhere in the prompt variables.

This is done in the proper order, so that the async request is
processed once the handler has been registered.

This fix also passes the return value of the previous command
to each of the async handlers, in case they are needed.

Diff

 1diff --git a/lib/async_prompt.zsh b/lib/async_prompt.zsh
 2index c6d03328b16f4a64e80ee344b0399de8c205bd9b..384e49d33e9c2626b1b65df614e8ac14051cfbf5 100644
 3--- a/lib/async_prompt.zsh
 4+++ b/lib/async_prompt.zsh
 5@@ -5,8 +5,8 @@
 6 zmodload zsh/system
 7 
 8 # For now, async prompt function handlers are set up like so:
 9-# First, define the async function handler and add the function name
10-# to the _omz_async_functions array:
11+# First, define the async function handler and register the handler
12+# with _omz_register_handler:
13 #
14 #  function _git_prompt_status_async {
15 #    # Do some expensive operation that outputs to stdout
16@@ -17,7 +17,7 @@ zmodload zsh/system
17 # which will show the output of "$_OMZ_ASYNC_OUTPUT[handler_name]":
18 #
19 #  function git_prompt_status {
20-#    echo -n $_OMZ_ASYNC_OUTPUT[_git_prompt_status]
21+#    echo -n $_OMZ_ASYNC_OUTPUT[_git_prompt_status_async]
22 #  }
23 #
24 #  RPROMPT='$(git_prompt_status)'
25@@ -43,6 +43,7 @@ function _omz_register_handler {
26 
27 # Set up async handlers and callbacks
28 function _omz_async_request {
29+  local -i ret=$?
30   typeset -gA _OMZ_ASYNC_FDS _OMZ_ASYNC_PIDS _OMZ_ASYNC_OUTPUT
31 
32   # executor runs a subshell for all async requests based on key
33@@ -83,6 +84,8 @@ function _omz_async_request {
34       builtin echo ${sysparams[pid]}
35       # Store handler name for callback
36       builtin echo $handler
37+      # Set exit code for the handler if used
38+      (exit $ret)
39       # Run the async function handler
40       $handler
41     )
42@@ -138,3 +141,6 @@ function _omz_async_callback() {
43   _OMZ_ASYNC_FDS[$handler]=-1
44   _OMZ_ASYNC_PIDS[$handler]=-1
45 }
46+
47+autoload -Uz add-zsh-hook
48+add-zsh-hook precmd _omz_async_request
49diff --git a/lib/git.zsh b/lib/git.zsh
50index 8fe9990955f9ea828c0642446b10052d37340ece..96df5589dfb931cc1c08ddb035280377cf14aae4 100644
51--- a/lib/git.zsh
52+++ b/lib/git.zsh
53@@ -40,11 +40,29 @@ function _omz_git_prompt_status() {
54 # Enable async prompt by default unless the setting is at false / no
55 if zstyle -t ':omz:alpha:lib:git' async-prompt; then
56   function git_prompt_info() {
57-    _omz_register_handler _omz_git_prompt_status
58     if [[ -n "$_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]" ]]; then
59       echo -n "$_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]"
60     fi
61   }
62+
63+  # Conditionally register the async handler, only if it's needed in $PROMPT
64+  # or any of the other prompt variables
65+  function _defer_async_git_register() {
66+    # Check if git_prompt_info is used in a prompt variable
67+    case "${PS1}:${PS2}:${PS3}:${PS4}:${RPS1}:${RPS2}:${RPS3}:${RPS4}" in
68+    *(\$\(git_prompt_info\)|\`git_prompt_info\`)*)
69+      _omz_register_handler _omz_git_prompt_status
70+      return
71+      ;;
72+    esac
73+
74+    add-zsh-hook -d precmd _defer_async_git_register
75+    unset -f _defer_async_git_register
76+  }
77+
78+  # Register the async handler first. This needs to be done before
79+  # the async request prompt is run
80+  precmd_functions=(_defer_async_git_register $precmd_functions)
81 else
82   function git_prompt_info() {
83     _omz_git_prompt_status