annotate .zfun/async @ 509:cea9a184de6c

zsh: add workaround for mcfly breaking autocd
author Augie Fackler <raf@durin42.com>
date Thu, 18 Feb 2021 11:12:42 -0500
parents 2ea29b487b06
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
1 #!/usr/bin/env zsh
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
2
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
3 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
4 # zsh-async
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
5 #
497
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
6 # version: v1.8.5
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
7 # author: Mathias Fredriksson
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
8 # url: https://github.com/mafredri/zsh-async
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
9 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
10
497
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
11 typeset -g ASYNC_VERSION=1.8.5
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
12 # Produce debug output from zsh-async when set to 1.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
13 typeset -g ASYNC_DEBUG=${ASYNC_DEBUG:-0}
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
14
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
15 # Execute commands that can manipulate the environment inside the async worker. Return output via callback.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
16 _async_eval() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
17 local ASYNC_JOB_NAME
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
18 # Rename job to _async_eval and redirect all eval output to cat running
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
19 # in _async_job. Here, stdout and stderr are not separated for
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
20 # simplicity, this could be improved in the future.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
21 {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
22 eval "$@"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
23 } &> >(ASYNC_JOB_NAME=[async/eval] _async_job 'cat')
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
24 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
25
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
26 # Wrapper for jobs executed by the async worker, gives output in parseable format with execution time
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
27 _async_job() {
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
28 # Disable xtrace as it would mangle the output.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
29 setopt localoptions noxtrace
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
30
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
31 # Store start time for job.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
32 float -F duration=$EPOCHREALTIME
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
33
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
34 # Run the command and capture both stdout (`eval`) and stderr (`cat`) in
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
35 # separate subshells. When the command is complete, we grab write lock
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
36 # (mutex token) and output everything except stderr inside the command
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
37 # block, after the command block has completed, the stdin for `cat` is
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
38 # closed, causing stderr to be appended with a $'\0' at the end to mark the
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
39 # end of output from this job.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
40 local jobname=${ASYNC_JOB_NAME:-$1} out
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
41 out="$(
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
42 local stdout stderr ret tok
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
43 {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
44 stdout=$(eval "$@")
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
45 ret=$?
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
46 duration=$(( EPOCHREALTIME - duration )) # Calculate duration.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
47
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
48 print -r -n - $'\0'${(q)jobname} $ret ${(q)stdout} $duration
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
49 } 2> >(stderr=$(cat) && print -r -n - " "${(q)stderr}$'\0')
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
50 )"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
51 if [[ $out != $'\0'*$'\0' ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
52 # Corrupted output (aborted job?), skipping.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
53 return
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
54 fi
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
55
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
56 # Grab mutex lock, stalls until token is available.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
57 read -r -k 1 -p tok || return 1
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
58
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
59 # Return output (<job_name> <return_code> <stdout> <duration> <stderr>).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
60 print -r -n - "$out"
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
61
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
62 # Unlock mutex by inserting a token.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
63 print -n -p $tok
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
64 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
65
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
66 # The background worker manages all tasks and runs them without interfering with other processes
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
67 _async_worker() {
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
68 # Reset all options to defaults inside async worker.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
69 emulate -R zsh
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
70
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
71 # Make sure monitor is unset to avoid printing the
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
72 # pids of child processes.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
73 unsetopt monitor
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
74
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
75 # Redirect stderr to `/dev/null` in case unforseen errors produced by the
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
76 # worker. For example: `fork failed: resource temporarily unavailable`.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
77 # Some older versions of zsh might also print malloc errors (know to happen
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
78 # on at least zsh 5.0.2 and 5.0.8) likely due to kill signals.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
79 exec 2>/dev/null
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
80
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
81 # When a zpty is deleted (using -d) all the zpty instances created before
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
82 # the one being deleted receive a SIGHUP, unless we catch it, the async
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
83 # worker would simply exit (stop working) even though visible in the list
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
84 # of zpty's (zpty -L). This has been fixed around the time of Zsh 5.4
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
85 # (not released).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
86 if ! is-at-least 5.4.1; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
87 TRAPHUP() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
88 return 0 # Return 0, indicating signal was handled.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
89 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
90 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
91
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
92 local -A storage
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
93 local unique=0
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
94 local notify_parent=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
95 local parent_pid=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
96 local coproc_pid=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
97 local processing=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
98
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
99 local -a zsh_hooks zsh_hook_functions
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
100 zsh_hooks=(chpwd periodic precmd preexec zshexit zshaddhistory)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
101 zsh_hook_functions=(${^zsh_hooks}_functions)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
102 unfunction $zsh_hooks &>/dev/null # Deactivate all zsh hooks inside the worker.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
103 unset $zsh_hook_functions # And hooks with registered functions.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
104 unset zsh_hooks zsh_hook_functions # Cleanup.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
105
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
106 close_idle_coproc() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
107 local -a pids
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
108 pids=(${${(v)jobstates##*:*:}%\=*})
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
109
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
110 # If coproc (cat) is the only child running, we close it to avoid
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
111 # leaving it running indefinitely and cluttering the process tree.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
112 if (( ! processing )) && [[ $#pids = 1 ]] && [[ $coproc_pid = $pids[1] ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
113 coproc :
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
114 coproc_pid=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
115 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
116 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
117
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
118 child_exit() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
119 close_idle_coproc
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
120
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
121 # On older version of zsh (pre 5.2) we notify the parent through a
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
122 # SIGWINCH signal because `zpty` did not return a file descriptor (fd)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
123 # prior to that.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
124 if (( notify_parent )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
125 # We use SIGWINCH for compatibility with older versions of zsh
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
126 # (pre 5.1.1) where other signals (INFO, ALRM, USR1, etc.) could
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
127 # cause a deadlock in the shell under certain circumstances.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
128 kill -WINCH $parent_pid
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
129 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
130 }
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
131
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
132 # Register a SIGCHLD trap to handle the completion of child processes.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
133 trap child_exit CHLD
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
134
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
135 # Process option parameters passed to worker.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
136 while getopts "np:uz" opt; do
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
137 case $opt in
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
138 n) notify_parent=1;;
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
139 p) parent_pid=$OPTARG;;
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
140 u) unique=1;;
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
141 z) notify_parent=0;; # Uses ZLE watcher instead.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
142 esac
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
143 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
144
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
145 # Terminate all running jobs, note that this function does not
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
146 # reinstall the child trap.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
147 terminate_jobs() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
148 trap - CHLD # Ignore child exits during kill.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
149 coproc : # Quit coproc.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
150 coproc_pid=0 # Reset pid.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
151
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
152 if is-at-least 5.4.1; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
153 trap '' HUP # Catch the HUP sent to this process.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
154 kill -HUP -$$ # Send to entire process group.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
155 trap - HUP # Disable HUP trap.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
156 else
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
157 # We already handle HUP for Zsh < 5.4.1.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
158 kill -HUP -$$ # Send to entire process group.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
159 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
160 }
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
161
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
162 killjobs() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
163 local tok
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
164 local -a pids
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
165 pids=(${${(v)jobstates##*:*:}%\=*})
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
166
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
167 # No need to send SIGHUP if no jobs are running.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
168 (( $#pids == 0 )) && continue
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
169 (( $#pids == 1 )) && [[ $coproc_pid = $pids[1] ]] && continue
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
170
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
171 # Grab lock to prevent half-written output in case a child
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
172 # process is in the middle of writing to stdin during kill.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
173 (( coproc_pid )) && read -r -k 1 -p tok
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
174
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
175 terminate_jobs
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
176 trap child_exit CHLD # Reinstall child trap.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
177 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
178
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
179 local request do_eval=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
180 local -a cmd
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
181 while :; do
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
182 # Wait for jobs sent by async_job.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
183 read -r -d $'\0' request || {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
184 # Unknown error occurred while reading from stdin, the zpty
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
185 # worker is likely in a broken state, so we shut down.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
186 terminate_jobs
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
187
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
188 # Stdin is broken and in case this was an unintended
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
189 # crash, we try to report it as a last hurrah.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
190 print -r -n $'\0'"'[async]'" $(( 127 + 3 )) "''" 0 "'$0:$LINENO: zpty fd died, exiting'"$'\0'
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
191
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
192 # We use `return` to abort here because using `exit` may
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
193 # result in an infinite loop that never exits and, as a
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
194 # result, high CPU utilization.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
195 return $(( 127 + 1 ))
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
196 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
197
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
198 # We need to clean the input here because sometimes when a zpty
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
199 # has died and been respawned, messages will be prefixed with a
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
200 # carraige return (\r, or \C-M).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
201 request=${request#$'\C-M'}
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
202
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
203 # Check for non-job commands sent to worker
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
204 case $request in
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
205 _killjobs) killjobs; continue;;
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
206 _async_eval*) do_eval=1;;
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
207 esac
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
208
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
209 # Parse the request using shell parsing (z) to allow commands
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
210 # to be parsed from single strings and multi-args alike.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
211 cmd=("${(z)request}")
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
212
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
213 # Name of the job (first argument).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
214 local job=$cmd[1]
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
215
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
216 # Check if a worker should perform unique jobs, unless
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
217 # this is an eval since they run synchronously.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
218 if (( !do_eval )) && (( unique )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
219 # Check if a previous job is still running, if yes,
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
220 # skip this job and let the previous one finish.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
221 for pid in ${${(v)jobstates##*:*:}%\=*}; do
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
222 if [[ ${storage[$job]} == $pid ]]; then
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
223 continue 2
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
224 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
225 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
226 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
227
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
228 # Guard against closing coproc from trap before command has started.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
229 processing=1
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
230
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
231 # Because we close the coproc after the last job has completed, we must
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
232 # recreate it when there are no other jobs running.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
233 if (( ! coproc_pid )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
234 # Use coproc as a mutex for synchronized output between children.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
235 coproc cat
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
236 coproc_pid="$!"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
237 # Insert token into coproc
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
238 print -n -p "t"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
239 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
240
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
241 if (( do_eval )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
242 shift cmd # Strip _async_eval from cmd.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
243 _async_eval $cmd
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
244 else
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
245 # Run job in background, completed jobs are printed to stdout.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
246 _async_job $cmd &
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
247 # Store pid because zsh job manager is extremely unflexible (show jobname as non-unique '$job')...
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
248 storage[$job]="$!"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
249 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
250
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
251 processing=0 # Disable guard.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
252
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
253 if (( do_eval )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
254 do_eval=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
255
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
256 # When there are no active jobs we can't rely on the CHLD trap to
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
257 # manage the coproc lifetime.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
258 close_idle_coproc
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
259 fi
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
260 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
261 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
262
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
263 #
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
264 # Get results from finished jobs and pass it to the to callback function. This is the only way to reliably return the
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
265 # job name, return code, output and execution time and with minimal effort.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
266 #
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
267 # If the async process buffer becomes corrupt, the callback will be invoked with the first argument being `[async]` (job
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
268 # name), non-zero return code and fifth argument describing the error (stderr).
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
269 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
270 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
271 # async_process_results <worker_name> <callback_function>
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
272 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
273 # callback_function is called with the following parameters:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
274 # $1 = job name, e.g. the function passed to async_job
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
275 # $2 = return code
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
276 # $3 = resulting stdout from execution
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
277 # $4 = execution time, floating point e.g. 2.05 seconds
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
278 # $5 = resulting stderr from execution
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
279 # $6 = has next result in buffer (0 = buffer empty, 1 = yes)
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
280 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
281 async_process_results() {
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
282 setopt localoptions unset noshwordsplit noksharrays noposixidentifiers noposixstrings
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
283
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
284 local worker=$1
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
285 local callback=$2
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
286 local caller=$3
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
287 local -a items
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
288 local null=$'\0' data
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
289 integer -l len pos num_processed has_next
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
290
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
291 typeset -gA ASYNC_PROCESS_BUFFER
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
292
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
293 # Read output from zpty and parse it if available.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
294 while zpty -r -t $worker data 2>/dev/null; do
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
295 ASYNC_PROCESS_BUFFER[$worker]+=$data
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
296 len=${#ASYNC_PROCESS_BUFFER[$worker]}
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
297 pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
298
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
299 # Keep going until we find a NULL-character.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
300 if (( ! len )) || (( pos > len )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
301 continue
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
302 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
303
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
304 while (( pos <= len )); do
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
305 # Take the content from the beginning, until the NULL-character and
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
306 # perform shell parsing (z) and unquoting (Q) as an array (@).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
307 items=("${(@Q)${(z)ASYNC_PROCESS_BUFFER[$worker][1,$pos-1]}}")
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
308
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
309 # Remove the extracted items from the buffer.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
310 ASYNC_PROCESS_BUFFER[$worker]=${ASYNC_PROCESS_BUFFER[$worker][$pos+1,$len]}
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
311
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
312 len=${#ASYNC_PROCESS_BUFFER[$worker]}
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
313 if (( len > 1 )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
314 pos=${ASYNC_PROCESS_BUFFER[$worker][(i)$null]} # Get index of NULL-character (delimiter).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
315 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
316
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
317 has_next=$(( len != 0 ))
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
318 if (( $#items == 5 )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
319 items+=($has_next)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
320 $callback "${(@)items}" # Send all parsed items to the callback.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
321 (( num_processed++ ))
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
322 elif [[ -z $items ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
323 # Empty items occur between results due to double-null ($'\0\0')
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
324 # caused by commands being both pre and suffixed with null.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
325 else
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
326 # In case of corrupt data, invoke callback with *async* as job
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
327 # name, non-zero exit status and an error message on stderr.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
328 $callback "[async]" 1 "" 0 "$0:$LINENO: error: bad format, got ${#items} items (${(q)items})" $has_next
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
329 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
330 done
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
331 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
332
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
333 (( num_processed )) && return 0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
334
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
335 # Avoid printing exit value when `setopt printexitvalue` is active.`
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
336 [[ $caller = trap || $caller = watcher ]] && return 0
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
337
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
338 # No results were processed
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
339 return 1
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
340 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
341
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
342 # Watch worker for output
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
343 _async_zle_watcher() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
344 setopt localoptions noshwordsplit
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
345 typeset -gA ASYNC_PTYS ASYNC_CALLBACKS
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
346 local worker=$ASYNC_PTYS[$1]
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
347 local callback=$ASYNC_CALLBACKS[$worker]
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
348
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
349 if [[ -n $2 ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
350 # from man zshzle(1):
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
351 # `hup' for a disconnect, `nval' for a closed or otherwise
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
352 # invalid descriptor, or `err' for any other condition.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
353 # Systems that support only the `select' system call always use
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
354 # `err'.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
355
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
356 # this has the side effect to unregister the broken file descriptor
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
357 async_stop_worker $worker
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
358
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
359 if [[ -n $callback ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
360 $callback '[async]' 2 "" 0 "$0:$LINENO: error: fd for $worker failed: zle -F $1 returned error $2" 0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
361 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
362 return
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
363 fi;
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
364
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
365 if [[ -n $callback ]]; then
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
366 async_process_results $worker $callback watcher
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
367 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
368 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
369
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
370 _async_send_job() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
371 setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
372
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
373 local caller=$1
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
374 local worker=$2
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
375 shift 2
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
376
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
377 zpty -t $worker &>/dev/null || {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
378 typeset -gA ASYNC_CALLBACKS
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
379 local callback=$ASYNC_CALLBACKS[$worker]
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
380
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
381 if [[ -n $callback ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
382 $callback '[async]' 3 "" 0 "$0:$LINENO: error: no such worker: $worker" 0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
383 else
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
384 print -u2 "$caller: no such async worker: $worker"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
385 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
386 return 1
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
387 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
388
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
389 zpty -w $worker "$@"$'\0'
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
390 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
391
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
392 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
393 # Start a new asynchronous job on specified worker, assumes the worker is running.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
394 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
395 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
396 # async_job <worker_name> <my_function> [<function_params>]
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
397 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
398 async_job() {
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
399 setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
400
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
401 local worker=$1; shift
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
402
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
403 local -a cmd
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
404 cmd=("$@")
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
405 if (( $#cmd > 1 )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
406 cmd=(${(q)cmd}) # Quote special characters in multi argument commands.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
407 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
408
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
409 _async_send_job $0 $worker "$cmd"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
410 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
411
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
412 #
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
413 # Evaluate a command (like async_job) inside the async worker, then worker environment can be manipulated. For example,
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
414 # issuing a cd command will change the PWD of the worker which will then be inherited by all future async jobs.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
415 #
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
416 # Output will be returned via callback, job name will be [async/eval].
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
417 #
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
418 # usage:
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
419 # async_worker_eval <worker_name> <my_function> [<function_params>]
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
420 #
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
421 async_worker_eval() {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
422 setopt localoptions noshwordsplit noksharrays noposixidentifiers noposixstrings
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
423
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
424 local worker=$1; shift
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
425
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
426 local -a cmd
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
427 cmd=("$@")
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
428 if (( $#cmd > 1 )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
429 cmd=(${(q)cmd}) # Quote special characters in multi argument commands.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
430 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
431
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
432 # Quote the cmd in case RC_EXPAND_PARAM is set.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
433 _async_send_job $0 $worker "_async_eval $cmd"
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
434 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
435
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
436 # This function traps notification signals and calls all registered callbacks
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
437 _async_notify_trap() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
438 setopt localoptions noshwordsplit
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
439
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
440 local k
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
441 for k in ${(k)ASYNC_CALLBACKS}; do
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
442 async_process_results $k ${ASYNC_CALLBACKS[$k]} trap
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
443 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
444 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
445
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
446 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
447 # Register a callback for completed jobs. As soon as a job is finnished, async_process_results will be called with the
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
448 # specified callback function. This requires that a worker is initialized with the -n (notify) option.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
449 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
450 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
451 # async_register_callback <worker_name> <callback_function>
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
452 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
453 async_register_callback() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
454 setopt localoptions noshwordsplit nolocaltraps
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
455
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
456 typeset -gA ASYNC_PTYS ASYNC_CALLBACKS
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
457 local worker=$1; shift
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
458
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
459 ASYNC_CALLBACKS[$worker]="$*"
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
460
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
461 # Enable trap when the ZLE watcher is unavailable, allows
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
462 # workers to notify (via -n) when a job is done.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
463 if [[ ! -o interactive ]] || [[ ! -o zle ]]; then
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
464 trap '_async_notify_trap' WINCH
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
465 elif [[ -o interactive ]] && [[ -o zle ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
466 local fd w
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
467 for fd w in ${(@kv)ASYNC_PTYS}; do
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
468 if [[ $w == $worker ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
469 zle -F $fd _async_zle_watcher # Register the ZLE handler.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
470 break
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
471 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
472 done
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
473 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
474 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
475
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
476 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
477 # Unregister the callback for a specific worker.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
478 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
479 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
480 # async_unregister_callback <worker_name>
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
481 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
482 async_unregister_callback() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
483 typeset -gA ASYNC_CALLBACKS
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
484
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
485 unset "ASYNC_CALLBACKS[$1]"
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
486 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
487
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
488 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
489 # Flush all current jobs running on a worker. This will terminate any and all running processes under the worker, use
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
490 # with caution.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
491 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
492 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
493 # async_flush_jobs <worker_name>
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
494 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
495 async_flush_jobs() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
496 setopt localoptions noshwordsplit
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
497
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
498 local worker=$1; shift
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
499
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
500 # Check if the worker exists
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
501 zpty -t $worker &>/dev/null || return 1
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
502
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
503 # Send kill command to worker
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
504 async_job $worker "_killjobs"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
505
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
506 # Clear the zpty buffer.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
507 local junk
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
508 if zpty -r -t $worker junk '*'; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
509 (( ASYNC_DEBUG )) && print -n "async_flush_jobs $worker: ${(V)junk}"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
510 while zpty -r -t $worker junk '*'; do
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
511 (( ASYNC_DEBUG )) && print -n "${(V)junk}"
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
512 done
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
513 (( ASYNC_DEBUG )) && print
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
514 fi
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
515
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
516 # Finally, clear the process buffer in case of partially parsed responses.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
517 typeset -gA ASYNC_PROCESS_BUFFER
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
518 unset "ASYNC_PROCESS_BUFFER[$worker]"
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
519 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
520
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
521 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
522 # Start a new async worker with optional parameters, a worker can be told to only run unique tasks and to notify a
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
523 # process when tasks are complete.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
524 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
525 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
526 # async_start_worker <worker_name> [-u] [-n] [-p <pid>]
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
527 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
528 # opts:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
529 # -u unique (only unique job names can run)
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
530 # -n notify through SIGWINCH signal
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
531 # -p pid to notify (defaults to current pid)
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
532 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
533 async_start_worker() {
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
534 setopt localoptions noshwordsplit noclobber
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
535
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
536 local worker=$1; shift
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
537 local -a args
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
538 args=("$@")
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
539 zpty -t $worker &>/dev/null && return
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
540
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
541 typeset -gA ASYNC_PTYS
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
542 typeset -h REPLY
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
543 typeset has_xtrace=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
544
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
545 if [[ -o interactive ]] && [[ -o zle ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
546 # Inform the worker to ignore the notify flag and that we're
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
547 # using a ZLE watcher instead.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
548 args+=(-z)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
549
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
550 if (( ! ASYNC_ZPTY_RETURNS_FD )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
551 # When zpty doesn't return a file descriptor (on older versions of zsh)
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
552 # we try to guess it anyway.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
553 integer -l zptyfd
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
554 exec {zptyfd}>&1 # Open a new file descriptor (above 10).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
555 exec {zptyfd}>&- # Close it so it's free to be used by zpty.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
556 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
557 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
558
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
559 # Workaround for stderr in the main shell sometimes (incorrectly) being
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
560 # reassigned to /dev/null by the reassignment done inside the async
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
561 # worker.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
562 # See https://github.com/mafredri/zsh-async/issues/35.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
563 integer errfd=-1
497
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
564
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
565 # Redirect of errfd is broken on zsh 5.0.2.
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
566 if is-at-least 5.0.8; then
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
567 exec {errfd}>&2
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
568 fi
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
569
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
570 # Make sure async worker is started without xtrace
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
571 # (the trace output interferes with the worker).
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
572 [[ -o xtrace ]] && {
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
573 has_xtrace=1
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
574 unsetopt xtrace
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
575 }
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
576
497
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
577 if (( errfd != -1 )); then
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
578 zpty -b $worker _async_worker -p $$ $args 2>&$errfd
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
579 else
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
580 zpty -b $worker _async_worker -p $$ $args
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
581 fi
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
582 local ret=$?
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
583
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
584 # Re-enable it if it was enabled, for debugging.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
585 (( has_xtrace )) && setopt xtrace
497
2ea29b487b06 zsh: update async to 1.8.5
Augie Fackler <raf@durin42.com>
parents: 495
diff changeset
586 (( errfd != -1 )) && exec {errfd}>& -
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
587
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
588 if (( ret )); then
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
589 async_stop_worker $worker
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
590 return 1
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
591 fi
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
592
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
593 if ! is-at-least 5.0.8; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
594 # For ZSH versions older than 5.0.8 we delay a bit to give
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
595 # time for the worker to start before issuing commands,
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
596 # otherwise it will not be ready to receive them.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
597 sleep 0.001
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
598 fi
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
599
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
600 if [[ -o interactive ]] && [[ -o zle ]]; then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
601 if (( ! ASYNC_ZPTY_RETURNS_FD )); then
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
602 REPLY=$zptyfd # Use the guessed value for the file desciptor.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
603 fi
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
604
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
605 ASYNC_PTYS[$REPLY]=$worker # Map the file desciptor to the worker.
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
606 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
607 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
608
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
609 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
610 # Stop one or multiple workers that are running, all unfetched and incomplete work will be lost.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
611 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
612 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
613 # async_stop_worker <worker_name_1> [<worker_name_2>]
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
614 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
615 async_stop_worker() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
616 setopt localoptions noshwordsplit
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
617
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
618 local ret=0 worker k v
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
619 for worker in $@; do
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
620 # Find and unregister the zle handler for the worker
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
621 for k v in ${(@kv)ASYNC_PTYS}; do
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
622 if [[ $v == $worker ]]; then
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
623 zle -F $k
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
624 unset "ASYNC_PTYS[$k]"
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
625 fi
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
626 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
627 async_unregister_callback $worker
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
628 zpty -d $worker 2>/dev/null || ret=$?
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
629
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
630 # Clear any partial buffers.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
631 typeset -gA ASYNC_PROCESS_BUFFER
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
632 unset "ASYNC_PROCESS_BUFFER[$worker]"
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
633 done
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
634
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
635 return $ret
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
636 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
637
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
638 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
639 # Initialize the required modules for zsh-async. To be called before using the zsh-async library.
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
640 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
641 # usage:
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
642 # async_init
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
643 #
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
644 async_init() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
645 (( ASYNC_INIT_DONE )) && return
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
646 typeset -g ASYNC_INIT_DONE=1
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
647
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
648 zmodload zsh/zpty
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
649 zmodload zsh/datetime
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
650
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
651 # Load is-at-least for reliable version check.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
652 autoload -Uz is-at-least
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
653
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
654 # Check if zsh/zpty returns a file descriptor or not,
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
655 # shell must also be interactive with zle enabled.
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
656 typeset -g ASYNC_ZPTY_RETURNS_FD=0
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
657 [[ -o interactive ]] && [[ -o zle ]] && {
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
658 typeset -h REPLY
495
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
659 zpty _async_test :
d3d52766cfcd zsh: update async to 1.8.4
Augie Fackler <raf@durin42.com>
parents: 381
diff changeset
660 (( REPLY )) && ASYNC_ZPTY_RETURNS_FD=1
381
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
661 zpty -d _async_test
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
662 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
663 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
664
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
665 async() {
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
666 async_init
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
667 }
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
668
e84b6da69ea0 async.zsh: import
Augie Fackler <raf@durin42.com>
parents:
diff changeset
669 async "$@"