summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/zle.yo7
-rw-r--r--Src/Zle/iwidgets.list1
-rw-r--r--Src/Zle/zle_misc.c61
-rw-r--r--Src/Zle/zle_utils.c2
5 files changed, 70 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 1491234a3..fc9f8e5fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2014-11-17  Oliver Kiddle  <opk@zsh.org>
 
+	* 33700: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list,
+	Src/Zle/zle_misc.c, Src/Zle/zle_utils.c: new widget
+	for put in vim style visual selection mode
+
 	* 33699: Test/X02zlevi.ztst, Test/comptest: support short
 	delays in zle tests where we need KEYTIMEOUT to elapse
 
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 6fe7c9bf2..998bf4a10 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -1721,6 +1721,13 @@ Insert the contents of the kill buffer after the cursor.
 If the kill buffer contains a sequence of lines (as opposed to characters),
 paste it below the current line.
 )
+tindex(put-replace-selection)
+item(tt(put-replace-selection) (unbound) (unbound) (unbound))(
+Replace the contents of the current region or selection with the
+contents of the kill buffer. If the kill buffer contains a sequence of
+lines (as opposed to characters), the current line will be split by the
+pasted lines.
+)
 tindex(quoted-insert)
 item(tt(quoted-insert) (^V) (unbound) (unbound))(
 Insert the next character typed into the buffer literally.
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index a2bad5aa9..070116f5f 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -89,6 +89,7 @@
 "push-input", pushinput, 0
 "push-line", pushline, 0
 "push-line-or-edit", pushlineoredit, 0
+"put-replace-selection", putreplaceselection, ZLE_KEEPSUFFIX
 "quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
 "quote-line", quoteline, 0
 "quote-region", quoteregion, 0
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 3d4a9bb4e..3e6d1aaac 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -507,11 +507,26 @@ yank(UNUSED(char **args))
     return 0;
 }
 
-static void pastebuf(Cutbuffer buf, int mult, int after)
+/* position: 0 is before, 1 after, 2 split the line */
+static void pastebuf(Cutbuffer buf, int mult, int position)
 {
     int cc;
     if (buf->flags & CUTBUFFER_LINE) {
-	if (after) {
+	if (position == 2) {
+	    if (!zlecs)
+		position = 0;
+	    else if (zlecs == zlell)
+		position = 1;
+	}
+	if (position == 2) {
+	    yankb = zlecs;
+	    spaceinline(buf->len + 2);
+	    zleline[zlecs++] = ZWC('\n');
+	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+	    zlecs += buf->len;
+	    zleline[zlecs] = ZWC('\n');
+	    yanke = zlecs + 1;
+	} else if (position != 0) {
 	    yankb = zlecs = findeol();
 	    spaceinline(buf->len + 1);
 	    zleline[zlecs++] = ZWC('\n');
@@ -526,7 +541,7 @@ static void pastebuf(Cutbuffer buf, int mult, int after)
 	}
 	vifirstnonblank(zlenoargs);
     } else {
-	if (after && zlecs != findeol())
+	if (position == 1 && zlecs != findeol())
 	    INCCS();
 	yankb = zlecs;
 	cc = buf->len;
@@ -585,6 +600,44 @@ viputafter(UNUSED(char **args))
 
 /**/
 int
+putreplaceselection(UNUSED(char **args))
+{
+    int n = zmult;
+    struct cutbuffer prevbuf;
+    Cutbuffer putbuf;
+    int clear = 0;
+    int pos = 2;
+
+    startvichange(-1);
+    if (n < 0 || zmod.flags & MOD_NULL)
+	return 1;
+    putbuf = (zmod.flags & MOD_VIBUF) ? &vibuf[zmod.vibuf] : &cutbuf;
+    if (!putbuf->buf)
+	return 1;
+    memcpy(&prevbuf, putbuf, sizeof(prevbuf));
+
+    /* if "9 was specified, prevent killregion from freeing it */
+    if (zmod.vibuf == 35) {
+	putbuf->buf = 0;
+	clear = 1;
+    }
+
+    zmod.flags = 0; /* flags apply to paste not kill */
+    if (region_active == 2 && prevbuf.flags & CUTBUFFER_LINE) {
+	int a, b;
+	regionlines(&a, &b);
+	pos = (b == zlell);
+    }
+    killregion(zlenoargs);
+
+    pastebuf(&prevbuf, n, pos);
+    if (clear)
+	free(prevbuf.buf);
+    return 0;
+}
+
+/**/
+int
 yankpop(UNUSED(char **args))
 {
     int kctstart = kct;
@@ -635,7 +688,7 @@ yankpop(UNUSED(char **args))
     zlecs = yankb;
     foredel(yanke - yankb, CUT_RAW);
     zlecs = yankcs;
-    pastebuf(buf, 1, lastcmd & ZLE_YANKAFTER);
+    pastebuf(buf, 1, !!(lastcmd & ZLE_YANKAFTER));
     return 0;
 }
 
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index f56063e82..08a32c30e 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -953,7 +953,7 @@ cuttext(ZLE_STRING_T line, int ct, int flags)
     } else {
 	/* Save in "1, shifting "1-"8 along to "2-"9 */
 	int n;
-	free(vibuf[34].buf);
+	free(vibuf[35].buf);
 	for(n=35; n>27; n--)
 	    vibuf[n] = vibuf[n-1];
 	vibuf[27].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE);