diff options
author | Ron Yorston <rmy@pobox.com> | 2021-06-16 14:47:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-16 23:53:03 +0200 |
commit | 038d4007092f6d0d2dc107f31397c57e62751717 (patch) | |
tree | f77d354026e4aefb9f7362e43e8aca5a3d4fbf0d | |
parent | ac04eb3657f99f6952971d8ceb8a82d73b783de8 (diff) | |
download | busybox-w32-038d4007092f6d0d2dc107f31397c57e62751717.tar.gz busybox-w32-038d4007092f6d0d2dc107f31397c57e62751717.tar.bz2 busybox-w32-038d4007092f6d0d2dc107f31397c57e62751717.zip |
vi: reject change command when motion fails
If the motion command used to define the range of a change, yank or
delete fails the whole command should be rejected. BusyBox vi already
handled failed searches in these circumstances. Add some more cases:
- non-existent mark: d'x
- movement beyond end of file: c99999+ or 99999<<
This is implemented using a global variable which is set when a command
error is detected. Unlike the case of motion within a line it's
insufficient to check that the motion command doesn't move the cursor:
this fails to process 'LyL' correctly, for example, as the second 'L'
doesn't move the cursor.
function old new delta
indicate_error 75 82 +7
find_range 686 692 +6
do_cmd 4851 4852 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 14/0) Total: 14 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/editors/vi.c b/editors/vi.c index 231c62809..b06270dfd 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -378,6 +378,7 @@ struct globals { | |||
378 | #if ENABLE_FEATURE_VI_SETOPTS | 378 | #if ENABLE_FEATURE_VI_SETOPTS |
379 | int indentcol; // column of recently autoindent, 0 or -1 | 379 | int indentcol; // column of recently autoindent, 0 or -1 |
380 | #endif | 380 | #endif |
381 | smallint cmd_error; | ||
381 | 382 | ||
382 | // former statics | 383 | // former statics |
383 | #if ENABLE_FEATURE_VI_YANKMARK | 384 | #if ENABLE_FEATURE_VI_YANKMARK |
@@ -502,6 +503,7 @@ struct globals { | |||
502 | #define dotcnt (G.dotcnt ) | 503 | #define dotcnt (G.dotcnt ) |
503 | #define last_search_pattern (G.last_search_pattern) | 504 | #define last_search_pattern (G.last_search_pattern) |
504 | #define indentcol (G.indentcol ) | 505 | #define indentcol (G.indentcol ) |
506 | #define cmd_error (G.cmd_error ) | ||
505 | 507 | ||
506 | #define edit_file__cur_line (G.edit_file__cur_line) | 508 | #define edit_file__cur_line (G.edit_file__cur_line) |
507 | #define refresh__old_offset (G.refresh__old_offset) | 509 | #define refresh__old_offset (G.refresh__old_offset) |
@@ -1099,6 +1101,7 @@ static void indicate_error(void) | |||
1099 | if (crashme > 0) | 1101 | if (crashme > 0) |
1100 | return; | 1102 | return; |
1101 | #endif | 1103 | #endif |
1104 | cmd_error = TRUE; | ||
1102 | if (!err_method) { | 1105 | if (!err_method) { |
1103 | write1(ESC_BELL); | 1106 | write1(ESC_BELL); |
1104 | } else { | 1107 | } else { |
@@ -3399,8 +3402,11 @@ static int find_range(char **start, char **stop, int cmd) | |||
3399 | #endif | 3402 | #endif |
3400 | // these cmds operate on whole lines | 3403 | // these cmds operate on whole lines |
3401 | buftype = WHOLE; | 3404 | buftype = WHOLE; |
3402 | if (--cmdcnt > 0) | 3405 | if (--cmdcnt > 0) { |
3403 | do_cmd('j'); | 3406 | do_cmd('j'); |
3407 | if (cmd_error) | ||
3408 | buftype = -1; | ||
3409 | } | ||
3404 | } else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) { | 3410 | } else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) { |
3405 | // Most operate on char positions within a line. Of those that | 3411 | // Most operate on char positions within a line. Of those that |
3406 | // don't '%' needs no special treatment, search commands are | 3412 | // don't '%' needs no special treatment, search commands are |
@@ -3430,6 +3436,8 @@ static int find_range(char **start, char **stop, int cmd) | |||
3430 | // these operate on whole lines | 3436 | // these operate on whole lines |
3431 | buftype = WHOLE; | 3437 | buftype = WHOLE; |
3432 | do_cmd(c); // execute movement cmd | 3438 | do_cmd(c); // execute movement cmd |
3439 | if (cmd_error) | ||
3440 | buftype = -1; | ||
3433 | } else if (c == ' ' || c == 'l') { | 3441 | } else if (c == ' ' || c == 'l') { |
3434 | // forward motion by character | 3442 | // forward motion by character |
3435 | int tmpcnt = (cmdcnt ?: 1); | 3443 | int tmpcnt = (cmdcnt ?: 1); |
@@ -3515,6 +3523,7 @@ static void do_cmd(int c) | |||
3515 | // p = q = save_dot = buf; // quiet the compiler | 3523 | // p = q = save_dot = buf; // quiet the compiler |
3516 | memset(buf, '\0', sizeof(buf)); | 3524 | memset(buf, '\0', sizeof(buf)); |
3517 | keep_index = FALSE; | 3525 | keep_index = FALSE; |
3526 | cmd_error = FALSE; | ||
3518 | 3527 | ||
3519 | show_status_line(); | 3528 | show_status_line(); |
3520 | 3529 | ||
@@ -3699,6 +3708,8 @@ static void do_cmd(int c) | |||
3699 | dot = q; | 3708 | dot = q; |
3700 | dot_begin(); // go to B-o-l | 3709 | dot_begin(); // go to B-o-l |
3701 | dot_skip_over_ws(); | 3710 | dot_skip_over_ws(); |
3711 | } else { | ||
3712 | indicate_error(); | ||
3702 | } | 3713 | } |
3703 | } else if (c1 == '\'') { // goto previous context | 3714 | } else if (c1 == '\'') { // goto previous context |
3704 | dot = swap_context(dot); // swap current and previous context | 3715 | dot = swap_context(dot); // swap current and previous context |