update prezto

This commit is contained in:
2018-11-18 23:37:19 +04:00
parent a17ecf9f57
commit 2808949f26
352 changed files with 15169 additions and 25328 deletions

View File

@@ -60,10 +60,18 @@ Simply stops a worker and all active jobs will be terminated immediately.
Start a new asynchronous job on specified worker, assumes the worker is running.
#### `async_worker_eval <worker_name> <my_function> [<function_params>]`
Evaluate a command (like async_job) inside the async worker, then worker environment can be manipulated. For example, issuing a cd command will change the PWD of the worker which will then be inherited by all future async jobs.
Output will be returned via callback, job name will be [async/eval].
#### `async_process_results <worker_name> <callback_function>`
Get results from finished jobs and pass it to the to callback function. This is the only way to reliably return the job name, return code, output and execution time and with minimal effort.
If the async process buffer becomes corrupt, the callback will be invoked with the first argument being `[async]` (job name), non-zero return code and fifth argument describing the error (stderr).
The `callback_function` is called with the following parameters:
* `$1` job name, e.g. the function passed to async_job

View File

@@ -3,15 +3,26 @@
#
# zsh-async
#
# version: 1.6.2
# version: 1.7.1
# author: Mathias Fredriksson
# url: https://github.com/mafredri/zsh-async
#
typeset -g ASYNC_VERSION=1.6.2
typeset -g ASYNC_VERSION=1.7.1
# Produce debug output from zsh-async when set to 1.
typeset -g ASYNC_DEBUG=${ASYNC_DEBUG:-0}
# Execute commands that can manipulate the environment inside the async worker. Return output via callback.
_async_eval() {
local ASYNC_JOB_NAME
# Rename job to _async_eval and redirect all eval output to cat running
# in _async_job. Here, stdout and stderr are not separated for
# simplicity, this could be improved in the future.
{
eval "$@"
} &> >(ASYNC_JOB_NAME=[async/eval] _async_job 'cat')
}
# Wrapper for jobs executed by the async worker, gives output in parseable format with execution time
_async_job() {
# Disable xtrace as it would mangle the output.
@@ -26,6 +37,7 @@ _async_job() {
# block, after the command block has completed, the stdin for `cat` is
# closed, causing stderr to be appended with a $'\0' at the end to mark the
# end of output from this job.
local jobname=${ASYNC_JOB_NAME:-$1}
local stdout stderr ret tok
{
stdout=$(eval "$@")
@@ -36,7 +48,7 @@ _async_job() {
read -r -k 1 -p tok || exit 1
# Return output (<job_name> <return_code> <stdout> <duration> <stderr>).
print -r -n - ${(q)1} $ret ${(q)stdout} $duration
print -r -n - $'\0'${(q)jobname} $ret ${(q)stdout} $duration
} 2> >(stderr=$(cat) && print -r -n - " "${(q)stderr}$'\0')
# Unlock mutex by inserting a token.
@@ -80,7 +92,7 @@ _async_worker() {
unset $zsh_hook_functions # And hooks with registered functions.
unset zsh_hooks zsh_hook_functions # Cleanup.
child_exit() {
close_idle_coproc() {
local -a pids
pids=(${${(v)jobstates##*:*:}%\=*})
@@ -90,6 +102,10 @@ _async_worker() {
coproc :
coproc_pid=0
fi
}
child_exit() {
close_idle_coproc
# On older version of zsh (pre 5.2) we notify the parent through a
# SIGWINCH signal because `zpty` did not return a file descriptor (fd)
@@ -132,7 +148,7 @@ _async_worker() {
coproc_pid=0 # Reset pid.
}
local request
local request do_eval=0
local -a cmd
while :; do
# Wait for jobs sent by async_job.
@@ -147,8 +163,9 @@ _async_worker() {
# Check for non-job commands sent to worker
case $request in
_unset_trap) notify_parent=0; continue;;
_killjobs) killjobs; continue;;
_unset_trap) notify_parent=0; continue;;
_killjobs) killjobs; continue;;
_async_eval*) do_eval=1;;
esac
# Parse the request using shell parsing (z) to allow commands
@@ -181,18 +198,34 @@ _async_worker() {
print -n -p "t"
fi
# Run job in background, completed jobs are printed to stdout.
_async_job $cmd &
# Store pid because zsh job manager is extremely unflexible (show jobname as non-unique '$job')...
storage[$job]="$!"
if (( do_eval )); then
shift cmd # Strip _async_eval from cmd.
_async_eval $cmd
else
# Run job in background, completed jobs are printed to stdout.
_async_job $cmd &
# Store pid because zsh job manager is extremely unflexible (show jobname as non-unique '$job')...
storage[$job]="$!"
fi
processing=0 # Disable guard.
if (( do_eval )); then
do_eval=0
# When there are no active jobs we can't rely on the CHLD trap to
# manage the coproc lifetime.
close_idle_coproc
fi
done
}
#
# Get results from finnished jobs and pass it to the to callback function. This is the only way to reliably return the
# job name, return code, output and execution time and with minimal effort.
# Get results from finished jobs and pass it to the to callback function. This is the only way to reliably return the
# job name, return code, output and execution time and with minimal effort.
#
# If the async process buffer becomes corrupt, the callback will be invoked with the first argument being `[async]` (job
# name), non-zero return code and fifth argument describing the error (stderr).
#
# usage:
# async_process_results <worker_name> <callback_function>
@@ -245,13 +278,15 @@ async_process_results() {
if (( $#items == 5 )); then
items+=($has_next)
$callback "${(@)items}" # Send all parsed items to the callback.
(( num_processed++ ))
elif [[ -z $items ]]; then
# Empty items occur between results due to double-null ($'\0\0')
# caused by commands being both pre and suffixed with null.
else
# In case of corrupt data, invoke callback with *async* as job
# name, non-zero exit status and an error message on stderr.
$callback "async" 1 "" 0 "$0:$LINENO: error: bad format, got ${#items} items (${(q)items})" $has_next
$callback "[async]" 1 "" 0 "$0:$LINENO: error: bad format, got ${#items} items (${(q)items})" $has_next
fi
(( num_processed++ ))
done
done
@@ -297,6 +332,30 @@ async_job() {
zpty -w $worker "$cmd"$'\0'
}
#
# Evaluate a command (like async_job) inside the async worker, then worker environment can be manipulated. For example,
# issuing a cd command will change the PWD of the worker which will then be inherited by all future async jobs.
#
# Output will be returned via callback, job name will be [async/eval].
#
# usage:
# async_worker_eval <worker_name> <my_function> [<function_params>]
#
async_worker_eval() {
setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings
local worker=$1; shift
local -a cmd
cmd=("$@")
if (( $#cmd > 1 )); then
cmd=(${(q)cmd}) # Quote special characters in multi argument commands.
fi
# Quote the cmd in case RC_EXPAND_PARAM is set.
zpty -w $worker "_async_eval $cmd"$'\0'
}
# This function traps notification signals and calls all registered callbacks
_async_notify_trap() {
setopt localoptions noshwordsplit

View File

@@ -7,8 +7,8 @@ test__async_job_print_hi() {
local line
local -a out
line=$(_async_job print hi)
# Remove trailing null, parse, unquote and interpret as array.
line=$line[1,$#line-1]
# Remove leading/trailing null, parse, unquote and interpret as array.
line=$line[2,$#line-1]
out=("${(@Q)${(z)line}}")
coproc exit
@@ -396,8 +396,10 @@ test_async_flush_jobs() {
# TODO: Confirm that they no longer exist in the process tree.
local output
output="${(Q)$(ASYNC_DEBUG=1 async_flush_jobs test)}"
[[ $output = *'print_four 0 4'* ]] || {
t_error "want discarded output 'print_four 0 4' when ASYNC_DEBUG=1, got ${(Vq-)output}"
# NOTE(mafredri): First 'p' in print_four is lost when null-prefixing
# _async_job output.
[[ $output = *'rint_four 0 4'* ]] || {
t_error "want discarded output 'rint_four 0 4' when ASYNC_DEBUG=1, got ${(Vq-)output}"
}
# Check that the killed job did not produce output.
@@ -430,6 +432,35 @@ test_async_worker_survives_termination_of_other_worker() {
(( $#result == 6 )) || t_error "wanted a result, got (${(@Vq)result})"
}
test_async_worker_update_pwd() {
local -a result
local eval_out
cb() {
if [[ $1 == '[async/eval]' ]]; then
eval_out="$3"
else
result+=("$3")
fi
}
async_start_worker test1
t_defer async_stop_worker test1
async_job test1 'print $PWD'
async_worker_eval test1 'print -n foo; cd ..; print -n bar; print -n -u2 baz'
async_job test1 'print $PWD'
start=$EPOCHREALTIME
while (( EPOCHREALTIME - start < 2.0 && $#result < 3 )); do
async_process_results test1 cb
done
(( $#result == 2 )) || t_error "wanted 2 results, got ${#result}"
[[ $eval_out = foobarbaz ]] || t_error "wanted async_worker_eval to output foobarbaz, got ${(q)eval_out}"
[[ -n $result[2] ]] || t_error "wanted second pwd to be non-empty"
[[ $result[1] != $result[2] ]] || t_error "wanted worker to change pwd, was ${(q)result[1]}, got ${(q)result[2]}"
}
setopt_helper() {
setopt localoptions $1