083cc2c8e8742bab8cce8c73a3e96f398e6b2da7
- Author
- Marc Cornellà <marc@mcornella.com>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/lib/async_prompt.zsh b/lib/async_prompt.zsh
2new file mode 100644
3index 0000000000000000000000000000000000000000..c6d03328b16f4a64e80ee344b0399de8c205bd9b
4--- /dev/null
5+++ b/lib/async_prompt.zsh
6@@ -0,0 +1,140 @@
7+# The async code is taken from
8+# https://github.com/zsh-users/zsh-autosuggestions/blob/master/src/async.zsh
9+# https://github.com/woefe/git-prompt.zsh/blob/master/git-prompt.zsh
10+
11+zmodload zsh/system
12+
13+# For now, async prompt function handlers are set up like so:
14+# First, define the async function handler and add the function name
15+# to the _omz_async_functions array:
16+#
17+# function _git_prompt_status_async {
18+# # Do some expensive operation that outputs to stdout
19+# }
20+# _omz_register_handler _git_prompt_status_async
21+#
22+# Then add a stub prompt function in `$PROMPT` or similar prompt variables,
23+# which will show the output of "$_OMZ_ASYNC_OUTPUT[handler_name]":
24+#
25+# function git_prompt_status {
26+# echo -n $_OMZ_ASYNC_OUTPUT[_git_prompt_status]
27+# }
28+#
29+# RPROMPT='$(git_prompt_status)'
30+#
31+# This API is subject to change and optimization. Rely on it at your own risk.
32+
33+function _omz_register_handler {
34+ setopt localoptions noksharrays
35+ typeset -ga _omz_async_functions
36+ # we want to do nothing if there's no $1 function or we already set it up
37+ if [[ -z "$1" ]] || (( ! ${+functions[$1]} )) \
38+ || (( ${_omz_async_functions[(Ie)$1]} )); then
39+ return
40+ fi
41+ _omz_async_functions+=("$1")
42+ # let's add the hook to async_request if it's not there yet
43+ if (( ! ${precmd_functions[(Ie)_omz_async_request]} )) \
44+ && (( ${+functions[_omz_async_request]})); then
45+ autoload -Uz add-zsh-hook
46+ add-zsh-hook precmd _omz_async_request
47+ fi
48+}
49+
50+# Set up async handlers and callbacks
51+function _omz_async_request {
52+ typeset -gA _OMZ_ASYNC_FDS _OMZ_ASYNC_PIDS _OMZ_ASYNC_OUTPUT
53+
54+ # executor runs a subshell for all async requests based on key
55+ local handler
56+ for handler in ${_omz_async_functions}; do
57+ (( ${+functions[$handler]} )) || continue
58+
59+ local fd=${_OMZ_ASYNC_FDS[$handler]:--1}
60+ local pid=${_OMZ_ASYNC_PIDS[$handler]:--1}
61+
62+ # If we've got a pending request, cancel it
63+ if (( fd != -1 && pid != -1 )) && { true <&$fd } 2>/dev/null; then
64+ # Close the file descriptor and remove the handler
65+ exec {fd}<&-
66+ zle -F $fd
67+
68+ # Zsh will make a new process group for the child process only if job
69+ # control is enabled (MONITOR option)
70+ if [[ -o MONITOR ]]; then
71+ # Send the signal to the process group to kill any processes that may
72+ # have been forked by the async function handler
73+ kill -TERM -$pid 2>/dev/null
74+ else
75+ # Kill just the child process since it wasn't placed in a new process
76+ # group. If the async function handler forked any child processes they may
77+ # be orphaned and left behind.
78+ kill -TERM $pid 2>/dev/null
79+ fi
80+ fi
81+
82+ # Define global variables to store the file descriptor, PID and output
83+ _OMZ_ASYNC_FDS[$handler]=-1
84+ _OMZ_ASYNC_PIDS[$handler]=-1
85+
86+ # Fork a process to fetch the git status and open a pipe to read from it
87+ exec {fd}< <(
88+ # Tell parent process our PID
89+ builtin echo ${sysparams[pid]}
90+ # Store handler name for callback
91+ builtin echo $handler
92+ # Run the async function handler
93+ $handler
94+ )
95+
96+ # Save FD for handler
97+ _OMZ_ASYNC_FDS[$handler]=$fd
98+
99+ # There's a weird bug here where ^C stops working unless we force a fork
100+ # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
101+ command true
102+
103+ # Save the PID from the handler child process
104+ read pid <&$fd
105+ _OMZ_ASYNC_PIDS[$handler]=$pid
106diff --git a/lib/git.zsh b/lib/git.zsh
107index f049f73c2029ee21018a4f2b9d31e49f2a09b27f..6f48234580f6b2bb88ff552670ff581ae0fc657b 100644
108--- a/lib/git.zsh
109+++ b/lib/git.zsh
110@@ -9,14 +9,18 @@ function __git_prompt_git() {
111 GIT_OPTIONAL_LOCKS=0 command git "$@"
112 }
113
114-function git_prompt_info() {
115+function _omz_git_prompt_status() {
116 # If we are on a folder not tracked by git, get out.
117 # Otherwise, check for hide-info at global and local repository level
118 if ! __git_prompt_git rev-parse --git-dir &> /dev/null \
119- || [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then
120+ || [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then
121 return 0
122 fi
123
124+ # Get either:
125+ # - the current branch name
126+ # - the tag name if we are on a tag
127+ # - the short SHA of the current commit
128 local ref
129 ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) \
130 || ref=$(__git_prompt_git describe --tags --exact-match HEAD 2> /dev/null) \
131@@ -33,6 +37,20 @@ function git_prompt_info() {
132 echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref:gs/%/%%}${upstream:gs/%/%%}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}"
133 }
134
135+# Enable async prompt by default unless the setting is at false / no
136+if zstyle -T ':omz:alpha:lib:git' async-prompt; then
137+ function git_prompt_info() {
138+ _omz_register_handler _omz_git_prompt_status
139+ if [[ -n "$_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]" ]]; then
140+ echo -n "$_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]"
141+ fi
142+ }
143+else
144+ function git_prompt_info() {
145+ _omz_git_prompt_status
146+ }
147+fi
148+
149 # Checks if working tree is dirty
150 function parse_git_dirty() {
151 local STATUS