summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Src/Zle/textobjects.c1
-rw-r--r--Src/Zle/zle_misc.c27
-rw-r--r--Src/Zle/zle_move.c12
-rw-r--r--Src/Zle/zle_vi.c56
-rw-r--r--Test/X02zlevi.ztst10
6 files changed, 66 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c15d969b..ca2a6021c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2014-12-05  Oliver Kiddle  <opk@zsh.org>
 
+	* 33860: Src/Zle/textobjects.c, Src/Zle/zle_misc.c,
+	Src/Zle/zle_move.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst:
+	minor fixes to vi mode changes
+
 	* 33845: Src/Zle/zle_hist.c: save correct cursor position with
 	push-line from vi command mode
 
diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c
index 7f049c5dd..85d014b27 100644
--- a/Src/Zle/textobjects.c
+++ b/Src/Zle/textobjects.c
@@ -286,6 +286,7 @@ selectargument(UNUSED(char **args))
     /* convert offsets for mark and zlecs back to ZLE internal format */
     linein[wend] = '\0'; /* a bit of a hack to get two offsets */
     free(stringaszleline(linein, wstarts[wcur], &zlecs, &tmpsz, &mark));
+    free(linein);
 
     if (bindk == t_selectinshellword) {
 	ZLE_CHAR_T *match = ZWS("`\'\"");
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index a1dc3fa5c..d432acf7b 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -476,9 +476,11 @@ killregion(UNUSED(char **args))
 	    foredel(1, 0);
 	    vifirstnonblank(zlenoargs);
 	}
-    } else if (mark > zlecs)
-	forekill(mark - zlecs + invicmdmode(), CUT_RAW);
-    else {
+    } else if (mark > zlecs) {
+	if (invicmdmode())
+	    INCPOS(mark);
+	forekill(mark - zlecs, CUT_RAW);
+    } else {
 	if (invicmdmode())
 	    INCCS();
 	backkill(zlecs - mark, CUT_FRONT|CUT_RAW);
@@ -490,6 +492,7 @@ killregion(UNUSED(char **args))
 int
 copyregionaskill(char **args)
 {
+    int start, end;
     if (*args) {
         int len;
         ZLE_STRING_T line = stringaszleline(*args, 0, &len, NULL, NULL);
@@ -498,10 +501,16 @@ copyregionaskill(char **args)
     } else {
 	if (mark > zlell)
 	    mark = zlell;
-	if (mark > zlecs)
-	    cut(zlecs, mark - zlecs + invicmdmode(), 0);
-	else
-	    cut(mark, zlecs - mark + invicmdmode(), CUT_FRONT);
+	if (mark > zlecs) {
+	    start = zlecs;
+	    end = mark;
+	} else {
+	    start = mark;
+	    end = zlecs;
+	}
+	if (invicmdmode())
+	    INCPOS(end);
+	cut(start, end - start, mark > zlecs ? 0 : CUT_FRONT);
     }
     return 0;
 }
@@ -1057,7 +1066,9 @@ quoteregion(UNUSED(char **args))
 	mark = zlecs;
 	zlecs = tmp;
     }
-    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs + extra) *
+    if (extra)
+	INCPOS(mark);
+    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) *
 	ZLE_CHAR_SIZE);
     ZS_memcpy(str, zleline + zlecs, len);
     foredel(len, CUT_RAW);
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index fad6b0a5f..939cfb1d0 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -575,7 +575,8 @@ vimatchbracket(UNUSED(char **args))
 
     if ((zlecs == zlell || zleline[zlecs] == '\n') && zlecs > 0)
 	DECCS();
-
+    if (virangeflag)
+	mark = zlecs;
   otog:
     if (zlecs == zlell || zleline[zlecs] == '\n') {
 	zlecs = ocs;
@@ -587,7 +588,6 @@ vimatchbracket(UNUSED(char **args))
 	oth = '}';
 	break;
     case /*{*/ '}':
-	virangeflag = -virangeflag;
 	dir = -1;
 	oth = '{'; /*}*/
 	break;
@@ -596,7 +596,6 @@ vimatchbracket(UNUSED(char **args))
 	oth = ')';
 	break;
     case ')':
-	virangeflag = -virangeflag;
 	dir = -1;
 	oth = '(';
 	break;
@@ -605,7 +604,6 @@ vimatchbracket(UNUSED(char **args))
 	oth = ']';
 	break;
     case ']':
-	virangeflag = -virangeflag;
 	dir = -1;
 	oth = '[';
 	break;
@@ -613,6 +611,8 @@ vimatchbracket(UNUSED(char **args))
 	INCCS();
 	goto otog;
     }
+    if (virangeflag && dir < 0)
+	INCPOS(mark); /* include starting position when going backwards */
     ct = 1;
     while (zlecs >= 0 && zlecs < zlell && ct) {
 	if (dir < 0)
@@ -636,7 +636,7 @@ vimatchbracket(UNUSED(char **args))
 int
 viforwardchar(char **args)
 {
-    int lim = findeol() - invicmdmode() + virangeflag;
+    int lim = findeol();
     int n = zmult;
 
     if (n < 0) {
@@ -646,6 +646,8 @@ viforwardchar(char **args)
 	zmult = n;
 	return ret;
     }
+    if (invicmdmode() && !virangeflag)
+	DECPOS(lim);
     if (zlecs >= lim)
 	return 1;
     while (n-- && zlecs < lim)
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index e9a367668..249e38f15 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -167,6 +167,8 @@ getvirange(int wf)
     Thingy k2;
 
     if (visual) {
+	if (!zlell)
+	    return -1;
 	pos = mark;
 	vilinerange = (visual == 2);
 	region_active = 0;
@@ -179,17 +181,15 @@ getvirange(int wf)
 	if (km)
 	    selectlocalmap(km);
 	/* Now we need to execute the movement command, to see where it *
-	* actually goes.  virangeflag here indicates to the movement   *
-	* function that it should place the cursor at the end of the   *
-	* range, rather than where the cursor would actually go if it  *
-	* were executed normally.  This makes a difference to some     *
-	* commands, but not all.  For example, if searching forward    *
-	* for a character, under normal circumstances the cursor lands *
-	* on the character.  For a range, the range must include the   *
-	* character, so the cursor gets placed after the character if  *
-	* virangeflag is set.  vi-match-bracket needs to change the    *
-	* value of virangeflag under some circumstances, meaning that  *
-	* we need to change the *starting* position.                   */
+	 * actually goes.  virangeflag here indicates to the movement   *
+	 * function that it should place the cursor at the end of the   *
+	 * range, rather than where the cursor would actually go if it  *
+	 * were executed normally.  This makes a difference to some     *
+	 * commands, but not all.  For example, if searching forward    *
+	 * for a character, under normal circumstances the cursor lands *
+	 * on the character.  For a range, the range must include the   *
+	 * character, so the cursor gets placed after the character if  *
+	 * virangeflag is set.                                          */
 	zmod.flags &= ~MOD_TMULT;
 	do {
 	    vilinerange = 0;
@@ -202,10 +202,10 @@ getvirange(int wf)
 		return -1;
 	    }
 	    /*
-	    * With k2 == bindk, the command key is repeated:
-	    * a number of lines is used.  If the function used
-	    * returns 1, we fail.
-	    */
+	     * With k2 == bindk, the command key is repeated:
+	     * a number of lines is used.  If the function used
+	     * returns 1, we fail.
+	     */
 	    if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1))
 		ret = -1;
 	    if(vichgrepeat)
@@ -217,8 +217,8 @@ getvirange(int wf)
 	selectlocalmap(NULL);
 
 	/* It is an error to use a non-movement command to delimit the *
-	* range.  We here reject the case where the command modified  *
-	* the line, or selected a different history line.             */
+	 * range.  We here reject the case where the command modified  *
+	 * the line, or selected a different history line.             */
 	if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) {
 	    histline = hist1;
 	    ZS_memcpy(zleline, lastline, zlell = lastll);
@@ -228,21 +228,16 @@ getvirange(int wf)
 	}
 
 	/* Can't handle an empty file.  Also, if the movement command *
-	* failed, or didn't move, it is an error.                    */
-	if (!zlell || (zlecs == pos && mark == -1 && virangeflag != 2) || ret == -1) {
+	 * failed, or didn't move, it is an error.                    */
+	if (!zlell || (zlecs == pos && (mark == -1 || mark == zlecs) &&
+		    virangeflag != 2) || ret == -1) {
 	    mark = mpos;
 	    return -1;
 	}
-
-	/* vi-match-bracket changes the value of virangeflag when *
-	* moving to the opening bracket, meaning that we need to *
-	* change the *starting* position.                        */
-	if (virangeflag == -1)
-	    INCPOS(pos);
 	virangeflag = 0;
 
 	/* if the mark has moved, ignore the original cursor position *
-	* and use the mark. */
+	 * and use the mark.                                          */
 	if (mark != -1)
 	    pos = mark;
     }
@@ -883,7 +878,7 @@ vijoin(UNUSED(char **args))
     } else if ((x = findeol()) == zlell || (visual && x >= mark))
 	return 1;
 
-    while (n) {
+    do {
 	zlecs = x + 1;
 	pos = zlecs;
 	for (; zlecs != zlell && ZC_iblank(zleline[zlecs]); INCPOS(zlecs))
@@ -895,14 +890,13 @@ vijoin(UNUSED(char **args))
 	    DECPOS(pos);
 	    if (ZC_iblank(zleline[pos])) {
 		zlecs = pos;
-		return 0;
+		continue;
 	    }
 	}
 	spaceinline(1);
 	zleline[zlecs] = ZWC(' ');
-	if ((!visual && --n < 2) || (x = findeol()) == zlell || (visual && x >= mark))
-	    return 0;
-    }
+    } while (!((!visual && --n < 2) || (x = findeol()) == zlell || (visual && x >= mark)));
+
     return 0;
 }
 
diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst
index 8f9390250..520431193 100644
--- a/Test/X02zlevi.ztst
+++ b/Test/X02zlevi.ztst
@@ -317,6 +317,16 @@
 >BUFFER: bhello
 >CURSOR: 5
 
+  zletest $'old\C-w\evyvP'
+0:yank empty selection
+>BUFFER: old
+>CURSOR: 2
+
+  zletest $'old\C-w\evdvP'
+0:delete empty selection
+>BUFFER: old
+>CURSOR: 2
+
   zletest $'one\eotwo\eyykVp'
 0:yank linewise and put over linewise selection at start of buffer
 >BUFFER: two