about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/zle.yo29
-rw-r--r--Src/Zle/zle_main.c5
-rw-r--r--Src/Zle/zle_params.c24
-rw-r--r--Src/Zle/zle_thingy.c39
5 files changed, 92 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 20860a1f6..eaa565870 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2015-10-01  Mikael Magnusson  <mikachu@gmail.com>
+
+	* 36709: Doc/Zsh/zle.yo, Functions/Zle/bracketed-paste-url-magic,
+	Src/Zle/zle_main.c, Src/Zle/zle_params.c, Src/Zle/zle_thingy.c:
+	zle -f from inside widget to set flags and make yank start/end
+	zle params writable.
+
 2015-09-30  Daniel Shahaf  <d.s@daniel.shahaf.name>
 
 	* 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 7d95eb377..05bb14829 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,21 @@ 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 +1027,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/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 992f152df..593d636cc 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 000bc388c..b5bb288f1 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 da3a6d458..3963d7eaf 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