aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-03-18 11:30:38 +0000
committerDenys Vlasenko <vda.linux@googlemail.com>2022-06-26 19:38:31 +0200
commit2617a5e4c600b4577b2c18f794701276e55da43b (patch)
treecb1b1e0065e87a01e5262b7763b9c8328ee1121b
parentaf3b585815de5af367995d6064d994394b46c928 (diff)
downloadbusybox-w32-2617a5e4c600b4577b2c18f794701276e55da43b.tar.gz
busybox-w32-2617a5e4c600b4577b2c18f794701276e55da43b.tar.bz2
busybox-w32-2617a5e4c600b4577b2c18f794701276e55da43b.zip
vi: handle autoindent in 'cc' command
When the 'cc' command is invoked with autoindent enabled it should use the indent of the first line being changed. The size of the indent has to be established before char_insert() is called as the lines being changed are deleted. Introduce a new global variable, newindent, to handle this. The indentcol global is now effectively a static variable in char_insert(). function old new delta do_cmd 4247 4308 +61 vi_main 416 422 +6 char_insert 891 875 -16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 67/-16) Total: 51 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/vi.c71
1 files changed, 47 insertions, 24 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 5b86b0516..d799a8170 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -380,7 +380,9 @@ struct globals {
380 char *last_search_pattern; // last pattern from a '/' or '?' search 380 char *last_search_pattern; // last pattern from a '/' or '?' search
381#endif 381#endif
382#if ENABLE_FEATURE_VI_SETOPTS 382#if ENABLE_FEATURE_VI_SETOPTS
383 int indentcol; // column of recently autoindent, 0 or -1 383 int char_insert__indentcol; // column of recent autoindent or 0
384 int newindent; // autoindent value for 'O'/'cc' commands
385 // or -1 to use indent from previous line
384#endif 386#endif
385 smallint cmd_error; 387 smallint cmd_error;
386 388
@@ -507,7 +509,8 @@ struct globals {
507#define ioq_start (G.ioq_start ) 509#define ioq_start (G.ioq_start )
508#define dotcnt (G.dotcnt ) 510#define dotcnt (G.dotcnt )
509#define last_search_pattern (G.last_search_pattern) 511#define last_search_pattern (G.last_search_pattern)
510#define indentcol (G.indentcol ) 512#define char_insert__indentcol (G.char_insert__indentcol)
513#define newindent (G.newindent )
511#define cmd_error (G.cmd_error ) 514#define cmd_error (G.cmd_error )
512 515
513#define edit_file__cur_line (G.edit_file__cur_line) 516#define edit_file__cur_line (G.edit_file__cur_line)
@@ -540,10 +543,11 @@ struct globals {
540 543
541#define INIT_G() do { \ 544#define INIT_G() do { \
542 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 545 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
543 last_modified_count = -1; \ 546 last_modified_count--; \
544 /* "" but has space for 2 chars: */ \ 547 /* "" but has space for 2 chars: */ \
545 IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ 548 IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
546 tabstop = 8; \ 549 tabstop = 8; \
550 IF_FEATURE_VI_SETOPTS(newindent--;) \
547} while (0) 551} while (0)
548 552
549#if ENABLE_FEATURE_VI_CRASHME 553#if ENABLE_FEATURE_VI_CRASHME
@@ -2113,6 +2117,7 @@ static size_t indent_len(char *p)
2113static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' 2117static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2114{ 2118{
2115#if ENABLE_FEATURE_VI_SETOPTS 2119#if ENABLE_FEATURE_VI_SETOPTS
2120# define indentcol char_insert__indentcol
2116 size_t len; 2121 size_t len;
2117 int col, ntab, nspc; 2122 int col, ntab, nspc;
2118#endif 2123#endif
@@ -2141,7 +2146,8 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2141#if ENABLE_FEATURE_VI_SETOPTS 2146#if ENABLE_FEATURE_VI_SETOPTS
2142 if (autoindent) { 2147 if (autoindent) {
2143 len = indent_len(bol); 2148 len = indent_len(bol);
2144 if (len && get_column(bol + len) == indentcol && bol[len] == '\n') { 2149 col = get_column(bol + len);
2150 if (len && col == indentcol && bol[len] == '\n') {
2145 // remove autoindent from otherwise empty line 2151 // remove autoindent from otherwise empty line
2146 text_hole_delete(bol, bol + len - 1, undo); 2152 text_hole_delete(bol, bol + len - 1, undo);
2147 p = bol; 2153 p = bol;
@@ -2210,26 +2216,30 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2210 showmatching(p - 1); 2216 showmatching(p - 1);
2211 } 2217 }
2212 if (autoindent && c == '\n') { // auto indent the new line 2218 if (autoindent && c == '\n') { // auto indent the new line
2213 // use indent of current/previous line 2219 if (newindent < 0) {
2214 bol = indentcol < 0 ? p : prev_line(p); 2220 // use indent of previous line
2215 len = indent_len(bol); 2221 bol = prev_line(p);
2216 col = get_column(bol + len); 2222 len = indent_len(bol);
2217 2223 col = get_column(bol + len);
2218 if (len && col == indentcol) { 2224
2219 // previous line was empty except for autoindent 2225 if (len && col == indentcol) {
2220 // move the indent to the current line 2226 // previous line was empty except for autoindent
2221 memmove(bol + 1, bol, len); 2227 // move the indent to the current line
2222 *bol = '\n'; 2228 memmove(bol + 1, bol, len);
2223 return p; 2229 *bol = '\n';
2230 return p;
2231 }
2232 } else {
2233 // for 'O'/'cc' commands add indent before newly inserted NL
2234 if (p != end - 1) // but not for 'cc' at EOF
2235 p--;
2236 col = newindent;
2224 } 2237 }
2225 2238
2226 if (indentcol < 0) 2239 if (col) {
2227 p--; // open above, indent before newly inserted NL
2228
2229 if (len) {
2230 // only record indent if in insert/replace mode or for 2240 // only record indent if in insert/replace mode or for
2231 // the 'o'/'O' commands, which are switched to insert 2241 // the 'o'/'O'/'cc' commands, which are switched to
2232 // mode early. 2242 // insert mode early.
2233 indentcol = cmd_mode != 0 ? col : 0; 2243 indentcol = cmd_mode != 0 ? col : 0;
2234 if (expandtab) { 2244 if (expandtab) {
2235 ntab = 0; 2245 ntab = 0;
@@ -2252,6 +2262,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2252 } 2262 }
2253#if ENABLE_FEATURE_VI_SETOPTS 2263#if ENABLE_FEATURE_VI_SETOPTS
2254 indentcol = 0; 2264 indentcol = 0;
2265# undef indentcol
2255#endif 2266#endif
2256 return p; 2267 return p;
2257} 2268}
@@ -4220,6 +4231,9 @@ static void do_cmd(int c)
4220 case 'i': // i- insert before current char 4231 case 'i': // i- insert before current char
4221 case KEYCODE_INSERT: // Cursor Key Insert 4232 case KEYCODE_INSERT: // Cursor Key Insert
4222 dc_i: 4233 dc_i:
4234#if ENABLE_FEATURE_VI_SETOPTS
4235 newindent = -1;
4236#endif
4223 cmd_mode = 1; // start inserting 4237 cmd_mode = 1; // start inserting
4224 undo_queue_commit(); // commit queue when cmd_mode changes 4238 undo_queue_commit(); // commit queue when cmd_mode changes
4225 break; 4239 break;
@@ -4262,7 +4276,8 @@ static void do_cmd(int c)
4262 case 'O': // O- open an empty line above 4276 case 'O': // O- open an empty line above
4263 dot_begin(); 4277 dot_begin();
4264#if ENABLE_FEATURE_VI_SETOPTS 4278#if ENABLE_FEATURE_VI_SETOPTS
4265 indentcol = -1; 4279 // special case: use indent of current line
4280 newindent = get_column(dot + indent_len(dot));
4266#endif 4281#endif
4267 goto dc3; 4282 goto dc3;
4268 case 'o': // o- open an empty line below 4283 case 'o': // o- open an empty line below
@@ -4385,14 +4400,22 @@ static void do_cmd(int c)
4385 if (buftype == WHOLE) { 4400 if (buftype == WHOLE) {
4386 save_dot = p; // final cursor position is start of range 4401 save_dot = p; // final cursor position is start of range
4387 p = begin_line(p); 4402 p = begin_line(p);
4403#if ENABLE_FEATURE_VI_SETOPTS
4404 if (c == 'c') // special case: use indent of current line
4405 newindent = get_column(p + indent_len(p));
4406#endif
4388 q = end_line(q); 4407 q = end_line(q);
4389 } 4408 }
4390 dot = yank_delete(p, q, buftype, yf, ALLOW_UNDO); // delete word 4409 dot = yank_delete(p, q, buftype, yf, ALLOW_UNDO); // delete word
4391 if (buftype == WHOLE) { 4410 if (buftype == WHOLE) {
4392 if (c == 'c') { 4411 if (c == 'c') {
4412#if ENABLE_FEATURE_VI_SETOPTS
4413 cmd_mode = 1; // switch to insert mode early
4414#endif
4393 dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN); 4415 dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN);
4394 // on the last line of file don't move to prev line 4416 // on the last line of file don't move to prev line,
4395 if (dot != (end-1)) { 4417 // handled in char_insert() if autoindent is enabled
4418 if (dot != (end-1) && !autoindent) {
4396 dot_prev(); 4419 dot_prev();
4397 } 4420 }
4398 } else if (c == 'd') { 4421 } else if (c == 'd') {