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

PATCH: allow region to function as vi-mode visual



This does a few different things all aimed at making visual mode work
more like it should.

Firstly, in vi command mode, the region now extends by one more
character at the end. This is needed as a consequence of the way vi
moves the cursor back one position for command mode. Without it, it is
impossible to select the final character of the buffer as part of the
region. This is the easiest way to make things compatible with vim.

Unfortunately it complicates all widgets that do something with the region
because they have to allow for it but I've adapted kill-region,
quote-region and copy-region-as-kill.

A visual-mode widget has been added which toggles the region aswell as
setting it. 

Finally, getvirange is changed to use an active region instead of
getting a movement command. This makes the usual vi commands like
y, c, d etc work. This puts most of getvirange() in the else part of an
if statement. I'll reindent it separately later.

Oliver

diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index dc7e800..f5ff0a4 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -179,6 +179,7 @@
 "vi-yank", viyank, ZLE_LASTCOL
 "vi-yank-eol", viyankeol, 0
 "vi-yank-whole-line", viyankwholeline, 0
+"visual-mode", visualmode, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "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
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 3d4a9bb..d1bd5a1 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -446,9 +446,12 @@ killregion(UNUSED(char **args))
     if (mark > zlell)
 	mark = zlell;
     if (mark > zlecs)
-	forekill(mark - zlecs, CUT_RAW);
-    else
+	forekill(mark - zlecs + invicmdmode(), CUT_RAW);
+    else {
+	if (invicmdmode())
+	    INCCS();
 	backkill(zlecs - mark, CUT_FRONT|CUT_RAW);
+    }
     return 0;
 }
 
@@ -465,9 +468,9 @@ copyregionaskill(char **args)
 	if (mark > zlell)
 	    mark = zlell;
 	if (mark > zlecs)
-	    cut(zlecs, mark - zlecs, 0);
+	    cut(zlecs, mark - zlecs + invicmdmode(), 0);
 	else
-	    cut(mark, zlecs - mark, CUT_FRONT);
+	    cut(mark, zlecs - mark + invicmdmode(), CUT_FRONT);
     }
     return 0;
 }
@@ -963,7 +966,8 @@ quoteregion(UNUSED(char **args))
 	mark = zlecs;
 	zlecs = tmp;
     }
-    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) * ZLE_CHAR_SIZE);
+    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs + invicmdmode()) *
+	ZLE_CHAR_SIZE);
     ZS_memcpy(str, zleline + zlecs, len);
     foredel(len, CUT_RAW);
     str = makequote(str, &len);
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 35e4193..7b6420c 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -509,6 +509,24 @@ exchangepointandmark(UNUSED(char **args))
 
 /**/
 int
+visualmode(UNUSED(char **args))
+{
+    switch (region_active) {
+    case 1:
+	region_active = 0;
+	break;
+    case 0:
+	mark = zlecs;
+	/* fall through */
+    case 2:
+	region_active = 1;
+	break;
+    }
+    return 0;
+}
+
+/**/
+int
 vigotocolumn(UNUSED(char **args))
 {
     int x, y, n = zmult;
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 684ac13..ebc6b49 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1037,6 +1037,8 @@ zrefresh(void)
 	    region_highlights[0].start = mark;
 	    region_highlights[0].end = zlecs;
 	}
+	if (invicmdmode())
+	    INCPOS(region_highlights[0].end);
     } else {
 	region_highlights[0].start = region_highlights[0].end = -1;
     }
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 76c54ee..ba13de3 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -162,9 +162,14 @@ static int
 getvirange(int wf)
 {
     int pos = zlecs, mpos = mark, ret = 0;
+    int visual = region_active; /* don't trust movement cmd not to change it */
     int mult1 = zmult, hist1 = histline;
     Thingy k2;
 
+    if (visual) {
+	pos = mark;
+    } else {
+
     virangeflag = 1;
     wordflag = wf;
     mark = -1;
@@ -245,6 +250,7 @@ getvirange(int wf)
      * and use the mark. */
     if (mark != -1)
 	pos = mark;
+    }
     mark = mpos;
 
     /* Get the range the right way round.  zlecs is placed at the *
@@ -256,6 +262,11 @@ getvirange(int wf)
 	pos = tmp;
     }
 
+    if (visual && invicmdmode()) {
+	region_active = 0;
+	INCPOS(pos);
+    }
+
     /* Was it a line-oriented move?  If so, the command will have set *
      * the vilinerange flag.  In this case, entire lines are taken,   *
      * rather than just the sequence of characters delimited by pos   *
@@ -383,6 +394,10 @@ videletechar(char **args)
     int n = zmult;
 
     startvichange(-1);
+
+    if (region_active)
+	return killregion(args);
+
     /* handle negative argument */
     if (n < 0) {
 	int ret;
@@ -436,12 +451,16 @@ visubstitute(UNUSED(char **args))
     /* it is an error to be on the end of line */
     if (zlecs == zlell || zleline[zlecs] == '\n')
 	return 1;
-    /* Put argument into the acceptable range -- it is not an error to  *
-     * specify a greater count than the number of available characters. */
-    if (n > findeol() - zlecs)
-	n = findeol() - zlecs;
-    /* do the substitution */
-    forekill(n, CUT_RAW);
+    if (region_active) {
+	killregion(zlenoargs);
+    } else {
+	/* Put argument into the acceptable range -- it is not an error to  *
+	* specify a greater count than the number of available characters. */
+	if (n > findeol() - zlecs)
+	    n = findeol() - zlecs;
+	/* do the substitution */
+	forekill(n, CUT_RAW);
+    }
     startvitext(1);
     return 0;
 }
@@ -772,6 +791,10 @@ vibackwarddeletechar(char **args)
 
     if (invicmdmode())
 	startvichange(-1);
+
+    if (region_active)
+	return killregion(args);
+
     /* handle negative argument */
     if (n < 0) {
 	int ret;
@@ -813,12 +836,21 @@ vijoin(UNUSED(char **args))
 {
     int x, pos;
     int n = zmult;
+    int visual = region_active;
 
     startvichange(-1);
     if (n < 1)
 	return 1;
-    if ((x = findeol()) == zlell)
+    if (visual && zlecs > mark) {
+	exchangepointandmark(zlenoargs);
+	x = findeol();
+	if (x >= mark) {
+	    exchangepointandmark(zlenoargs);
+	    return 1;
+	}
+    } else if ((x = findeol()) == zlell || (visual && x >= mark))
 	return 1;
+
     while (n) {
 	zlecs = x + 1;
 	pos = zlecs;
@@ -836,7 +868,7 @@ vijoin(UNUSED(char **args))
 	}
 	spaceinline(1);
 	zleline[zlecs] = ZWC(' ');
-	if (--n < 2 || (x = findeol()) == zlell)
+	if ((!visual && --n < 2) || (x = findeol()) == zlell || (visual && x >= mark))
 	    return 0;
     }
     return 0;



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