From 83da04aba0d07112f650a98fafc3f28daf75dcd1 Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Wed, 21 Apr 2021 14:33:27 +0300 Subject: [PATCH] Add execute-command() widget function --- Doc/Zsh/contrib.yo | 26 +++++++++++++++++ Functions/Zle/execute-command | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 Functions/Zle/execute-command diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 8bf1a208e..df02fc4d9 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2502,6 +2502,32 @@ arguments: example(zstyle :zle:edit-command-line editor gvim -f) ) +tindex(execute-command) +item(tt(execute-command))( +This function lets you implement widgets that can execute arbitrary commands +without losing the current command line, in a fashion similar to the +tt(run-help) and tt(which-command) widgets (see +ifzman(the subsection Miscellaneous in zmanref(zshzle))\ +ifnzman(noderef(Miscellaneous))). More precisely, it +enumeration( +myeit() pushes the buffer onto the buffer stack, +myeit() executes the supplied arguments, then +myeit() lets the ZLE pop the buffer off the top of the buffer stack and load + it into the editing buffer. +) + +You can use this, for example, to create key bindings that let you instantly +change directories, even while in the middle of typing another command: + +example(autoload -Uz execute-command +setopt autopushd pushdminus pushdsilent +zle -N cd-upward ; cd-upward() { execute-command cd .. } +zle -N cd-backward; cd-backward() { execute-command pushd -1 } +zle -N cd-forward ; cd-forward() { execute-command pushd +0 } +bindkey '^[^[[A' cd-upward; bindkey '^[^[OA' cd-upward +bindkey '^[-' cd-backward +bindkey '^[=' cd-forward) +) tindex(expand-absolute-path) item(tt(expand-absolute-path))( Expand the file name under the cursor to an absolute path, resolving diff --git a/Functions/Zle/execute-command b/Functions/Zle/execute-command new file mode 100644 index 000000000..04fccf176 --- /dev/null +++ b/Functions/Zle/execute-command @@ -0,0 +1,54 @@ +# This function lets you implement widgets that can execute arbitrary commands +# without losing the current command line, in a fashion similar to the +# 'run-help' and 'which-command' widgets. You can use this, for example, to +# create key bindings that let you instantly change directories, even while in +# the middle of typing another command: +# +# autoload -Uz execute-command +# setopt autopushd pushdminus pushdsilent +# zle -N cd-upward ; cd-upward() { execute-command cd .. } +# zle -N cd-backward; cd-backward() { execute-command pushd -1 } +# zle -N cd-forward ; cd-forward() { execute-command pushd +0 } +# bindkey '^[^[[A' cd-upward; bindkey '^[^[OA' cd-upward +# bindkey '^[-' cd-backward +# bindkey '^[=' cd-forward +# + +case $CONTEXT in + ( start ) # PS1 + ;; + ( cont ) # PS2 + # Add a one-time hook that will re-run this widget at the top-level prompt. + autoload -Uz add-zle-hook-widget + local hook=line-init + local func=:$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 + + zle $WIDGET + }" + add-zle-hook-widget $hook $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. + zle .push-line-or-edit + return # Not actually necessary, but for clarity's sake + ;; + ( * ) + # We don't want this to be used in a select loop or in vared. + return 1 + ;; +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 + +BUFFER="$*" +zle .accept-line -- 2.31.1