# Lets you implement widgets that can execute arbitrary commands without losing # the current command line, in a fashion similar to 'run-help' and # 'which-command' widgets. See the manual for examples. zmodload -F zsh/zutil b:zparseopts autoload -Uz add-zle-hook-widget case $CONTEXT in ( start ) # PS1 ;; ( cont ) # PS2 # Add a one-time hook that will re-run this widget at the top-level prompt. local hook=line-init local func=${(q):-:${(%):-%N}:$hook:$WIDGET} eval "$func() { # Make sure we don't run twice. add-zle-hook-widget -d $hook $func # Don't leave anything behind. zle -D $func unfunction $func # Use -w to ensure \$WIDGET is set to our original widget, not the hook. # This doesn't matter at present, but might matter in future or if this # code gets copy-pasted elsewhere. zle ${(q)WIDGET} -w }" add-zle-hook-widget $hook ${(Q)func} # Move the entire current multiline construct into the editor buffer. This # function is then aborted and we return to the top-level prompt, which # triggers the hook above. # We don't use .push-input here, because that would result in a blank # buffer afterwards. zle .push-line-or-edit return # Command flow never actually gets here. See above. ;; ( * ) # We don't want this to be used in a select loop or in vared: # * At a select prompt, the command wouldn't be "executed"; it'd be fed to # select as the value of the selection. # * In vared, it would replace the contents of the variable with the # command string and then exit vared. return 75 # EX_TEMPFAIL; see `man 3 sysexits`. ;; esac # Push the current buffer onto the buffer stack and clear the buffer. The ZLE # will auto-restore it at the next top-level prompt. zle .push-line zparseopts -D - # Remove - or -- argument. BUFFER="$1" zle .accept-line