Reputation: 86087
I've got some long-running commands that can last 15 minutes or more.
Is there a way to output a dynamic "time spent" section in the output?
E.g.
$ `do something long`
10 mins 15 secs
Refreshing state...
then:
$ `do something long`
14 mins 15 secs
Refreshing state...
Output results
$ ... and we're done
Upvotes: 2
Views: 608
Reputation: 6995
zmodload -F zsh/system p:sysparams # Load the sysparams table.
zmodload -F zsh/terminfo b:echoti # Load the echoti builtin.
timed() {
local +h -i SECONDS=0
# Open an async process for the timer.
local -i timer_fd
exec {timer_fd}< <(
# Print the process id, so we can kill it later.
print $sysparams[pid]
echoti civis # Make the cursor invisible.
while true; do
print "$(( SECONDS / 60 )) mins, $(( SECONDS % 60 )) secs"
echoti cuu1 # Move the cursor up 1 line.
done
)
# Read the timer process id.
local -i timer_pid
read timer_pid <&$timer_fd
# Start another async process for the actual task.
local -i task_fd
exec {task_fd}< <(
eval "$@" # Run the task.
# Close the timer fd and kill the timer process.
exec {timer_fd}<&-
kill -KILL $timer_pid
echoti cnorm # Make the cursor normal again.
)
# Redirect the output of the async processes to the terminal. This is
# a blocking operation. Thus, we won't get past these two lines until
# both async processes end.
<&$timer_fd
<&$task_fd
exec {task_fd}<&- # We're done. Close the task fd.
}
Example usage:
% timed 'sleep 855; print Output results'
<( command )
){fd}<file
) and closing ({fd}<&-
) file descriptorsexec
builtinsysparams
tableechoti
builtinSECONDS
parameterUpvotes: 3