zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: visual line mode
@ 2014-11-07 15:48 Oliver Kiddle
  2014-11-07 16:41 ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Oliver Kiddle @ 2014-11-07 15:48 UTC (permalink / raw)
  To: Zsh workers

This adds a linewise visual mode.

This uses a value of 2 for region_active which is exposed to the shell
function widgets via REGION_ACTIVE.

A visual-line-mode widget is added. We might need another one to just
set region_active to 0 which would be bound to escape in the visual
keymap.

There are also a few widgets: vichangeeol, viindent and viunindent that
should work linewise even for a character-wise selection.

There's an existing old bug with blank lines: dd on a blank line doesn't
work. It works in 3.0.8 but not in 4.2.1.

Oliver

diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index f5ff0a4..1dc0c9a 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -179,7 +179,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 d1bd5a1..5ee9f5a 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())
@@ -958,15 +990,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 7b6420c..fad6b0a 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 ebc6b49..f0351ad 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 ba13de3..a07ed61 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;
@@ -262,10 +264,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,   *
@@ -469,7 +469,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;
 }
@@ -727,8 +735,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;
@@ -758,8 +769,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;


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: visual line mode
  2014-11-07 15:48 PATCH: visual line mode Oliver Kiddle
@ 2014-11-07 16:41 ` Bart Schaefer
  2014-11-07 17:50   ` Oliver Kiddle
  0 siblings, 1 reply; 3+ messages in thread
From: Bart Schaefer @ 2014-11-07 16:41 UTC (permalink / raw)
  To: Zsh workers

On Nov 7,  4:48pm, Oliver Kiddle wrote:
}
} This adds a linewise visual mode.

If I ever knew what "visual mode" means in this context, I have managed
to forget it.  Could you remind me?


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: visual line mode
  2014-11-07 16:41 ` Bart Schaefer
@ 2014-11-07 17:50   ` Oliver Kiddle
  0 siblings, 0 replies; 3+ messages in thread
From: Oliver Kiddle @ 2014-11-07 17:50 UTC (permalink / raw)
  To: Zsh workers

Bart wrote:
> If I ever knew what "visual mode" means in this context, I have managed
> to forget it.  Could you remind me?

The visual mode is a vim feature analagous to the region in emacs or the
selection in typical MS Windows applications. The name "visual" probably
resulted from v being one of the few keys that vi doesn't use.

In vim, press v and then move the cursors (or hjkl if you prefer). Text
is highlighted. You can also extend the selection with other vi movement
commands: w, b, G etc. If you now press a normal vi operator: y for
yank, d for delete, c for change then instead of waiting for a movement
command, it will operate on the selected text.

The linewise mode selects only whole lines, by default bound to
uppercase V. Some text editors do something like this if you
double-click with the mouse. vim also has a blockwise mode for
rectangular selections.

Oliver


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-11-07 17:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-07 15:48 PATCH: visual line mode Oliver Kiddle
2014-11-07 16:41 ` Bart Schaefer
2014-11-07 17:50   ` Oliver Kiddle

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).