Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] Add execute-command() widget function (was Re: [RFC][PATCH] Add change-directory() widget function)
- X-seq: zsh-workers 48642
- From: Marlon Richert <marlon.richert@xxxxxxxxx>
- To: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>, Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx>
- Cc: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: [PATCH] Add execute-command() widget function (was Re: [RFC][PATCH] Add change-directory() widget function)
- Date: Wed, 21 Apr 2021 14:37:28 +0300
- Archived-at: <https://zsh.org/workers/48642>
- In-reply-to: <CAH+w=7ZCzG-BGZuU-rLoZJX=3zcA74NK+TNVDP-CWF-9b-BfrA@mail.gmail.com>
- List-id: <zsh-workers.zsh.org>
- References: <95CDA630-4EE5-4003-8D9C-CCCB9A47F109@gmail.com> <CAH+w=7bpkYktd4UN5DtUS45MMNdWYr7c-OG7DHOX21QXG4LMUA@mail.gmail.com> <4D587C0C-EB5F-4A58-A0AE-D45E43F432CD@gmail.com> <CAH+w=7bQLq43JChP7PmaqT_wHMwgs4Nk_-0grrtQXEhQJcfrbA@mail.gmail.com> <CAH+w=7ZCzG-BGZuU-rLoZJX=3zcA74NK+TNVDP-CWF-9b-BfrA@mail.gmail.com>
On 21 Apr 2021, at 00:32, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> My only remark about this as-is, is that it would have potentially
> dangerous side-effects if invoked at a PS2 or PS3 prompt.
>
> Potential fixes - begin the widget function with:
> [[ ${(%):-%_} = select ]] && return 1
> [[ -n "$PREBUFFER$BUFFER" ]] && zle push-input
On 21 Apr 2021, at 06:46, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> Oh, I missed this:
>
>> On Tue, Apr 20, 2021 at 1:13 PM Marlon Richert <marlon.richert@xxxxxxxxx> wrote:
>>> @@ -0,0 +1,29 @@
>>> +zle .push-line-or-edit
>
> That's still wrong, because in the event there's a PS2 prompt, you'll
> never get past this line. You need .push-input here. My suggested
> test for $PREBUFFER is probably not actually needed.
Thank you both (Bart & Daniel) for your input. I added better safeguards against the non-PS1 cases, rewrote the function to be more generic and added comments. New patch attached.
From 83da04aba0d07112f650a98fafc3f28daf75dcd1 Mon Sep 17 00:00:00 2001
From: Marlon Richert <marlon.richert@xxxxxxxxx>
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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author