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 <[email protected]>
---
 editors/vi.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

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
-- 
2.31.1

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to