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

PATCH: make kill ring work in vi mode



This makes yank-pop also work together with vi-put-before and
vi-put-after. I find this a lot more usable than trying to work out
which of the vi numbered registers is applicable. In vim, this requires
a plugin (see https://github.com/maxbrunsfeld/vim-yankstack). 

Rather than make a bunch of static variables global, I've moved the vi
put functions to zle_misc.c. So startvichange() loses 'static' instead.
Any objections or alternative suggestions to this? There's a certain
amount of commonality between the four affected functions, should I
perhaps try to factor bits out into some smaller functions?

I'm not too happy with the way this interacts with undo. I'd prefer that
undo would revert everything to before the put instead of stepping back
through each yank-pop. This seems to be consistent with emacs though so
I'm probably stuck with it. I may also look further at what happens with
. (vi-repeat-change).

Oliver

diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 881e56b..06b1659 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -1786,7 +1786,7 @@ tindex(yank-pop)
 item(tt(yank-pop) (ESC-y) (unbound) (unbound))(
 Remove the text just yanked, rotate the kill-ring (the history of
 previously killed text) and yank the new top.  Only works following
-tt(yank) or tt(yank-pop).
+tt(yank), tt(vi-put-before), tt(vi-put-after) or tt(yank-pop).
 )
 tindex(vi-yank)
 item(tt(vi-yank) (unbound) (y) (unbound))(
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index 79d62c7..dc7e800 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -159,8 +159,8 @@
 "vi-open-line-below", viopenlinebelow, 0
 "vi-oper-swap-case", vioperswapcase, ZLE_LASTCOL
 "vi-pound-insert", vipoundinsert, 0
-"vi-put-after", viputafter, ZLE_YANK | ZLE_KEEPSUFFIX
-"vi-put-before", viputbefore, ZLE_YANK | ZLE_KEEPSUFFIX
+"vi-put-after", viputafter, ZLE_YANKAFTER | ZLE_KEEPSUFFIX
+"vi-put-before", viputbefore, ZLE_YANKBEFORE | ZLE_KEEPSUFFIX
 "vi-quoted-insert", viquotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
 "vi-repeat-change", virepeatchange, 0
 "vi-repeat-find", virepeatfind, 0
@@ -182,5 +182,5 @@
 "what-cursor-position", whatcursorposition, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "where-is", whereis, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "which-command", processcmd, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
-"yank", yank, ZLE_YANK | ZLE_KEEPSUFFIX
-"yank-pop", yankpop, ZLE_YANK | ZLE_KEEPSUFFIX
+"yank", yank, ZLE_YANKBEFORE | ZLE_KEEPSUFFIX
+"yank-pop", yankpop, ZLE_KEEPSUFFIX | ZLE_NOTCOMMAND
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index dd6cdcc..8a85ee3 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -203,13 +203,15 @@ struct widget {
 #define WIDGET_INT	(1<<0)	/* widget is internally implemented */
 #define WIDGET_NCOMP    (1<<1)	/* new style completion widget */
 #define ZLE_MENUCMP	(1<<2)	/* DON'T invalidate completion list */
-#define ZLE_YANK	(1<<3)
-#define ZLE_LINEMOVE	(1<<4)	/* command is a line-oriented movement */
-#define ZLE_LASTCOL     (1<<5)	/* command maintains lastcol correctly */
-#define ZLE_KILL	(1<<6)
-#define ZLE_KEEPSUFFIX	(1<<7)	/* DON'T remove added suffix */
-#define ZLE_NOTCOMMAND  (1<<8)	/* widget should not alter lastcmd */
-#define ZLE_ISCOMP      (1<<9)	/* usable for new style completion */
+#define ZLE_YANKAFTER	(1<<3)
+#define ZLE_YANKBEFORE	(1<<4)
+#define ZLE_YANK        (ZLE_YANKAFTER | ZLE_YANKBEFORE)
+#define ZLE_LINEMOVE	(1<<5)	/* command is a line-oriented movement */
+#define ZLE_LASTCOL     (1<<6)	/* command maintains lastcol correctly */
+#define ZLE_KILL	(1<<7)
+#define ZLE_KEEPSUFFIX	(1<<8)	/* DON'T remove added suffix */
+#define ZLE_NOTCOMMAND  (1<<9)	/* widget should not alter lastcmd */
+#define ZLE_ISCOMP      (1<<10)	/* usable for new style completion */
 
 /* thingies */
 
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 9bc1cf6..10bd71c 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -475,8 +475,10 @@ copyregionaskill(char **args)
 /*
  * kct: index into kill ring, or -1 for original cutbuffer of yank.
  * yankb, yanke: mark the start and end of last yank in editing buffer.
+ * yankcs marks the cursor position preceding the last yank
  */
-static int kct, yankb, yanke;
+static int kct, yankb, yanke, yankcs;
+
 /* The original cutbuffer, either cutbuf or one of the vi buffers. */
 static Cutbuffer kctbuf;
 
@@ -494,8 +496,7 @@ yank(UNUSED(char **args))
 	kctbuf = &cutbuf;
     if (!kctbuf->buf)
 	return 1;
-    mark = zlecs;
-    yankb = zlecs;
+    yankb = yankcs = mark = zlecs;
     while (n--) {
 	kct = -1;
 	spaceinline(kctbuf->len);
@@ -508,6 +509,84 @@ yank(UNUSED(char **args))
 
 /**/
 int
+viputbefore(UNUSED(char **args))
+{
+    int n = zmult;
+
+    startvichange(-1);
+    if (n < 0 || zmod.flags & MOD_NULL)
+	return 1;
+    if (zmod.flags & MOD_VIBUF)
+	kctbuf = &vibuf[zmod.vibuf];
+    else
+	kctbuf = &cutbuf;
+    if (!kctbuf->buf)
+	return 1;
+    kct = -1;
+    yankcs = zlecs;
+    if (kctbuf->flags & CUTBUFFER_LINE) {
+	yankb = zlecs = findbol();
+	spaceinline(kctbuf->len + 1);
+	ZS_memcpy(zleline + zlecs, kctbuf->buf, kctbuf->len);
+	yanke = zlecs + kctbuf->len + 1;
+	zleline[zlecs + kctbuf->len] = ZWC('\n');
+	vifirstnonblank(zlenoargs);
+    } else {
+	yankb = zlecs;
+	while (n--) {
+	    spaceinline(kctbuf->len);
+	    ZS_memcpy(zleline + zlecs, kctbuf->buf, kctbuf->len);
+	    zlecs += kctbuf->len;
+	}
+	yanke = zlecs;
+	if (zlecs)
+	    DECCS();
+    }
+    return 0;
+}
+
+/**/
+int
+viputafter(UNUSED(char **args))
+{
+    int n = zmult;
+
+    startvichange(-1);
+    if (n < 0 || zmod.flags & MOD_NULL)
+	return 1;
+    if (zmod.flags & MOD_VIBUF)
+	kctbuf = &vibuf[zmod.vibuf];
+    else
+	kctbuf = &cutbuf;
+    if (!kctbuf->buf)
+	return 1;
+    kct = -1;
+    yankcs = zlecs;
+    if (kctbuf->flags & CUTBUFFER_LINE) {
+	yankb = zlecs = findeol();
+	spaceinline(kctbuf->len + 1);
+	zleline[zlecs++] = ZWC('\n');
+	yanke = zlecs + kctbuf->len;
+	ZS_memcpy(zleline + zlecs, kctbuf->buf, kctbuf->len);
+	vifirstnonblank(zlenoargs);
+    } else {
+	if (zlecs != findeol())
+	    INCCS();
+	yankb = zlecs;
+	while (n--) {
+	    spaceinline(kctbuf->len);
+	    ZS_memcpy(zleline + zlecs, kctbuf->buf, kctbuf->len);
+	    zlecs += kctbuf->len;
+	}
+	yanke = zlecs;
+	if (zlecs)
+	    DECCS();
+    }
+    return 0;
+}
+
+/**/
+int
 yankpop(UNUSED(char **args))
 {
     int cc, kctstart = kct;
@@ -557,11 +636,33 @@ yankpop(UNUSED(char **args))
 
     zlecs = yankb;
     foredel(yanke - yankb, CUT_RAW);
-    cc = buf->len;
-    spaceinline(cc);
-    ZS_memcpy(zleline + zlecs, buf->buf, cc);
-    zlecs += cc;
-    yanke = zlecs;
+    zlecs = yankcs;
+
+    if (buf->flags & CUTBUFFER_LINE) {
+	if (lastcmd & ZLE_YANKBEFORE) {
+	    yankb = zlecs = findbol();
+	    spaceinline(buf->len + 1);
+	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+	    yanke = zlecs + buf->len + 1;
+	    zleline[zlecs + buf->len] = ZWC('\n');
+	} else {
+	    yankb = zlecs = findeol();
+	    spaceinline(buf->len + 1);
+	    zleline[zlecs++] = ZWC('\n');
+	    yanke = zlecs + buf->len;
+	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+	}
+	vifirstnonblank(zlenoargs);
+    } else {
+	if ((lastcmd & ZLE_YANKAFTER) && zlecs != findeol())
+	    INCCS();
+	yankb = zlecs;
+	cc = buf->len;
+	spaceinline(cc);
+	ZS_memcpy(zleline + zlecs, buf->buf, cc);
+	zlecs += cc;
+	yanke = zlecs;
+    }
     return 0;
 }
 
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 0a8b27d..b0e696b 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -75,7 +75,7 @@ static int inrepeat, vichgrepeat;
  */
 
 /**/
-static void
+void
 startvichange(int im)
 {
     if (im != -1) {
@@ -793,72 +793,6 @@ vikillline(UNUSED(char **args))
 
 /**/
 int
-viputbefore(UNUSED(char **args))
-{
-    Cutbuffer buf = &cutbuf;
-    int n = zmult;
-
-    startvichange(-1);
-    if (n < 0 || zmod.flags & MOD_NULL)
-	return 1;
-    if (zmod.flags & MOD_VIBUF)
-	buf = &vibuf[zmod.vibuf];
-    if (!buf->buf)
-	return 1;
-    if(buf->flags & CUTBUFFER_LINE) {
-	zlecs = findbol();
-	spaceinline(buf->len + 1);
-	ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
-	zleline[zlecs + buf->len] = ZWC('\n');
-	vifirstnonblank(zlenoargs);
-    } else {
-	while (n--) {
-	    spaceinline(buf->len);
-	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
-	    zlecs += buf->len;
-	}
-	if (zlecs)
-	    DECCS();
-    }
-    return 0;
-}
-
-/**/
-int
-viputafter(UNUSED(char **args))
-{
-    Cutbuffer buf = &cutbuf;
-    int n = zmult;
-
-    startvichange(-1);
-    if (n < 0 || zmod.flags & MOD_NULL)
-	return 1;
-    if (zmod.flags & MOD_VIBUF)
-	buf = &vibuf[zmod.vibuf];
-    if (!buf->buf)
-	return 1;
-    if(buf->flags & CUTBUFFER_LINE) {
-	zlecs = findeol();
-	spaceinline(buf->len + 1);
-	zleline[zlecs++] = ZWC('\n');
-	ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
-	vifirstnonblank(zlenoargs);
-    } else {
-	if (zlecs != findeol())
-	    INCCS();
-	while (n--) {
-	    spaceinline(buf->len);
-	    ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
-	    zlecs += buf->len;
-	}
-	if (zlecs)
-	    DECCS();
-    }
-    return 0;
-}
-
-/**/
-int
 vijoin(UNUSED(char **args))
 {
     int x, pos;



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