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) |
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 { #if ENABLE_FEATURE_VI_SETOPTS int indentcol; // column of recently autoindent, 0 or -1 #endif + smallint cmd_error; // former statics #if ENABLE_FEATURE_VI_YANKMARK @@ -502,6 +503,7 @@ struct globals { #define dotcnt (G.dotcnt ) #define last_search_pattern (G.last_search_pattern) #define indentcol (G.indentcol ) +#define cmd_error (G.cmd_error ) #define edit_file__cur_line (G.edit_file__cur_line) #define refresh__old_offset (G.refresh__old_offset) @@ -1099,6 +1101,7 @@ static void indicate_error(void) if (crashme > 0) return; #endif + cmd_error = TRUE; if (!err_method) { write1(ESC_BELL); } else { @@ -3399,8 +3402,11 @@ static int find_range(char **start, char **stop, int cmd) #endif // these cmds operate on whole lines buftype = WHOLE; - if (--cmdcnt > 0) + if (--cmdcnt > 0) { do_cmd('j'); + if (cmd_error) + buftype = -1; + } } else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) { // Most operate on char positions within a line. Of those that // don't '%' needs no special treatment, search commands are @@ -3430,6 +3436,8 @@ static int find_range(char **start, char **stop, int cmd) // these operate on whole lines buftype = WHOLE; do_cmd(c); // execute movement cmd + if (cmd_error) + buftype = -1; } else if (c == ' ' || c == 'l') { // forward motion by character int tmpcnt = (cmdcnt ?: 1); @@ -3515,6 +3523,7 @@ static void do_cmd(int c) // p = q = save_dot = buf; // quiet the compiler memset(buf, '\0', sizeof(buf)); keep_index = FALSE; + cmd_error = FALSE; show_status_line(); @@ -3699,6 +3708,8 @@ static void do_cmd(int c) dot = q; dot_begin(); // go to B-o-l dot_skip_over_ws(); + } else { + indicate_error(); } } else if (c1 == '\'') { // goto previous context dot = swap_context(dot); // swap current and previous context |