From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25034 invoked by alias); 1 Sep 2015 06:12:16 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 36358 Received: (qmail 2149 invoked from network); 1 Sep 2015 06:12:14 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; bh=2wphLOrtM2hgskFN+nK9to9MNaxpv1PvSuT96Jw0Vq4=; b=LE9StRRP2CgE55qDqFVjEJpt5oY04gOl/ZZvmeJ4ppKLhquPY9W1e1GuLmDWpBDsjY PmFk/HgmPRmEVmyIRJ9PGNzliuWBoaz76VbclMXLaRmWuyQNgYIN9HHiiTCmrmfhCE1S ER04dpvXMYIlQQp6IlbL6a8d60eY/fiZaq8pW5ML3Ch31imaF+lG0RNKpCXW7LuW07MQ dQgLc+EkhDieIg3VBsqast3OGyUeSvl84i/lHBFo4GiZy5K/sH3gny+urD8aphA8CfWT LMYB9EAAlritIoJznWRZFEVZl19NaHiLUDx8fW9jyfoEgsmZKKeTNe2VKZRNe3VC2Mhk AlVA== X-Received: by 10.194.122.97 with SMTP id lr1mr31334186wjb.26.1441087931779; Mon, 31 Aug 2015 23:12:11 -0700 (PDT) From: Mikael Magnusson To: zsh-workers@zsh.org Subject: PATCH v2 (complete): Implement zle -P Date: Tue, 1 Sep 2015 08:07:44 +0200 Message-Id: <1441087664-9081-1-git-send-email-mikachu@gmail.com> X-Mailer: git-send-email 2.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- On Fri, Dec 31, 2010 at 9:28 AM, Bart Schaefer wrote: > On Dec 30, 1:59pm, Wayne Davison wrote: > } > } I've coded up a patch that adds the -y option to zle so that I can define a > } "zle -Ny yank" widget (as well as yank-pop), which marks it as being a > } ZLE_YANK equivalent. > > This sort of follows from "zle -C". For completion widgets, it was > recognized that there are a set of behaviors which are the model for > any newly-added widget, and the builtin completion widgets provide > names for those behaviors. > > Perhaps a general solution would be that for *any* widget, not just > a completion one, it should be possible to name a "prototype" widget > whose behavior the new widget is intended to simulate or replace. > "zle -P WIDGET PROTOTYPE-WIDGET [FUNCTION]" where "zle -N ..." becomes > a special case equivalent to "zle -P WIDGET self-insert FUNCTION", > or something to that effect (or maybe undefined-key instead). > > Then one could write, e.g., > > zle -P history-search-sideways history-incremental-search-forward > > and zle would "know" to invoke the minibuffer and re-call the function > as each new keystroke is typed, without that needing to be coded as a > loop in the widget itself. > > Then the question would be whether we still need "zle -C ..." other > than for backward compatibility. > > The only other solution to this that I've thought of would be to follow > the example of the auto-suffix-remove and auto-suffix-retain widgets, > that is, have a special widget whose only effect is to have the side- > effect of enabling yank-pop on the next interaction: yank-pop-enable > perhaps (is yank-pop-disable ever needed?). Here's a more complete patch for this. sorry about sending a bunch of incremental patches, I seem to tend to do that. On Mon, Aug 31, 2015 at 7:11 PM, Peter Stephenson wrote: > It's not entirely clear what this does without documentation, but as the > flags are a bit obcsure anyway, it might not be all that clear how to > document it, either. Indeed, I'm not sure if a user can figure out which widgets are useful to override in this way. Would it be more useful to just do what Wayne did originally and let zle -N take some flags that specify which specific flags the new widget should have after all? The advantage of this method is that if we add more flags, users can wrap those widgets without us remembering to add a new zle -N flag as well. I replaced all of my zle -C with zle -P and my custom completion widgets work the same, so that's a good sign at least. The following are the usecases from the other mails to centralize. I can now do this (which is why I originally found this old thread, if anyone was curious): function _start_paste() { local content local a b local oldcutbuf="$CUTBUFFER" # I haven't quite decided how I want to control quoting yet. [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; a=$? (( $+NUMERIC )) || [[ $KEYS = $'\e\e'* ]]; b=$? zle .$WIDGET -N content if [[ $a -ne $b ]]; then CUTBUFFER=${(q-)content}' ' else CUTBUFFER=$content fi zle .yank CUTBUFFER="$oldcutbuf" } zle -P bracketed-paste bracketed-paste _start_paste And my pastes are appropriately highlit. (Wouldn't it really be more useful to have the middle argument optional? I see how it might be confusing if you're used to the zle -N behavior though.) % zle -P myyank yank myyank % myyank () { zle -M hello local oldbuf=$CUTBUFFER CUTBUFFER=${(U)CUTBUFFER zle .yank CUTBUFFER=$oldbuf } # put asdfdδ in the cutbuffer here # press yank and myyank alternatingly % asdfdδASDFDΔASDFDΔASDFDΔasdfdδasdfdδasdfdδASDFDΔASDFDΔASDFDΔ # each word gets highlighted appropriately in both cases Src/Zle/zle_main.c | 5 +++-- Src/Zle/zle_thingy.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index e610ae1..6df7367 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1396,7 +1396,8 @@ execzlefunc(Thingy func, char **args, int set_bindk) opts[XTRACE] = oxt; sfcontext = osc; endparamscope(); - lastcmd = 0; + if (!(w->flags & ZLE_NOTCOMMAND)) + lastcmd = w->flags; r = 1; redup(osi, 0); } @@ -1975,7 +1976,7 @@ zle_main_entry(int cmd, va_list ap) static struct builtin bintab[] = { BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL), BUILTIN("vared", 0, bin_vared, 1, 1, 0, "aAcef:hi:M:m:p:r:t:", NULL), - BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNrRTUw", NULL), + BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNPrRTUw", NULL), }; /* The order of the entries in this table has to match the *HOOK diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 7fd3a59..20a1de9 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -347,6 +347,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func)) { 'A', bin_zle_link, 2, 2 }, { 'N', bin_zle_new, 1, 2 }, { 'C', bin_zle_complete, 3, 3 }, + { 'P', bin_zle_prototype, 2, 3}, { 'R', bin_zle_refresh, 0, -1 }, { 'M', bin_zle_mesg, 1, 1 }, { 'U', bin_zle_unget, 1, 1 }, @@ -591,6 +592,50 @@ bin_zle_new(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) /**/ static int +bin_zle_prototype(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) +{ + Thingy t; + Widget w, pw; + char *funcname = args[2] ? args[2] : args[0]; + + t = rthingy((args[1][0] == '.') ? args[1] : dyncat(".", args[1])); + pw = t->widget; + unrefthingy(t); + + if (!pw) { + zwarnnam(name, "invalid widget `%s'", args[1]); + return 1; + } + if (pw->flags & ZLE_ISCOMP && + require_module("zsh/complete", NULL) == 1) + { + zwarnnam(name, "can't load complete module"); + return 1; + } + w = zalloc(sizeof(*w)); + w->flags = pw->flags & ~(WIDGET_INT|ZLE_ISCOMP); + w->first = NULL; + if (pw->flags & ZLE_ISCOMP) { + w->flags |= WIDGET_NCOMP; + w->u.comp.fn = pw->u.fn; + w->u.comp.wid = ztrdup(args[1]); + w->u.comp.func = ztrdup(funcname); + } else { + w->u.fnnam = ztrdup(funcname); + } + if (bindwidget(w, rthingy(args[0]))) { + freewidget(w); + zwarnnam(name, "widget name `%s' is protected", args[0]); + return 1; + } + if (w->flags & WIDGET_NCOMP) + hascompwidgets++; + + return 0; +} + +/**/ +static int bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { Thingy t; diff --git i/Doc/Zsh/zle.yo w/Doc/Zsh/zle.yo index c06e226..a8b7476 100644 --- i/Doc/Zsh/zle.yo +++ w/Doc/Zsh/zle.yo @@ -404,6 +404,7 @@ xitem(tt(zle) tt(-D) var(widget) ...) xitem(tt(zle) tt(-A) var(old-widget) var(new-widget)) xitem(tt(zle) tt(-N) var(widget) [ var(function) ]) xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function)) +xitem(tt(zle) tt(-P) var(widget) var(prototype-widget) [ var(function) ]) xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ]) xitem(tt(zle) tt(-M) var(string)) xitem(tt(zle) tt(-U) var(string)) @@ -474,6 +475,20 @@ ifzman(zmanref(zshcompwid))\ ifnzman(noderef(Completion Widgets))\ . ) +item(tt(-P) var(widget) var(prototype-widget) [ var(function) ])( +Create a user-defined widget. If there is already a widget with the +specified name, it is overwritten. When the new +widget is invoked from within the editor, the specified shell var(function) +is called. If no function name is specified, it defaults to +the same name as the widget. The widget will behave as the given +var(prototype-widget). If it is a completion widget then this works like +tt(zle -C) above. An example of a useful case is wrapping the tt(yank) +widget, without using tt(zle -P), the yanked text will not be highlighted. +For further information, see +ifzman(the section `Widgets' below)\ +ifnzman(noderef(Zle Widgets))\ +. +) item(tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])( Redisplay the command line; this is to be called from within a user-defined widget to allow changes to become visible. If a var(display-string) is @@ -986,18 +1001,19 @@ The name of the widget currently being executed; read-only. vindex(WIDGETFUNC) item(tt(WIDGETFUNC) (scalar))( The name of the shell function that implements a widget defined with -either tt(zle -N) or tt(zle -C). In the former case, this is the second +either tt(zle -N), tt(zle -C) or tt(zle -P). In the former case, this is the second argument to the tt(zle -N) command that defined the widget, or -the first argument if there was no second argument. In the latter case -this is the third argument to the tt(zle -C) command that defined the -widget. Read-only. +the first argument if there was no second argument. For tt(zle -C) +and tt(zle -P), this is the third argument to the tt(zle -C) command +that defined the widget. Read-only. ) vindex(WIDGETSTYLE) item(tt(WIDGETSTYLE) (scalar))( Describes the implementation behind the completion widget currently being -executed; the second argument that followed tt(zle -C) when the widget was -defined. This is the name of a builtin completion widget. For widgets -defined with tt(zle -N) this is set to the empty string. Read-only. +executed; the second argument that followed tt(zle -C) or tt(zle -P) when +the widget was defined. This is the name of a builtin completion widget. +For widgets defined with tt(zle -N) this is set to the empty string. +Read-only. ) vindex(ZLE_STATE) item(tt(ZLE_STATE) (scalar))( -- 2.5.0