From 0cffb0a6b3602a00cebe2bbb7537d76727892959 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 18 Jun 2020 11:42:19 +0000 Subject: 46072 + 46136: Add the 'zle $widget -f nolast' syntax, to improve add-zle-hook-widget support for multiple hook functions. See workers/46004 for the use-case. --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/zle.yo | 7 +++++-- Functions/Misc/add-zle-hook-widget | 4 ++-- Src/Zle/zle_thingy.c | 19 +++++++++++++++++-- Test/X04zlehighlight.ztst | 11 +++++++++++ 6 files changed, 42 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc1963af2..0d3a50cd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2020-06-27 Daniel Shahaf + * 46072 + 46136: Doc/Zsh/contrib.yo, Doc/Zsh/zle.yo, + Functions/Misc/add-zle-hook-widget, Src/Zle/zle_thingy.c, + Test/X04zlehighlight.ztst: Add the 'zle $widget -f nolast' + syntax, to improve add-zle-hook-widget support for multiple + hook functions. + * users/24959/0002: Doc/Zsh/grammar.yo: Update aliases documentation for the addition of the ALIAS_FUNC_DEF option. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index c611ff43b..7cde0033f 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -347,7 +347,7 @@ as the var(hook) argument. var(widgetname) is the name of a ZLE widget. If no options are given this is added to the array of widgets to be invoked in the given hook context. Widgets are invoked in the order they were added, with -example(tt(zle )var(widgetname)tt( -Nw -- "$@")) +example(tt(zle )var(widgetname)tt( -Nw -f "nolast" -- "$@")) vindex(WIDGET, in hooks) Note that this means that the `tt(WIDGET)' special parameter tracks the diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 909abeb49..84be010e1 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -415,7 +415,7 @@ xitem(tt(zle) tt(-K) var(keymap)) xitem(tt(zle) tt(-F) [ tt(-L) | tt(-w) ] [ var(fd) [ var(handler) ] ]) xitem(tt(zle) tt(-I)) xitem(tt(zle) tt(-T) [ tt(tc) var(function) | tt(-r) tt(tc) | tt(-L) ] ) -item(tt(zle) var(widget) [ tt(-n) var(num) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( +item(tt(zle) var(widget) [ tt(-n) var(num) ] [ tt(-f) var(flag) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( The tt(zle) builtin performs a number of different actions concerning ZLE. @@ -683,7 +683,7 @@ optional argument for debugging or testing. Note that this transformation is not applied to other non-printing characters such as carriage returns and newlines. ) -item(var(widget) [ tt(-n) var(num) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( +item(var(widget) [ tt(-n) var(num) ] [ tt(-f) var(flag) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( Invoke the specified var(widget). This can only be done when ZLE is active; normally this will be within a user-defined widget. @@ -702,6 +702,9 @@ appears as if the top-level widget called by the user were still active. With the option tt(-w), tt(WIDGET) and related parameters are set to reflect the widget being executed by the tt(zle) call. +Normally, when var(widget) returns the special parameter tt(LASTWIDGET) will +point to it. This can be inhibited by passing the option tt(-f nolast). + Any further arguments will be passed to the widget; note that as standard argument handling is performed, any general argument list should be preceded by tt(-)tt(-). If it is a shell diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 9cc35496f..4d8049083 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -47,9 +47,9 @@ function azhw:${^hooktypes} { for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do if [[ "$hook" = user:* ]]; then # Preserve $WIDGET within the renamed widget - zle "$hook" -N -- "$@" + zle "$hook" -f "nolast" -N -- "$@" else - zle "$hook" -Nw -- "$@" + zle "$hook" -f "nolast" -Nw -- "$@" fi || return done return 0 diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index ce61db27b..cd3f2c356 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -678,6 +678,7 @@ bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) else if (!strcmp(*flag, "keepsuffix")) w->flags |= ZLE_KEEPSUFFIX; */ + /* If you add magic strings here, be consistent with bin_zle_call() */ else if (!strcmp(*flag, "vichange")) { if (invicmdmode()) { startvichange(-1); @@ -703,7 +704,7 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { Thingy t; struct modifier modsave = zmod; - int ret, saveflag = 0, setbindk = 0, setlbindk, remetafy; + int ret, saveflag = 0, setbindk = 0, setlbindk = 0, remetafy; char *wname = *args++, *keymap_restore = NULL, *keymap_tmp; if (!wname) @@ -727,12 +728,26 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) while (*args && **args == '-') { char skip_this_arg[2] = "x"; char *num; + char *flag; if (!args[0][1] || args[0][1] == '-') { args++; break; } while (*++(*args)) { switch (**args) { + case 'f': + flag = args[0][1] ? args[0]+1 : args[1]; + if (flag == NULL || strcmp(flag, "nolast")) { + zwarnnam(name, "%s", "'nolast' expected after -f"); + if (remetafy) + metafy_line(); + return 1; + } + if (!args[0][1]) + *++args = skip_this_arg; + /* If you add magic strings here, be consistent with bin_zle_flags() */ + setlbindk = 1; + break; case 'n': num = args[0][1] ? args[0]+1 : args[1]; if (!num) { @@ -787,7 +802,7 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) * a vi range to detect a repeated key */ setbindk = setbindk || (t->widget && (t->widget->flags & (WIDGET_INT | ZLE_VIOPER)) == WIDGET_INT); - setlbindk = t->widget && (t->widget->flags & ZLE_NOLAST) == ZLE_NOLAST; + setlbindk |= t->widget && (t->widget->flags & ZLE_NOLAST) == ZLE_NOLAST; ret = execzlefunc(t, args, setbindk, setlbindk); unrefthingy(t); if (saveflag) diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst index 7ab050bee..ea1d64fe1 100644 --- a/Test/X04zlehighlight.ztst +++ b/Test/X04zlehighlight.ztst @@ -198,6 +198,17 @@ 0:overlapping region_highlight with near-color (hex-triplets at input) >0m27m24mCDE|340|tCDE|3160|rCDE|39|CDE|340|ueCDE|39| + zpty_start + zpty_input 'f () { zle clear-screen; zle g -f nolast; BUFFER=": ${(q)LASTWIDGET}" }; zle -N f' + zpty_input 'g () { }; zle -N g' + zpty_input 'bindkey "\C-a" f' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line 1 p + zpty_stop +0:zle $widgetname -f nolast +>0m27m24m0m27m24m: clear-screen + %clean zmodload -ui zsh/zpty -- cgit 1.4.1