zsh-workers
 help / color / mirror / code / Atom feed
* Overriding a yank* widget in zle
@ 2010-12-30 21:59 Wayne Davison
  2010-12-31  6:39 ` Wayne Davison
  2010-12-31  8:28 ` Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Wayne Davison @ 2010-12-30 21:59 UTC (permalink / raw)
  To: zsh-workers


[-- Attachment #1.1: Type: text/plain, Size: 544 bytes --]

I'm trying to figure out how to override the zle yank widget without
breaking the ability to use yank-pop, and this does not appear to be
possible in the current code.  A query in early 2005 on the subject went
unanswered, so hopefully I didn't miss some simple solution to this.

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.  I'm not sure that this is the right solution, so see
what you think of the change.

..wayne..

[-- Attachment #1.2: Type: text/html, Size: 625 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Overriding a yank* widget in zle
  2010-12-30 21:59 Overriding a yank* widget in zle Wayne Davison
@ 2010-12-31  6:39 ` Wayne Davison
  2010-12-31  8:28 ` Bart Schaefer
  1 sibling, 0 replies; 11+ messages in thread
From: Wayne Davison @ 2010-12-31  6:39 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 273 bytes --]

On Thu, Dec 30, 2010 at 1:59 PM, Wayne Davison <wayned@users.sourceforge.net
> wrote:

> I've coded up a patch that adds the -y option to zle
>

Looks like the mailing list ate my patch attachment, so I uploaded it here:

http://opencoder.net/zle-yank-opt.patch

..wayne..

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Overriding a yank* widget in zle
  2010-12-30 21:59 Overriding a yank* widget in zle Wayne Davison
  2010-12-31  6:39 ` Wayne Davison
@ 2010-12-31  8:28 ` Bart Schaefer
  2010-12-31 23:23   ` Wayne Davison
  2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
  1 sibling, 2 replies; 11+ messages in thread
From: Bart Schaefer @ 2010-12-31  8:28 UTC (permalink / raw)
  To: zsh-workers

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?).


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Overriding a yank* widget in zle
  2010-12-31  8:28 ` Bart Schaefer
@ 2010-12-31 23:23   ` Wayne Davison
  2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
  1 sibling, 0 replies; 11+ messages in thread
From: Wayne Davison @ 2010-12-31 23:23 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 943 bytes --]

On Fri, Dec 31, 2010 at 12:28 AM, Bart Schaefer
<schaefer@brasslantern.com>wrote:

> 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.
>

That seems like a great solution to me.

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?).
>

Something like that would work if done right.  I tried something along those
lines (it was named "yank-noop"), but hadn't worked out the right bits to
make the flags stick around long enough before I changed direction.  I like
the prototype idiom best, though.

..wayne..

^ permalink raw reply	[flat|nested] 11+ messages in thread

* PATCH: Implement zle -P
  2010-12-31  8:28 ` Bart Schaefer
  2010-12-31 23:23   ` Wayne Davison
@ 2015-08-31  7:54   ` Mikael Magnusson
  2015-08-31  7:56     ` Mikael Magnusson
                       ` (2 more replies)
  1 sibling, 3 replies; 11+ messages in thread
From: Mikael Magnusson @ 2015-08-31  7:54 UTC (permalink / raw)
  To: zsh-workers

This lets you say
% zle -P mywidget prototypewidget myfunction
and it will work like zle -N mywidget myfunction except it will behave
like prototypewidget in Various Ways™.

---

I haven't tested this much (for completion functions, not at all) yet,
but it works for the case in the current thread, see example at the
bottom. Does it look overall sane? I'm not very sure on which/how/where
all these flags are checked and set. The final argument should probably
be optional and default to the first, like for zle -N, but zle -C doesn't
seem to do that, and that's the code I mostly copied.

I don't see any reason to change zle -N to call into zle -P internally 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 | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index c1b70e7..d4592ba 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..e648838 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, 3, 3},
 	{ 'R', bin_zle_refresh, 0, -1 },
 	{ 'M', bin_zle_mesg, 1, 1 },
 	{ 'U', bin_zle_unget, 1, 1 },
@@ -591,6 +592,42 @@ 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;
+
+    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;
+    }
+    w = zalloc(sizeof(*w));
+    w->flags = pw->flags & ~WIDGET_INT;
+    w->first = NULL;
+    if (w->flags & WIDGET_NCOMP) {
+	w->u.comp.fn = pw->u.fn;
+	w->u.comp.wid = ztrdup(args[1]);
+	w->u.comp.func = ztrdup(args[2]);
+    } else {
+	w->u.fnnam = ztrdup(args[2]);
+    }
+    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;
-- 
2.5.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: PATCH: Implement zle -P
  2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
@ 2015-08-31  7:56     ` Mikael Magnusson
  2015-08-31  9:55     ` PATCH: Set completion function flags correctly for " Mikael Magnusson
  2015-08-31 17:11     ` PATCH: Implement " Peter Stephenson
  2 siblings, 0 replies; 11+ messages in thread
From: Mikael Magnusson @ 2015-08-31  7:56 UTC (permalink / raw)
  To: zsh workers

On Mon, Aug 31, 2015 at 9:54 AM, Mikael Magnusson <mikachu@gmail.com> wrote:
> This lets you say
> % zle -P mywidget prototypewidget myfunction
> and it will work like zle -N mywidget myfunction except it will behave
> like prototypewidget in Various Ways™.
>
> ---
>
> I haven't tested this much (for completion functions, not at all) yet,
> but it works for the case in the current thread, see example at the
> bottom. Does it look overall sane? I'm not very sure on which/how/where
> all these flags are checked and set. The final argument should probably
> be optional and default to the first, like for zle -N, but zle -C doesn't
> seem to do that, and that's the code I mostly copied.
>
> I don't see any reason to change zle -N to call into zle -P internally though.

Here's the original thread, by the way.
http://www.zsh.org/mla/workers/2010/msg01000.html

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 11+ messages in thread

* PATCH: Set completion function flags correctly for zle -P
  2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
  2015-08-31  7:56     ` Mikael Magnusson
@ 2015-08-31  9:55     ` Mikael Magnusson
  2015-08-31 10:17       ` Mikael Magnusson
  2015-08-31 17:11     ` PATCH: Implement " Peter Stephenson
  2 siblings, 1 reply; 11+ messages in thread
From: Mikael Magnusson @ 2015-08-31  9:55 UTC (permalink / raw)
  To: zsh-workers

---

This appears to work better.

 Src/Zle/zle_thingy.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index e648838..0401099 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -606,9 +606,10 @@ bin_zle_prototype(char *name, char **args, UNUSED(Options ops), UNUSED(char func
 	return 1;
     }
     w = zalloc(sizeof(*w));
-    w->flags = pw->flags & ~WIDGET_INT;
+    w->flags = pw->flags & ~(WIDGET_INT|ZLE_ISCOMP);
     w->first = NULL;
-    if (w->flags & WIDGET_NCOMP) {
+    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(args[2]);
-- 
2.5.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: PATCH: Set completion function flags correctly for zle -P
  2015-08-31  9:55     ` PATCH: Set completion function flags correctly for " Mikael Magnusson
@ 2015-08-31 10:17       ` Mikael Magnusson
  0 siblings, 0 replies; 11+ messages in thread
From: Mikael Magnusson @ 2015-08-31 10:17 UTC (permalink / raw)
  To: zsh workers

On Mon, Aug 31, 2015 at 11:55 AM, Mikael Magnusson <mikachu@gmail.com> wrote:
> ---
>
> This appears to work better.
>
>  Src/Zle/zle_thingy.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
> index e648838..0401099 100644
> --- a/Src/Zle/zle_thingy.c
> +++ b/Src/Zle/zle_thingy.c
> @@ -606,9 +606,10 @@ bin_zle_prototype(char *name, char **args, UNUSED(Options ops), UNUSED(char func
>         return 1;
>      }
>      w = zalloc(sizeof(*w));
> -    w->flags = pw->flags & ~WIDGET_INT;
> +    w->flags = pw->flags & ~(WIDGET_INT|ZLE_ISCOMP);
>      w->first = NULL;
> -    if (w->flags & WIDGET_NCOMP) {
> +    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(args[2]);

Here's the final(?) touchup, not counting documentation. It makes the
last argument optional. Maybe it would be better to make the middle
argument optional? Not sure. (This one will be whitespace damaged.)

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.)

diff --git i/Src/Zle/zle_thingy.c w/Src/Zle/zle_thingy.c
index 8c66761..20a1de9 100644
--- i/Src/Zle/zle_thingy.c
+++ w/Src/Zle/zle_thingy.c
@@ -347,7 +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, 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 },
@@ -596,6 +596,7 @@ 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;
@@ -618,9 +619,9 @@ bin_zle_prototype(char *name, char **args,
UNUSED(Options ops), UNUSED(char func
        w->flags |= WIDGET_NCOMP;
        w->u.comp.fn = pw->u.fn;
        w->u.comp.wid = ztrdup(args[1]);
-       w->u.comp.func = ztrdup(args[2]);
+       w->u.comp.func = ztrdup(funcname);
     } else {
-       w->u.fnnam = ztrdup(args[2]);
+       w->u.fnnam = ztrdup(funcname);
     }
     if (bindwidget(w, rthingy(args[0]))) {
        freewidget(w);


-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: PATCH: Implement zle -P
  2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
  2015-08-31  7:56     ` Mikael Magnusson
  2015-08-31  9:55     ` PATCH: Set completion function flags correctly for " Mikael Magnusson
@ 2015-08-31 17:11     ` Peter Stephenson
  2015-09-01  6:23       ` Bart Schaefer
  2 siblings, 1 reply; 11+ messages in thread
From: Peter Stephenson @ 2015-08-31 17:11 UTC (permalink / raw)
  To: zsh-workers

On Mon, 31 Aug 2015 09:54:02 +0200
Mikael Magnusson <mikachu@gmail.com> wrote:
> This lets you say
> % zle -P mywidget prototypewidget myfunction
> and it will work like zle -N mywidget myfunction except it will behave
> like prototypewidget in Various Ways™.

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.

pws


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: PATCH: Implement zle -P
  2015-08-31 17:11     ` PATCH: Implement " Peter Stephenson
@ 2015-09-01  6:23       ` Bart Schaefer
  2015-09-01  6:50         ` Mikael Magnusson
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2015-09-01  6:23 UTC (permalink / raw)
  To: zsh-workers

On Aug 31,  6:11pm, Peter Stephenson wrote:
} Subject: Re: PATCH: Implement zle -P
}
} On Mon, 31 Aug 2015 09:54:02 +0200
} Mikael Magnusson <mikachu@gmail.com> wrote:
} > This lets you say
} > % zle -P mywidget prototypewidget myfunction
} > and it will work like zle -N mywidget myfunction except it will behave
} > like prototypewidget in Various Ways0x2122.
} 
} 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.

I presume this is exactly like "zle -C name widget function" except that
"widget" doesn't have to be a completion widget and "function" defaults
to being the same as "name".

Presumably the idea is for wrapper widgets, e.g., something like this:

    zle -P bracketed-paste-magic bracketed-paste

which would then make b-p-magic behave exactly like b-p, and thereby,
e.g., eliminate the need for this stuff at the end of the former:

    # Arrange to display highlighting if necessary
    if [[ -n ${(M)zle_highlight:#paste:*} ]]; then
        zle -R
        zle .read-command && zle -U - $KEYS
    fi

If that's NOT what it accomplishes, then I'm uncertain why it's needed
at all.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: PATCH: Implement zle -P
  2015-09-01  6:23       ` Bart Schaefer
@ 2015-09-01  6:50         ` Mikael Magnusson
  0 siblings, 0 replies; 11+ messages in thread
From: Mikael Magnusson @ 2015-09-01  6:50 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh workers

On Tue, Sep 1, 2015 at 8:23 AM, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Aug 31,  6:11pm, Peter Stephenson wrote:
> } Subject: Re: PATCH: Implement zle -P
> }
> } On Mon, 31 Aug 2015 09:54:02 +0200
> } Mikael Magnusson <mikachu@gmail.com> wrote:
> } > This lets you say
> } > % zle -P mywidget prototypewidget myfunction
> } > and it will work like zle -N mywidget myfunction except it will behave
> } > like prototypewidget in Various Ways0x2122.
> }
> } 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.
>
> I presume this is exactly like "zle -C name widget function" except that
> "widget" doesn't have to be a completion widget and "function" defaults
> to being the same as "name".
>
> Presumably the idea is for wrapper widgets, e.g., something like this:
>
>     zle -P bracketed-paste-magic bracketed-paste
>
> which would then make b-p-magic behave exactly like b-p, and thereby,
> e.g., eliminate the need for this stuff at the end of the former:
>
>     # Arrange to display highlighting if necessary
>     if [[ -n ${(M)zle_highlight:#paste:*} ]]; then
>         zle -R
>         zle .read-command && zle -U - $KEYS
>     fi
>
> If that's NOT what it accomplishes, then I'm uncertain why it's needed
> at all.

Well, it was your idea in the first place. And yeah, I made a mess of
these threads, there's an example for the above in the latest mail.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-09-01  6:51 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-30 21:59 Overriding a yank* widget in zle Wayne Davison
2010-12-31  6:39 ` Wayne Davison
2010-12-31  8:28 ` Bart Schaefer
2010-12-31 23:23   ` Wayne Davison
2015-08-31  7:54   ` PATCH: Implement zle -P Mikael Magnusson
2015-08-31  7:56     ` Mikael Magnusson
2015-08-31  9:55     ` PATCH: Set completion function flags correctly for " Mikael Magnusson
2015-08-31 10:17       ` Mikael Magnusson
2015-08-31 17:11     ` PATCH: Implement " Peter Stephenson
2015-09-01  6:23       ` Bart Schaefer
2015-09-01  6:50         ` Mikael Magnusson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).