aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-06-28 07:46:32 +0100
committerRon Yorston <rmy@pobox.com>2021-06-28 07:46:32 +0100
commite1ad66c0b8fd58a7158d40771175a7dab224202d (patch)
tree959d687eee9637151ad5798322586174de331141 /editors/vi.c
parent0fdf99bee07b6c38795eb5415b5e337ab82cfba8 (diff)
parent5dbbd0a6f52befe6bc57baf97d39168e595197f1 (diff)
downloadbusybox-w32-e1ad66c0b8fd58a7158d40771175a7dab224202d.tar.gz
busybox-w32-e1ad66c0b8fd58a7158d40771175a7dab224202d.tar.bz2
busybox-w32-e1ad66c0b8fd58a7158d40771175a7dab224202d.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c144
1 files changed, 88 insertions, 56 deletions
diff --git a/editors/vi.c b/editors/vi.c
index a4d6b21b4..89c567f10 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -181,7 +181,7 @@
181//kbuild:lib-$(CONFIG_VI) += vi.o 181//kbuild:lib-$(CONFIG_VI) += vi.o
182 182
183//usage:#define vi_trivial_usage 183//usage:#define vi_trivial_usage
184//usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[FILE]..." 184//usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[-H] [FILE]..."
185//usage:#define vi_full_usage "\n\n" 185//usage:#define vi_full_usage "\n\n"
186//usage: "Edit FILE\n" 186//usage: "Edit FILE\n"
187//usage: IF_FEATURE_VI_COLON( 187//usage: IF_FEATURE_VI_COLON(
@@ -191,6 +191,7 @@
191//usage: "\n -R Read-only" 191//usage: "\n -R Read-only"
192//usage: ) 192//usage: )
193//usage: "\n -H List available features" 193//usage: "\n -H List available features"
194// note: non-standard, "vim -H" is Hebrew mode (bidi support)
194 195
195#include "libbb.h" 196#include "libbb.h"
196// Should be after libbb.h: on some systems regex.h needs sys/types.h: 197// Should be after libbb.h: on some systems regex.h needs sys/types.h:
@@ -377,6 +378,7 @@ struct globals {
377#if ENABLE_FEATURE_VI_SETOPTS 378#if ENABLE_FEATURE_VI_SETOPTS
378 int indentcol; // column of recently autoindent, 0 or -1 379 int indentcol; // column of recently autoindent, 0 or -1
379#endif 380#endif
381 smallint cmd_error;
380 382
381 // former statics 383 // former statics
382#if ENABLE_FEATURE_VI_YANKMARK 384#if ENABLE_FEATURE_VI_YANKMARK
@@ -503,6 +505,7 @@ struct globals {
503#define dotcnt (G.dotcnt ) 505#define dotcnt (G.dotcnt )
504#define last_search_pattern (G.last_search_pattern) 506#define last_search_pattern (G.last_search_pattern)
505#define indentcol (G.indentcol ) 507#define indentcol (G.indentcol )
508#define cmd_error (G.cmd_error )
506 509
507#define edit_file__cur_line (G.edit_file__cur_line) 510#define edit_file__cur_line (G.edit_file__cur_line)
508#define refresh__old_offset (G.refresh__old_offset) 511#define refresh__old_offset (G.refresh__old_offset)
@@ -537,6 +540,7 @@ struct globals {
537 last_modified_count = -1; \ 540 last_modified_count = -1; \
538 /* "" but has space for 2 chars: */ \ 541 /* "" but has space for 2 chars: */ \
539 IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ 542 IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
543 tabstop = 8; \
540} while (0) 544} while (0)
541 545
542#if ENABLE_FEATURE_VI_CRASHME 546#if ENABLE_FEATURE_VI_CRASHME
@@ -1122,6 +1126,7 @@ static void indicate_error(void)
1122 if (crashme > 0) 1126 if (crashme > 0)
1123 return; 1127 return;
1124#endif 1128#endif
1129 cmd_error = TRUE;
1125 if (!err_method) { 1130 if (!err_method) {
1126 write1(ESC_BELL); 1131 write1(ESC_BELL);
1127 } else { 1132 } else {
@@ -2191,13 +2196,13 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2191 cmdcnt = 0; 2196 cmdcnt = 0;
2192 end_cmd_q(); // stop adding to q 2197 end_cmd_q(); // stop adding to q
2193 last_status_cksum = 0; // force status update 2198 last_status_cksum = 0; // force status update
2194 if ((p[-1] != '\n') && (dot > text)) { 2199 if ((dot > text) && (p[-1] != '\n')) {
2195 p--; 2200 p--;
2196 } 2201 }
2197#if ENABLE_FEATURE_VI_SETOPTS 2202#if ENABLE_FEATURE_VI_SETOPTS
2198 if (autoindent) { 2203 if (autoindent) {
2199 len = indent_len(bol); 2204 len = indent_len(bol);
2200 if (len && get_column(bol + len) == indentcol) { 2205 if (len && get_column(bol + len) == indentcol && bol[len] == '\n') {
2201 // remove autoindent from otherwise empty line 2206 // remove autoindent from otherwise empty line
2202 text_hole_delete(bol, bol + len - 1, undo); 2207 text_hole_delete(bol, bol + len - 1, undo);
2203 p = bol; 2208 p = bol;
@@ -2437,9 +2442,7 @@ static char *char_search(char *p, const char *pat, int dir_and_range)
2437 struct re_pattern_buffer preg; 2442 struct re_pattern_buffer preg;
2438 const char *err; 2443 const char *err;
2439 char *q; 2444 char *q;
2440 int i; 2445 int i, size, range, start;
2441 int size;
2442 int range;
2443 2446
2444 re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; 2447 re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
2445 if (ignorecase) 2448 if (ignorecase)
@@ -2464,31 +2467,26 @@ static char *char_search(char *p, const char *pat, int dir_and_range)
2464 2467
2465 // RANGE could be negative if we are searching backwards 2468 // RANGE could be negative if we are searching backwards
2466 range = q - p; 2469 range = q - p;
2467 q = p;
2468 size = range;
2469 if (range < 0) { 2470 if (range < 0) {
2470 size = -size; 2471 size = -range;
2471 q = p - size; 2472 start = size;
2472 if (q < text) 2473 } else {
2473 q = text; 2474 size = range;
2475 start = 0;
2474 } 2476 }
2477 q = p - start;
2478 if (q < text)
2479 q = text;
2475 // search for the compiled pattern, preg, in p[] 2480 // search for the compiled pattern, preg, in p[]
2476 // range < 0: search backward 2481 // range < 0, start == size: search backward
2477 // range > 0: search forward 2482 // range > 0, start == 0: search forward
2478 // 0 < start < size
2479 // re_search() < 0: not found or error 2483 // re_search() < 0: not found or error
2480 // re_search() >= 0: index of found pattern 2484 // re_search() >= 0: index of found pattern
2481 // struct pattern char int int int struct reg 2485 // struct pattern char int int int struct reg
2482 // re_search(*pattern_buffer, *string, size, start, range, *regs) 2486 // re_search(*pattern_buffer, *string, size, start, range, *regs)
2483 i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL); 2487 i = re_search(&preg, q, size, start, range, /*struct re_registers*:*/ NULL);
2484 regfree(&preg); 2488 regfree(&preg);
2485 if (i < 0) 2489 return i < 0 ? NULL : q + i;
2486 return NULL;
2487 if (dir_and_range > 0) // FORWARD?
2488 p = p + i;
2489 else
2490 p = p - i;
2491 return p;
2492} 2490}
2493# else 2491# else
2494# if ENABLE_FEATURE_VI_SETOPTS 2492# if ENABLE_FEATURE_VI_SETOPTS
@@ -3063,12 +3061,10 @@ static void colon(char *buf)
3063 status_line_bold("No current filename"); 3061 status_line_bold("No current filename");
3064 goto ret; 3062 goto ret;
3065 } 3063 }
3066 if (e < 0) { // no addr given- read after current line 3064 if (e == 0) { // user said ":0r foo"
3067 q = begin_line(dot);
3068 } else if (e == 0) { // user said ":0r foo"
3069 q = text; 3065 q = text;
3070 } else { // addr given- read after that line 3066 } else { // read after given line or current line if none given
3071 q = next_line(find_line(e)); 3067 q = next_line(e > 0 ? find_line(e) : dot);
3072 // read after last line 3068 // read after last line
3073 if (q == end-1) 3069 if (q == end-1)
3074 ++q; 3070 ++q;
@@ -3170,6 +3166,18 @@ static void colon(char *buf)
3170 } 3166 }
3171 len_R = strlen(R); 3167 len_R = strlen(R);
3172 3168
3169 if (len_F) { // save "find" as last search pattern
3170 free(last_search_pattern);
3171 last_search_pattern = xstrdup(F - 1);
3172 last_search_pattern[0] = '/';
3173 } else if (last_search_pattern[1] == '\0') {
3174 status_line_bold("No previous search");
3175 goto ret;
3176 } else {
3177 F = last_search_pattern + 1;
3178 len_F = strlen(F);
3179 }
3180
3173 if (e < 0) { // no addr given 3181 if (e < 0) { // no addr given
3174 q = begin_line(dot); // start with cur line 3182 q = begin_line(dot); // start with cur line
3175 r = end_line(dot); 3183 r = end_line(dot);
@@ -3465,8 +3473,11 @@ static int find_range(char **start, char **stop, int cmd)
3465#endif 3473#endif
3466 // these cmds operate on whole lines 3474 // these cmds operate on whole lines
3467 buftype = WHOLE; 3475 buftype = WHOLE;
3468 if (--cmdcnt > 0) 3476 if (--cmdcnt > 0) {
3469 do_cmd('j'); 3477 do_cmd('j');
3478 if (cmd_error)
3479 buftype = -1;
3480 }
3470 } else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) { 3481 } else if (strchr("^%$0bBeEfFtThnN/?|{}\b\177", c)) {
3471 // Most operate on char positions within a line. Of those that 3482 // Most operate on char positions within a line. Of those that
3472 // don't '%' needs no special treatment, search commands are 3483 // don't '%' needs no special treatment, search commands are
@@ -3496,6 +3507,8 @@ static int find_range(char **start, char **stop, int cmd)
3496 // these operate on whole lines 3507 // these operate on whole lines
3497 buftype = WHOLE; 3508 buftype = WHOLE;
3498 do_cmd(c); // execute movement cmd 3509 do_cmd(c); // execute movement cmd
3510 if (cmd_error)
3511 buftype = -1;
3499 } else if (c == ' ' || c == 'l') { 3512 } else if (c == ' ' || c == 'l') {
3500 // forward motion by character 3513 // forward motion by character
3501 int tmpcnt = (cmdcnt ?: 1); 3514 int tmpcnt = (cmdcnt ?: 1);
@@ -3581,6 +3594,7 @@ static void do_cmd(int c)
3581// p = q = save_dot = buf; // quiet the compiler 3594// p = q = save_dot = buf; // quiet the compiler
3582 memset(buf, '\0', sizeof(buf)); 3595 memset(buf, '\0', sizeof(buf));
3583 keep_index = FALSE; 3596 keep_index = FALSE;
3597 cmd_error = FALSE;
3584 3598
3585 show_status_line(); 3599 show_status_line();
3586 3600
@@ -3701,24 +3715,30 @@ static void do_cmd(int c)
3701 case 10: // Newline ^J 3715 case 10: // Newline ^J
3702 case 'j': // j- goto next line, same col 3716 case 'j': // j- goto next line, same col
3703 case KEYCODE_DOWN: // cursor key Down 3717 case KEYCODE_DOWN: // cursor key Down
3718 case 13: // Carriage Return ^M
3719 case '+': // +- goto next line
3720 q = dot;
3704 do { 3721 do {
3705 dot_next(); // go to next B-o-l 3722 p = next_line(q);
3723 if (p == end_line(q)) {
3724 indicate_error();
3725 goto dc1;
3726 }
3727 q = p;
3706 } while (--cmdcnt > 0); 3728 } while (--cmdcnt > 0);
3707 // try to stay in saved column 3729 dot = q;
3708 dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); 3730 if (c == 13 || c == '+') {
3709 keep_index = TRUE; 3731 dot_skip_over_ws();
3732 } else {
3733 // try to stay in saved column
3734 dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex);
3735 keep_index = TRUE;
3736 }
3710 break; 3737 break;
3711 case 12: // ctrl-L force redraw whole screen 3738 case 12: // ctrl-L force redraw whole screen
3712 case 18: // ctrl-R force redraw 3739 case 18: // ctrl-R force redraw
3713 redraw(TRUE); // this will redraw the entire display 3740 redraw(TRUE); // this will redraw the entire display
3714 break; 3741 break;
3715 case 13: // Carriage Return ^M
3716 case '+': // +- goto next line
3717 do {
3718 dot_next();
3719 } while (--cmdcnt > 0);
3720 dot_skip_over_ws();
3721 break;
3722 case 21: // ctrl-U scroll up half screen 3742 case 21: // ctrl-U scroll up half screen
3723 dot_scroll((rows - 2) / 2, -1); 3743 dot_scroll((rows - 2) / 2, -1);
3724 break; 3744 break;
@@ -3759,6 +3779,8 @@ static void do_cmd(int c)
3759 dot = q; 3779 dot = q;
3760 dot_begin(); // go to B-o-l 3780 dot_begin(); // go to B-o-l
3761 dot_skip_over_ws(); 3781 dot_skip_over_ws();
3782 } else {
3783 indicate_error();
3762 } 3784 }
3763 } else if (c1 == '\'') { // goto previous context 3785 } else if (c1 == '\'') { // goto previous context
3764 dot = swap_context(dot); // swap current and previous context 3786 dot = swap_context(dot); // swap current and previous context
@@ -3884,12 +3906,6 @@ static void do_cmd(int c)
3884 case ',': // ,- repeat latest search in opposite direction 3906 case ',': // ,- repeat latest search in opposite direction
3885 dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20); 3907 dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20);
3886 break; 3908 break;
3887 case '-': // -- goto prev line
3888 do {
3889 dot_prev();
3890 } while (--cmdcnt > 0);
3891 dot_skip_over_ws();
3892 break;
3893#if ENABLE_FEATURE_VI_DOT_CMD 3909#if ENABLE_FEATURE_VI_DOT_CMD
3894 case '.': // .- repeat the last modifying command 3910 case '.': // .- repeat the last modifying command
3895 // Stuff the last_modifying_cmd back into stdin 3911 // Stuff the last_modifying_cmd back into stdin
@@ -4095,9 +4111,10 @@ static void do_cmd(int c)
4095 if (cmdcnt > (rows - 1)) { 4111 if (cmdcnt > (rows - 1)) {
4096 cmdcnt = (rows - 1); 4112 cmdcnt = (rows - 1);
4097 } 4113 }
4098 if (--cmdcnt > 0) { 4114 while (--cmdcnt > 0) {
4099 do_cmd('+'); 4115 dot_next();
4100 } 4116 }
4117 dot_begin();
4101 dot_skip_over_ws(); 4118 dot_skip_over_ws();
4102 break; 4119 break;
4103 case 'I': // I- insert before first non-blank 4120 case 'I': // I- insert before first non-blank
@@ -4134,8 +4151,8 @@ static void do_cmd(int c)
4134 if (cmdcnt > (rows - 1)) { 4151 if (cmdcnt > (rows - 1)) {
4135 cmdcnt = (rows - 1); 4152 cmdcnt = (rows - 1);
4136 } 4153 }
4137 if (--cmdcnt > 0) { 4154 while (--cmdcnt > 0) {
4138 do_cmd('-'); 4155 dot_prev();
4139 } 4156 }
4140 dot_begin(); 4157 dot_begin();
4141 dot_skip_over_ws(); 4158 dot_skip_over_ws();
@@ -4300,12 +4317,24 @@ static void do_cmd(int c)
4300 } 4317 }
4301 case 'k': // k- goto prev line, same col 4318 case 'k': // k- goto prev line, same col
4302 case KEYCODE_UP: // cursor key Up 4319 case KEYCODE_UP: // cursor key Up
4320 case '-': // -- goto prev line
4321 q = dot;
4303 do { 4322 do {
4304 dot_prev(); 4323 p = prev_line(q);
4324 if (p == begin_line(q)) {
4325 indicate_error();
4326 goto dc1;
4327 }
4328 q = p;
4305 } while (--cmdcnt > 0); 4329 } while (--cmdcnt > 0);
4306 // try to stay in saved column 4330 dot = q;
4307 dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); 4331 if (c == '-') {
4308 keep_index = TRUE; 4332 dot_skip_over_ws();
4333 } else {
4334 // try to stay in saved column
4335 dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex);
4336 keep_index = TRUE;
4337 }
4309 break; 4338 break;
4310 case 'r': // r- replace the current char with user input 4339 case 'r': // r- replace the current char with user input
4311 c1 = get_one_char(); // get the replacement char 4340 c1 = get_one_char(); // get the replacement char
@@ -4686,7 +4715,6 @@ static void edit_file(char *fn)
4686 4715
4687 cmd_mode = 0; // 0=command 1=insert 2='R'eplace 4716 cmd_mode = 0; // 0=command 1=insert 2='R'eplace
4688 cmdcnt = 0; 4717 cmdcnt = 0;
4689 tabstop = 8;
4690 offset = 0; // no horizontal offset 4718 offset = 0; // no horizontal offset
4691 c = '\0'; 4719 c = '\0';
4692#if ENABLE_FEATURE_VI_DOT_CMD 4720#if ENABLE_FEATURE_VI_DOT_CMD
@@ -4814,7 +4842,11 @@ int vi_main(int argc, char **argv)
4814 initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN); 4842 initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN);
4815 } 4843 }
4816#endif 4844#endif
4817 while ((c = getopt(argc, argv, "hCRH" IF_FEATURE_VI_COLON("c:"))) != -1) { 4845 while ((c = getopt(argc, argv,
4846#if ENABLE_FEATURE_VI_CRASHME
4847 "C"
4848#endif
4849 "RHh" IF_FEATURE_VI_COLON("c:"))) != -1) {
4818 switch (c) { 4850 switch (c) {
4819#if ENABLE_FEATURE_VI_CRASHME 4851#if ENABLE_FEATURE_VI_CRASHME
4820 case 'C': 4852 case 'C':