aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-03-28 13:21:34 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-03-29 12:16:21 +0200
commit1e84daf054113b97dad2d1201b8ec7fbebc9aeb3 (patch)
treeb30495efb5a37331cabbad4c739ad8e33593dec3
parentd4c46037a6c595c42aab22b6910c56f5ccadb96e (diff)
downloadbusybox-w32-1e84daf054113b97dad2d1201b8ec7fbebc9aeb3.tar.gz
busybox-w32-1e84daf054113b97dad2d1201b8ec7fbebc9aeb3.tar.bz2
busybox-w32-1e84daf054113b97dad2d1201b8ec7fbebc9aeb3.zip
vi: allow motion count for change/delete/yank/shift
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@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/vi.c20
1 files 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)
1102# define get_one_char() readit() 1102# define get_one_char() readit()
1103#endif 1103#endif
1104 1104
1105// Get type of thing to operate on and adjust count
1106static int get_motion_char(void)
1107{
1108 int c, cnt;
1109
1110 c = get_one_char();
1111 if (c != '0' && isdigit(c)) {
1112 // get any non-zero motion count
1113 for (cnt = 0; isdigit(c); c = get_one_char())
1114 cnt = cnt * 10 + (c - '0');
1115 cmdcnt = (cmdcnt ?: 1) * cnt;
1116 }
1117
1118 return c;
1119}
1120
1105// Get input line (uses "status line" area) 1121// Get input line (uses "status line" area)
1106static char *get_input_line(const char *prompt) 1122static char *get_input_line(const char *prompt)
1107{ 1123{
@@ -3532,7 +3548,7 @@ static void do_cmd(int c)
3532 case '<': // <- Left shift something 3548 case '<': // <- Left shift something
3533 case '>': // >- Right shift something 3549 case '>': // >- Right shift something
3534 cnt = count_lines(text, dot); // remember what line we are on 3550 cnt = count_lines(text, dot); // remember what line we are on
3535 c1 = get_one_char(); // get the type of thing to delete 3551 c1 = get_motion_char(); // get the type of thing to operate on
3536 find_range(&p, &q, c1); 3552 find_range(&p, &q, c1);
3537 yank_delete(p, q, WHOLE, YANKONLY, NO_UNDO); // save copy before change 3553 yank_delete(p, q, WHOLE, YANKONLY, NO_UNDO); // save copy before change
3538 p = begin_line(p); 3554 p = begin_line(p);
@@ -3778,7 +3794,7 @@ static void do_cmd(int c)
3778#endif 3794#endif
3779 c1 = 'y'; 3795 c1 = 'y';
3780 if (c != 'Y') { 3796 if (c != 'Y') {
3781 c1 = get_one_char(); // get the type of thing to delete 3797 c1 = get_motion_char(); // get the type of thing to operate on
3782 if (c1 == 27) // ESC- user changed mind and wants out 3798 if (c1 == 27) // ESC- user changed mind and wants out
3783 goto dc6; 3799 goto dc6;
3784 } 3800 }