summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Src/Zle/zle_vi.c43
-rw-r--r--Test/X02zlevi.ztst5
3 files changed, 43 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 9e1b0206e..bfddb06df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2014-11-21  Oliver Kiddle  <opk@zsh.org>
 
+	* 33738: Src/Zle/zle_vi.c, Test/X02zlevi.ztst: account for a
+	selection in vi-replace-chars
+
 	* 33730: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list,
 	Src/Zle/textobjects.c, Src/Zle/zle.mdd, Src/Zle/zle_keymap.c,
 	Test/X02zlevi.ztst: vim style text objects for selecting words
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index b0d69f112..e9a367668 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -257,6 +257,7 @@ getvirange(int wf)
 	pos = tmp;
     }
 
+    /* visual selection mode needs to include additional position */
     if (visual == 1 && invicmdmode())
 	INCPOS(pos);
 
@@ -576,16 +577,40 @@ vireplacechars(UNUSED(char **args))
     int n = zmult, fail = 0, newchars = 0;
 
     if (n > 0) {
-	int pos = zlecs;
-	while (n-- > 0) {
-	    if (pos == zlell || zleline[pos] == ZWC('\n')) {
-		fail = 1;
-		break;
+	if (region_active) {
+	    int a, b;
+	    if (region_active == 1) {
+		if (mark > zlecs) {
+		    a = zlecs;
+		    b = mark;
+		} else {
+		    a = mark;
+		    b = zlecs;
+		}
+		INCPOS(b);
+	    } else
+		regionlines(&a, &b);
+	    zlecs = a;
+	    if (b > zlell)
+		b = zlell;
+	    n = b - a;
+	    while (a < b) {
+		newchars++;
+		INCPOS(a);
+            }
+	    region_active = 0;
+	} else {
+	    int pos = zlecs;
+	    while (n-- > 0) {
+		if (pos == zlell || zleline[pos] == ZWC('\n')) {
+		    fail = 1;
+		    break;
+		}
+		newchars++;
+		INCPOS(pos);
 	    }
-	    newchars++;
-	    INCPOS(pos);
+	    n = pos - zlecs;
 	}
-	n = pos - zlecs;
     }
     startvichange(1);
     /* check argument range */
@@ -617,6 +642,8 @@ vireplacechars(UNUSED(char **args))
 	 * buffer offset.
 	 * Use shiftchars so as not to adjust the cursor position;
 	 * we are overwriting anything that remains directly.
+	 * With a selection this will replace newlines which vim
+	 * doesn't do but this simplifies things a lot.
 	 */
 	if (n > newchars)
 	    shiftchars(zlecs, n - newchars);
diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst
index 6b7ca567e..1185a083d 100644
--- a/Test/X02zlevi.ztst
+++ b/Test/X02zlevi.ztst
@@ -289,6 +289,11 @@
 >BUFFER: x g
 >CURSOR: 2
 
+  zletest $'line end\eOstart 1 back new\e0verawvrbwevbrcwvj0erdwv$re'
+0:replace characters in selections
+>BUFFER: aaaaa b cccc dddddddd eee
+>CURSOR: 24
+
   zletest $'one two\eyb0vep'
 0:put over selection at start of buffer
 >BUFFER: tw two