summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Src/Zle/iwidgets.list3
-rw-r--r--Src/Zle/zle_misc.c45
-rw-r--r--Src/Zle/zle_move.c19
-rw-r--r--Src/Zle/zle_refresh.c8
-rw-r--r--Src/Zle/zle_vi.c28
6 files changed, 96 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 7391f300c..e181b3852 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2014-11-17  Oliver Kiddle  <opk@zsh.org>
 
+	* 33636: Src/Zle/iwidgets.list, Src/Zle/zle_misc.c,
+	Src/Zle/zle_move.c, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c:
+	add support for a linewise visual selection mode
+
 	* 33635: Src/Zle/iwidgets.list, Src/Zle/zle_misc.c,
 	Src/Zle/zle_move.c, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c:
 	adapt region to function as vim style visual selection mode
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index 23e5783f9..26182974a 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -184,7 +184,8 @@
 "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
+"visual-line-mode", visuallinemode, ZLE_MENUCMP | ZLE_LASTCOL
+"visual-mode", visualmode, ZLE_MENUCMP | 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 5996c485d..a220a6bc8 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -440,12 +440,44 @@ killline(char **args)
 }
 
 /**/
+void
+regionlines(int *start, int *end)
+{
+    int origcs = zlecs;
+
+    UNMETACHECK();
+    if (zlecs < mark) {
+	*start = findbol();
+        zlecs = (mark > zlell) ? zlell : mark;
+	*end = findeol();
+    } else {
+	*end = findeol();
+        zlecs = mark;
+	*start = findbol();
+    }
+    zlecs = origcs;
+}
+
+/**/
 int
 killregion(UNUSED(char **args))
 {
     if (mark > zlell)
 	mark = zlell;
-    if (mark > zlecs)
+    if (region_active == 2) {
+	int a, b;
+	regionlines(&a, &b);
+	zlecs = a;
+	region_active = 0;
+	cut(zlecs, b - zlecs, CUT_RAW);
+	shiftchars(zlecs, b - zlecs);
+	if (zlell) {
+	    if (zlecs == zlell)
+		DECCS();
+	    foredel(1, 0);
+	    vifirstnonblank(zlenoargs);
+	}
+    } else if (mark > zlecs)
 	forekill(mark - zlecs + invicmdmode(), CUT_RAW);
     else {
 	if (invicmdmode())
@@ -1011,15 +1043,22 @@ quoteregion(UNUSED(char **args))
 {
     ZLE_STRING_T str;
     size_t len;
+    int extra = invicmdmode();
 
     if (mark > zlell)
 	mark = zlell;
-    if (mark < zlecs) {
+    if (region_active == 2) {
+	int a, b;
+	regionlines(&a, &b);
+	zlecs = a;
+	mark = b;
+	extra = 0;
+    } else if (mark < zlecs) {
 	int tmp = mark;
 	mark = zlecs;
 	zlecs = tmp;
     }
-    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs + invicmdmode()) *
+    str = (ZLE_STRING_T)hcalloc((len = mark - zlecs + extra) *
 	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 7b6420c06..fad6b0a5f 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -527,6 +527,25 @@ visualmode(UNUSED(char **args))
 
 /**/
 int
+visuallinemode(UNUSED(char **args))
+{
+    switch (region_active) {
+    case 2:
+	region_active = 0;
+	break;
+    case 0:
+	mark = zlecs;
+	/* fall through */
+    case 1:
+	region_active = 2;
+	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 ebc6b494c..f0351ad15 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1039,6 +1039,14 @@ zrefresh(void)
 	}
 	if (invicmdmode())
 	    INCPOS(region_highlights[0].end);
+	if (region_active == 2) {
+	    int origcs = zlecs;
+	    zlecs = region_highlights[0].end;
+	    region_highlights[0].end = findeol();
+	    zlecs = region_highlights[0].start;
+	    region_highlights[0].start = findbol();
+	    zlecs = origcs;
+	}
     } 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 02877deee..3a4304ced 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -162,12 +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 visual = region_active; /* movement command might set it */
     int mult1 = zmult, hist1 = histline;
     Thingy k2;
 
     if (visual) {
 	pos = mark;
+	vilinerange = (visual == 2);
+	region_active = 0;
     } else {
 
     virangeflag = 1;
@@ -256,10 +258,8 @@ getvirange(int wf)
 	pos = tmp;
     }
 
-    if (visual && invicmdmode()) {
-	region_active = 0;
+    if (visual && invicmdmode())
 	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,   *
@@ -463,7 +463,15 @@ visubstitute(UNUSED(char **args))
 int
 vichangeeol(UNUSED(char **args))
 {
-    forekill(findeol() - zlecs, CUT_RAW);
+    int a, b;
+    if (region_active) {
+	regionlines(&a, &b);
+	zlecs = a;
+	region_active = 0;
+	cut(zlecs, b - zlecs, CUT_RAW);
+	shiftchars(zlecs, b - zlecs);
+    } else
+	forekill(findeol() - zlecs, CUT_RAW);
     startvitext(1);
     return 0;
 }
@@ -721,8 +729,11 @@ viindent(UNUSED(char **args))
 {
     int oldcs = zlecs, c2;
 
-    /* get the range */
     startvichange(1);
+    /* force line range */
+    if (region_active == 1)
+	region_active = 2;
+    /* get the range */
     if ((c2 = getvirange(0)) == -1) {
 	vichgflag = 0;
 	return 1;
@@ -756,8 +767,11 @@ viunindent(UNUSED(char **args))
 {
     int oldcs = zlecs, c2;
 
-    /* get the range */
     startvichange(1);
+    /* force line range */
+    if (region_active == 1)
+	region_active = 2;
+    /* get the range */
     if ((c2 = getvirange(0)) == -1) {
 	vichgflag = 0;
 	return 1;