[git commit] vi: allow motion count for change/delete/yank/shift

Denys Vlasenko vda.linux at googlemail.com
Mon Mar 29 10:16:21 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=1e84daf054113b97dad2d1201b8ec7fbebc9aeb3
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

The motion that determines the range of a change, delete, yank
or shift operation can have its own count.  Thus the commands
'5dd' and 'd5d' are equivalent:  both delete 5 lines.

When the command itself also has a count the two values are
multiplied.  Thus the command '2d3w' deletes 6 words and '2D3G'
deletes from the current line to line 6.

(When dealing with structured data it might make sense to think in
units of 3 words so '2d3w' is deleting 2 such units.  It doesn't
seem quite as sensible to express 'delete from current line to line 6'
as '2D3G' but vi permits it.)

function                                             old     new   delta
get_motion_char                                        -      68     +68
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/0 up/down: 68/0)               Total: 68 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/vi.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index 5d96c1575..4e1a2390f 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -1102,6 +1102,22 @@ static int get_one_char(void)
 # define get_one_char() readit()
 #endif
 
+// Get type of thing to operate on and adjust count
+static int get_motion_char(void)
+{
+	int c, cnt;
+
+	c = get_one_char();
+	if (c != '0' && isdigit(c)) {
+		// get any non-zero motion count
+		for (cnt = 0; isdigit(c); c = get_one_char())
+			cnt = cnt * 10 + (c - '0');
+		cmdcnt = (cmdcnt ?: 1) * cnt;
+	}
+
+	return c;
+}
+
 // Get input line (uses "status line" area)
 static char *get_input_line(const char *prompt)
 {
@@ -3532,7 +3548,7 @@ static void do_cmd(int c)
 	case '<':			// <- Left  shift something
 	case '>':			// >- Right shift something
 		cnt = count_lines(text, dot);	// remember what line we are on
-		c1 = get_one_char();	// get the type of thing to delete
+		c1 = get_motion_char();	// get the type of thing to operate on
 		find_range(&p, &q, c1);
 		yank_delete(p, q, WHOLE, YANKONLY, NO_UNDO);	// save copy before change
 		p = begin_line(p);
@@ -3778,7 +3794,7 @@ static void do_cmd(int c)
 #endif
 		c1 = 'y';
 		if (c != 'Y') {
-			c1 = get_one_char();	// get the type of thing to delete
+			c1 = get_motion_char(); // get the type of thing to operate on
 			if (c1 == 27)	// ESC- user changed mind and wants out
 				goto dc6;
 		}


More information about the busybox-cvs mailing list