From 6b6826f0b87b13c5e83786f045b90d703507464e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Jun 2021 01:08:48 +0200 Subject: *: --help tweaks function old new delta .rodata 103190 103189 -1 packed_usage 33590 33566 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-25) Total: -25 bytes Signed-off-by: Denys Vlasenko --- editors/vi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index d85cdd98d..beccef4b4 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -181,7 +181,7 @@ //kbuild:lib-$(CONFIG_VI) += vi.o //usage:#define vi_trivial_usage -//usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[FILE]..." +//usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[-H] [FILE]..." //usage:#define vi_full_usage "\n\n" //usage: "Edit FILE\n" //usage: IF_FEATURE_VI_COLON( @@ -191,6 +191,7 @@ //usage: "\n -R Read-only" //usage: ) //usage: "\n -H List available features" +// note: non-standard, "vim -H" is Hebrew mode (bidi support) #include "libbb.h" // Should be after libbb.h: on some systems regex.h needs sys/types.h: @@ -4748,7 +4749,11 @@ int vi_main(int argc, char **argv) initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN); } #endif - while ((c = getopt(argc, argv, "hCRH" IF_FEATURE_VI_COLON("c:"))) != -1) { + while ((c = getopt(argc, argv, +#if ENABLE_FEATURE_VI_CRASHME + "C" +#endif + "RHh" IF_FEATURE_VI_COLON("c:"))) != -1) { switch (c) { #if ENABLE_FEATURE_VI_CRASHME case 'C': -- cgit v1.2.3-55-g6feb From f7ed0e8ae0508fafe91ae3eb20663b9f7870adda Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 9 Jun 2021 16:11:03 +0100 Subject: vi: ':r' should insert text after current line When no line number is specified ':read' should place the inserted text after the current line, not before. This used to be correct but was broken when commit 0c42a6b07 (vi: fix empty line range regression) revealed a bug in commit 7a8ceb4eb (vi: changes to line addresses for colon commands). function old new delta colon 3960 3952 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8) Total: -8 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index beccef4b4..7c1877bb2 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2998,12 +2998,10 @@ static void colon(char *buf) status_line_bold("No current filename"); goto ret; } - if (e < 0) { // no addr given- read after current line - q = begin_line(dot); - } else if (e == 0) { // user said ":0r foo" + if (e == 0) { // user said ":0r foo" q = text; - } else { // addr given- read after that line - q = next_line(find_line(e)); + } else { // read after given line or current line if none given + q = next_line(e > 0 ? find_line(e) : dot); // read after last line if (q == end-1) ++q; -- cgit v1.2.3-55-g6feb From 52c4b7ac3bbc216cc5fd40cf150517f36e7bb87a Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 11 Jun 2021 13:22:25 +0100 Subject: vi: initialise tabstop once not for each file The default tabstop value should be set during early start up, not reset for each new file. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index 7c1877bb2..ba608fbd2 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -536,6 +536,7 @@ struct globals { last_modified_count = -1; \ /* "" but has space for 2 chars: */ \ IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ + tabstop = 8; \ } while (0) #if ENABLE_FEATURE_VI_CRASHME @@ -4619,7 +4620,6 @@ static void edit_file(char *fn) cmd_mode = 0; // 0=command 1=insert 2='R'eplace cmdcnt = 0; - tabstop = 8; offset = 0; // no horizontal offset c = '\0'; #if ENABLE_FEATURE_VI_DOT_CMD -- cgit v1.2.3-55-g6feb From f1d21b743485defb39fada03b27878efb1e2f7e3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 16 Jun 2021 14:45:10 +0100 Subject: vi: keep autoindent if line isn't empty When ESC is entered to leave insert mode any autoindent should only be removed if there's no content beyond the indent. This may be the case if a line has been split by entering insert mode and then entering a CR. Add a check to ensure there's only a newline after the indent. function old new delta char_insert 912 929 +17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 17/0) Total: 17 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index ba608fbd2..3daa0756b 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2147,7 +2147,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' #if ENABLE_FEATURE_VI_SETOPTS if (autoindent) { len = indent_len(bol); - if (len && get_column(bol + len) == indentcol) { + if (len && get_column(bol + len) == indentcol && bol[len] == '\n') { // remove autoindent from otherwise empty line text_hole_delete(bol, bol + len - 1, undo); p = bol; -- cgit v1.2.3-55-g6feb From ac04eb3657f99f6952971d8ceb8a82d73b783de8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 16 Jun 2021 14:46:01 +0100 Subject: vi: up/down motion beyond end of file should fail In traditional vi and vim line motion commands ('+'/'-'/'j'/'k') fail if the movement would exceed the bounds of the file. BusyBox vi allowed such commands to succeed, leaving the cursor on the first or last character of the file. Make BusyBox vi work like vi/vim. For the 'G'/'H'/'L' commands traditional vi treats an out of bounds result as an error, vim doesn't. BusyBox vi behaves like vim, both before and after this patch. function old new delta do_cmd 4785 4851 +66 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 66/0) Total: 66 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 63 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 25 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index 3daa0756b..231c62809 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -3635,24 +3635,30 @@ static void do_cmd(int c) case 10: // Newline ^J case 'j': // j- goto next line, same col case KEYCODE_DOWN: // cursor key Down + case 13: // Carriage Return ^M + case '+': // +- goto next line + q = dot; do { - dot_next(); // go to next B-o-l + p = next_line(q); + if (p == end_line(q)) { + indicate_error(); + goto dc1; + } + q = p; } while (--cmdcnt > 0); - // try to stay in saved column - dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); - keep_index = TRUE; + dot = q; + if (c == 13 || c == '+') { + dot_skip_over_ws(); + } else { + // try to stay in saved column + dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); + keep_index = TRUE; + } break; case 12: // ctrl-L force redraw whole screen case 18: // ctrl-R force redraw redraw(TRUE); // this will redraw the entire display break; - case 13: // Carriage Return ^M - case '+': // +- goto next line - do { - dot_next(); - } while (--cmdcnt > 0); - dot_skip_over_ws(); - break; case 21: // ctrl-U scroll up half screen dot_scroll((rows - 2) / 2, -1); break; @@ -3818,12 +3824,6 @@ static void do_cmd(int c) case ',': // ,- repeat latest search in opposite direction dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20); break; - case '-': // -- goto prev line - do { - dot_prev(); - } while (--cmdcnt > 0); - dot_skip_over_ws(); - break; #if ENABLE_FEATURE_VI_DOT_CMD case '.': // .- repeat the last modifying command // Stuff the last_modifying_cmd back into stdin @@ -4029,9 +4029,10 @@ static void do_cmd(int c) if (cmdcnt > (rows - 1)) { cmdcnt = (rows - 1); } - if (--cmdcnt > 0) { - do_cmd('+'); + while (--cmdcnt > 0) { + dot_next(); } + dot_begin(); dot_skip_over_ws(); break; case 'I': // I- insert before first non-blank @@ -4068,8 +4069,8 @@ static void do_cmd(int c) if (cmdcnt > (rows - 1)) { cmdcnt = (rows - 1); } - if (--cmdcnt > 0) { - do_cmd('-'); + while (--cmdcnt > 0) { + dot_prev(); } dot_begin(); dot_skip_over_ws(); @@ -4234,12 +4235,24 @@ static void do_cmd(int c) } case 'k': // k- goto prev line, same col case KEYCODE_UP: // cursor key Up + case '-': // -- goto prev line + q = dot; do { - dot_prev(); + p = prev_line(q); + if (p == begin_line(q)) { + indicate_error(); + goto dc1; + } + q = p; } while (--cmdcnt > 0); - // try to stay in saved column - dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); - keep_index = TRUE; + dot = q; + if (c == '-') { + dot_skip_over_ws(); + } else { + // try to stay in saved column + dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); + keep_index = TRUE; + } break; case 'r': // r- replace the current char with user input c1 = get_one_char(); // get the replacement char -- cgit v1.2.3-55-g6feb From 038d4007092f6d0d2dc107f31397c57e62751717 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 16 Jun 2021 14:47:00 +0100 Subject: 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 Signed-off-by: Denys Vlasenko --- editors/vi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'editors/vi.c') 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 -- cgit v1.2.3-55-g6feb From 51358757c709f9c489aa6b13b34141edf84183fa Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 21 Jun 2021 11:30:39 +0100 Subject: vi: fix backward search with GNU regex With FEATURE_VI_REGEX_SEARCH enabled backward searches don't work. This is problematic on distros that enable regexes, such as Tiny Core Linux and Fedora. When calling GNU re_search() with a negative range parameter (indicating a backward search) the start offset must be set to the end of the area being searched. The return value of re_search() is the offset of the matched pattern from the start of the area being searched. For a successful search (positive return value) char_search() can return the pointer to the start of the area plus the offset. FEATURE_VI_REGEX_SEARCH isn't enabled by default but when it is: function old new delta char_search 256 247 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes Signed-off-by: Andrey Dobrovolsky Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index b06270dfd..0baea615b 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2376,9 +2376,7 @@ static char *char_search(char *p, const char *pat, int dir_and_range) struct re_pattern_buffer preg; const char *err; char *q; - int i; - int size; - int range; + int i, size, range, start; re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; if (ignorecase) @@ -2403,31 +2401,26 @@ static char *char_search(char *p, const char *pat, int dir_and_range) // RANGE could be negative if we are searching backwards range = q - p; - q = p; - size = range; if (range < 0) { - size = -size; - q = p - size; - if (q < text) - q = text; + size = -range; + start = size; + } else { + size = range; + start = 0; } + q = p - start; + if (q < text) + q = text; // search for the compiled pattern, preg, in p[] - // range < 0: search backward - // range > 0: search forward - // 0 < start < size + // range < 0, start == size: search backward + // range > 0, start == 0: search forward // re_search() < 0: not found or error // re_search() >= 0: index of found pattern // struct pattern char int int int struct reg // re_search(*pattern_buffer, *string, size, start, range, *regs) - i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL); + i = re_search(&preg, q, size, start, range, /*struct re_registers*:*/ NULL); regfree(&preg); - if (i < 0) - return NULL; - if (dir_and_range > 0) // FORWARD? - p = p + i; - else - p = p - i; - return p; + return i < 0 ? NULL : q + i; } # else # if ENABLE_FEATURE_VI_SETOPTS -- cgit v1.2.3-55-g6feb From 5c89e5a04ec445fd0e7437918290bedc71a4ccad Mon Sep 17 00:00:00 2001 From: S Harris Date: Mon, 21 Jun 2021 11:04:49 +0100 Subject: vi: fix read outside of text buffer during insert Signed-off-by: S Harris Signed-off-by: Denys Vlasenko --- editors/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index 0baea615b..38ce1fdf0 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2144,7 +2144,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' cmdcnt = 0; end_cmd_q(); // stop adding to q last_status_cksum = 0; // force status update - if ((p[-1] != '\n') && (dot > text)) { + if ((dot > text) && (p[-1] != '\n')) { p--; } #if ENABLE_FEATURE_VI_SETOPTS -- cgit v1.2.3-55-g6feb From 5dbbd0a6f52befe6bc57baf97d39168e595197f1 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 25 Jun 2021 19:33:31 +0100 Subject: vi: stored search pattern applies to ':s' The same stored search pattern applies to both search ('/') and search/replace (':s') operations. A search/replace operation with an empty "find" string (':s//abc/') should use the last stored search pattern, if available, and issue an error message if there is none. If the "find" string is not empty it should replace the stored search pattern. function old new delta colon 3952 4024 +72 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 72/0) Total: 72 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index 38ce1fdf0..f0bbc9518 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -3100,6 +3100,18 @@ static void colon(char *buf) } len_R = strlen(R); + if (len_F) { // save "find" as last search pattern + free(last_search_pattern); + last_search_pattern = xstrdup(F - 1); + last_search_pattern[0] = '/'; + } else if (last_search_pattern[1] == '\0') { + status_line_bold("No previous search"); + goto ret; + } else { + F = last_search_pattern + 1; + len_F = strlen(F); + } + if (e < 0) { // no addr given q = begin_line(dot); // start with cur line r = end_line(dot); -- cgit v1.2.3-55-g6feb