Skip to content

Commit

Permalink
Prevent multiple prompt resets in one execution cycle (#368)
Browse files Browse the repository at this point in the history
* Update zsh-async to 1.6.0 for buffer status indicator

* Prevent multiple prompt resets in one execution cycle

The prompt ends up in a weird state when `zle reset-prompt` is called
multiple times during one execution cycle. This can happen when multiple
async tasks finish at nearly the same time. What happened here is that
`async_process_results` called `prompt_pure_async_callback` multiple
times during it's execution. In turn, `prompt_pure_async_callback` did
multiple calls to `zle reset-prompt`. My theory is that ZLE ends up in a
weird state that is reset after all the current code has completed
executing.

This behavior is observable when the prompt "moves upwards" and erases
previous lines in the terminal.

Fixes #356.
  • Loading branch information
mafredri authored and sindresorhus committed Nov 22, 2017
1 parent f23e726 commit a3b22b2
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 11 deletions.
14 changes: 8 additions & 6 deletions async.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# zsh-async
#
# version: 1.5.2
# version: 1.6.0
# author: Mathias Fredriksson
# url: https://github.com/mafredri/zsh-async
#
Expand Down Expand Up @@ -202,6 +202,7 @@ _async_worker() {
# $3 = resulting stdout from execution
# $4 = execution time, floating point e.g. 2.05 seconds
# $5 = resulting stderr from execution
# $6 = has next result in buffer (0 = buffer empty, 1 = yes)
#
async_process_results() {
setopt localoptions unset noshwordsplit noksharrays noposixidentifiers noposixstrings
Expand Down Expand Up @@ -234,7 +235,13 @@ async_process_results() {
# Remove the extracted items from the buffer.
ASYNC_PROCESS_BUFFER[$worker]=${ASYNC_PROCESS_BUFFER[$worker][$pos+1,$len]}

len=${#ASYNC_PROCESS_BUFFER[$worker]}
if (( len > 1 )); then
pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).
fi

if (( $#items == 5 )); then
items+=($(( len != 0 )))
$callback "${(@)items}" # Send all parsed items to the callback.
else
# In case of corrupt data, invoke callback with *async* as job
Expand All @@ -243,11 +250,6 @@ async_process_results() {
fi

(( num_processed++ ))

len=${#ASYNC_PROCESS_BUFFER[$worker]}
if (( len > 1 )); then
pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).
fi
done
done

Expand Down
19 changes: 14 additions & 5 deletions pure.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ prompt_pure_check_git_arrows() {

prompt_pure_async_callback() {
setopt localoptions noshwordsplit
local job=$1 code=$2 output=$3 exec_time=$4
local job=$1 code=$2 output=$3 exec_time=$4 next_pending=$6
local do_render=0

case $job in
prompt_pure_async_vcs_info)
Expand Down Expand Up @@ -371,7 +372,7 @@ prompt_pure_async_callback() {
prompt_pure_vcs_info[branch]=$info[branch]
prompt_pure_vcs_info[top]=$info[top]

prompt_pure_preprompt_render
do_render=1
;;
prompt_pure_async_git_aliases)
if [[ -n $output ]]; then
Expand All @@ -387,7 +388,7 @@ prompt_pure_async_callback() {
typeset -g prompt_pure_git_dirty="*"
fi

[[ $prev_dirty != $prompt_pure_git_dirty ]] && prompt_pure_preprompt_render
[[ $prev_dirty != $prompt_pure_git_dirty ]] && do_render=1

# When prompt_pure_git_last_dirty_check_timestamp is set, the git info is displayed in a different color.
# To distinguish between a "fresh" and a "cached" result, the preprompt is rendered before setting this
Expand All @@ -402,19 +403,27 @@ prompt_pure_async_callback() {
prompt_pure_check_git_arrows ${(ps:\t:)output}
if [[ $prompt_pure_git_arrows != $REPLY ]]; then
typeset -g prompt_pure_git_arrows=$REPLY
prompt_pure_preprompt_render
do_render=1
fi
elif (( code != 99 )); then
# Unless the exit code is 99, prompt_pure_async_git_arrows
# failed with a non-zero exit status, meaning there is no
# upstream configured.
if [[ -n $prompt_pure_git_arrows ]]; then
unset prompt_pure_git_arrows
prompt_pure_preprompt_render
do_render=1
fi
fi
;;
esac

if (( next_pending )); then
(( do_render )) && typeset -g prompt_pure_async_render_requested=1
return
fi

[[ ${prompt_pure_async_render_requested:-$do_render} = 1 ]] && prompt_pure_preprompt_render
unset prompt_pure_async_render_requested
}

prompt_pure_setup() {
Expand Down

0 comments on commit a3b22b2

Please sign in to comment.