Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: zle -f from inside widget to set flags and make yank start/end zle params writable



I feel better about this interface, I think. And as a bonus, I did add
the 'kill' option for zle -f too (even tested it this time, and it does
work and fixes that problem for wrap widgets).

This is mostly the same as earlier patches I've sent but this version
now actually allows you to highlight a custom region, rather than having
to set CUTBUFFER and invoke 'zle .yank'.

'yank-pop' seems to work, although it is not a widget I ever use so
I can't say if it's working _sanely_. I did at one point manage to get
into a state where part of the commandline didn't even have the "default"
style, but I think (hope) that's not the fault of this patch.

---
 Doc/Zsh/zle.yo                          | 21 +++++++++++++-----
 Functions/Zle/bracketed-paste-url-magic | 38 ++++++++++++++++++++++++++++++++
 Src/Zle/zle_main.c                      |  5 +++--
 Src/Zle/zle_params.c                    | 24 +++++++++++++++-----
 Src/Zle/zle_thingy.c                    | 39 +++++++++++++++++++++++++++++++++
 5 files changed, 115 insertions(+), 12 deletions(-)
 create mode 100644 Functions/Zle/bracketed-paste-url-magic

NB, I see now I forgot to wrap the text in zle.yo, I'll do that before pushing.

diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 7d95eb3..0e4caec 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -404,6 +404,7 @@ xitem(tt(zle) tt(-l) [ tt(-L) | tt(-a) ] [ var(string) ... ])
 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(-f) var(flag) [ var(flag)... ])
 xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function))
 xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
 xitem(tt(zle) tt(-M) var(string))
@@ -464,6 +465,13 @@ ifzman(the section `Widgets' below)\
 ifnzman(noderef(Zle Widgets))\
 .
 )
+item(tt(-f) var(flag) [ var(flag)... ])(
+Set various flags on the running widget.  Possible values for var(flag) are:
+
+tt(yank) for indicating that the widget has yanked text into the buffer.  If the widget is wrapping an existing internal widget, no further action is necessary, but if it has inserted the text manually, then it should also take care to set tt(YANK_START) and tt(YANK_END) correctly.  tt(yankbefore) does the same but is used when the yanked text appears after the cursor.
+
+tt(kill) for indicating that text has been killed into the cutbuffer.  When repeatedly invoking a kill widget, text is appended to the cutbuffer instead of replacing it, but when wrapping such widgets, it is necessary to call `tt(zle -f kill)' to retain this effect.
+)
 cindex(completion widgets, creating)
 item(tt(-C) var(widget) var(completion-widget) var(function))(
 Create a user-defined completion widget named var(widget). The 
@@ -1011,11 +1019,14 @@ vindex(YANK_END)
 xitem(tt(YANK_ACTIVE) (integer))
 xitem(tt(YANK_START) (integer))
 item(tt(YANK_END) (integer))(
-These three parameters indicate whether text has just been yanked (pasted)
-into the buffer.  tt(YANK_START) and tt(YANK_END) are in the same units as
-tt(CURSOR), and are only valid when tt(YANK_ACTIVE) is non-zero.
-
-All three are read-only.
+tt(YANK_ACTIVE) indicates whether text has just been yanked (pasted)
+into the buffer.  tt(YANK_START) and tt(YANK_END) give the location of
+the pasted text and are in the same units as tt(CURSOR).  They are only
+valid for reading when tt(YANK_ACTIVE) is non-zero.  They can also be
+assigned by widgets that insert text in a yank-like fashion, for example
+wrappers of tt(bracketed-paste).  See also tt(zle -f).
+
+tt(YANK_ACTIVE) is read-only.
 )
 vindex(ZLE_STATE)
 item(tt(ZLE_STATE) (scalar))(
diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic
new file mode 100644
index 0000000..b952d84
--- /dev/null
+++ b/Functions/Zle/bracketed-paste-url-magic
@@ -0,0 +1,38 @@
+# bracketed-paste-url-magic quotes pasted urls automatically, if the
+# paste exactly starts with a url, eg no spaces or other characters precede it
+#
+# To use it, put this in your startup files (eg, .zshrc)
+#
+# autoload -Uz bracketed-paste-url-magic
+# zle -N bracketed-paste bracketed-paste-url-magic
+#
+# You can customize which schemas are to be quoted by using
+#
+# zstyle :bracketed-paste-url-magic schema http https ftp
+#
+# The default can be seen just below.
+
+local -a schema
+zstyle -a :bracketed-paste-url-magic schema schema || schema=(http https ftp ftps file ssh sftp)
+
+local wantquote=${NUMERIC:-0}
+local content
+local start=$#LBUFFER
+
+zle .$WIDGET -N content
+
+if ! (( $wantquote )); then
+  if [[ $content = (${(~j:|:)schema})://* ]]; then
+    wantquote=1
+  fi
+fi
+
+if (( $wantquote )); then
+  content=${(q-)content}
+fi
+
+LBUFFER+=$content
+
+YANK_START=$start
+YANK_END=$#LBUFFER
+zle -f yank
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 992f152..593d636 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -1402,7 +1402,8 @@ execzlefunc(Thingy func, char **args, int set_bindk)
 	    opts[XTRACE] = oxt;
 	    sfcontext = osc;
 	    endparamscope();
-	    lastcmd = 0;
+	    lastcmd = w->flags;
+	    w->flags = 0;
 	    r = 1;
 	    redup(osi, 0);
 	}
@@ -1981,7 +1982,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, "aAcCDfFgGIKlLmMNrRTUw", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index 000bc38..b5bb288 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -98,9 +98,9 @@ static const struct gsu_integer undo_change_no_gsu =
 static const struct gsu_integer undo_limit_no_gsu =
 { get_undo_limit_change, set_undo_limit_change, zleunsetfn };
 static const struct gsu_integer yankstart_gsu =
-{ get_yankstart, NULL, zleunsetfn };
+{ get_yankstart, set_yankstart, zleunsetfn };
 static const struct gsu_integer yankend_gsu =
-{ get_yankend, NULL, zleunsetfn };
+{ get_yankend, set_yankend, zleunsetfn };
 static const struct gsu_integer yankactive_gsu =
 { get_yankactive, NULL, zleunsetfn };
 
@@ -149,8 +149,8 @@ static struct zleparam {
     { "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL },
     { "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL },
     { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL },
-    { "YANK_START", PM_INTEGER | PM_READONLY, GSU(yankstart_gsu), NULL },
-    { "YANK_END", PM_INTEGER | PM_READONLY, GSU(yankend_gsu), NULL },
+    { "YANK_START", PM_INTEGER, GSU(yankstart_gsu), NULL },
+    { "YANK_END", PM_INTEGER, GSU(yankend_gsu), NULL },
     { "YANK_ACTIVE", PM_INTEGER | PM_READONLY, GSU(yankactive_gsu), NULL },
     { "ZLE_STATE", PM_SCALAR | PM_READONLY, GSU(zle_state_gsu), NULL },
     { NULL, 0, NULL, NULL }
@@ -503,7 +503,21 @@ get_yankend(UNUSED(Param pm))
 static zlong
 get_yankactive(UNUSED(Param pm))
 {
-    return lastcmd & ZLE_YANK;
+    return !!(lastcmd & ZLE_YANK) + !!(lastcmd & ZLE_YANKAFTER);
+}
+
+/**/
+static void
+set_yankstart(UNUSED(Param pm), zlong i)
+{
+    yankb = i;
+}
+
+/**/
+static void
+set_yankend(UNUSED(Param pm), zlong i)
+{
+    yanke = i;
 }
 
 /**/
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index da3a6d4..3963d7e 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -352,6 +352,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func))
 	{ 'U', bin_zle_unget, 1, 1 },
 	{ 'K', bin_zle_keymap, 1, 1 },
 	{ 'I', bin_zle_invalidate, 0, 0 },
+	{ 'f', bin_zle_flags, 1, -1 },
 	{ 'F', bin_zle_fd, 0, 2 },
 	{ 'T', bin_zle_transform, 0, 2},
 	{ 0,   bin_zle_call, 0, -1 },
@@ -625,6 +626,44 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func)
 
 /**/
 static int
+bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func))
+{
+    char **flag;
+
+    if (!zle_usable()) {
+	zwarnnam(name, "can only set flags from a widget");
+	return 1;
+    }
+
+    if (bindk) {
+	Widget w = bindk->widget;
+	if (w) {
+	    for (flag = args; *flag; flag++) {
+		if (!strcmp(*flag, "yank")) {
+		    w->flags |= ZLE_YANKAFTER;
+		} else if (!strcmp(*flag, "yankbefore"))
+		    w->flags |= ZLE_YANKBEFORE;
+		else if (!strcmp(*flag, "kill"))
+		    w->flags |= ZLE_KILL;
+		/*
+		 * These won't do anything yet, because of how execzlefunc
+		 * handles user widgets
+		} else if (!strcmp(*flag, "menucmp"))
+		    w->flags |= ZLE_MENUCMP;
+		else if (!strcmp(*flag, "linemove"))
+		    w->flags |= ZLE_LINEMOVE;
+		else if (!strcmp(*flag, "keepsuffix"))
+		    w->flags |= ZLE_KEEPSUFFIX;
+		*/
+		else
+		    zwarnnam(name, "invalid flag `%s' given to zle -f", *flag);
+	    }
+	}
+    }
+}
+
+/**/
+static int
 zle_usable()
 {
     return zleactive && !incompctlfunc && !incompfunc
-- 
2.5.0



Messages sorted by: Reverse Date, Date, Thread, Author