diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-15 12:04:22 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-15 13:09:12 +0200 |
commit | 47c3eaa22f7bbdc1d397c3d29beae33139beecde (patch) | |
tree | ea58556dd1994fad4232a4028a760b8e6b4a9dac | |
parent | ac6495f6fbb97cb59ccd0a6744660346fd9b80b3 (diff) | |
download | busybox-w32-47c3eaa22f7bbdc1d397c3d29beae33139beecde.tar.gz busybox-w32-47c3eaa22f7bbdc1d397c3d29beae33139beecde.tar.bz2 busybox-w32-47c3eaa22f7bbdc1d397c3d29beae33139beecde.zip |
vi: correct autoindent for 'O' command
Opening a line above the current line with the 'O' command should
use the current, not previous, line to determine how much to
autoindent.
function old new delta
char_insert 531 563 +32
do_cmd 4746 4723 -23
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 32/-23) Total: 9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/editors/vi.c b/editors/vi.c index 0a82f9e38..b77406967 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -286,6 +286,7 @@ struct globals { | |||
286 | int text_size; // size of the allocated buffer | 286 | int text_size; // size of the allocated buffer |
287 | 287 | ||
288 | // the rest | 288 | // the rest |
289 | #if ENABLE_FEATURE_VI_SETOPTS | ||
289 | smallint vi_setops; // set by setops() | 290 | smallint vi_setops; // set by setops() |
290 | #define VI_AUTOINDENT (1 << 0) | 291 | #define VI_AUTOINDENT (1 << 0) |
291 | #define VI_ERR_METHOD (1 << 1) | 292 | #define VI_ERR_METHOD (1 << 1) |
@@ -296,6 +297,7 @@ struct globals { | |||
296 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash | 297 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash |
297 | #define ignorecase (vi_setops & VI_IGNORECASE) | 298 | #define ignorecase (vi_setops & VI_IGNORECASE) |
298 | #define showmatch (vi_setops & VI_SHOWMATCH ) | 299 | #define showmatch (vi_setops & VI_SHOWMATCH ) |
300 | #define openabove (vi_setops & VI_TABSTOP ) | ||
299 | // order of constants and strings must match | 301 | // order of constants and strings must match |
300 | #define OPTS_STR \ | 302 | #define OPTS_STR \ |
301 | "ai\0""autoindent\0" \ | 303 | "ai\0""autoindent\0" \ |
@@ -303,6 +305,15 @@ struct globals { | |||
303 | "ic\0""ignorecase\0" \ | 305 | "ic\0""ignorecase\0" \ |
304 | "sm\0""showmatch\0" \ | 306 | "sm\0""showmatch\0" \ |
305 | "ts\0""tabstop\0" | 307 | "ts\0""tabstop\0" |
308 | #define set_openabove() (vi_setops |= VI_TABSTOP) | ||
309 | #define clear_openabove() (vi_setops &= ~VI_TABSTOP) | ||
310 | #else | ||
311 | #define autoindent (0) | ||
312 | #define err_method (0) | ||
313 | #define openabove (0) | ||
314 | #define set_openabove() ((void)0) | ||
315 | #define clear_openabove() ((void)0) | ||
316 | #endif | ||
306 | 317 | ||
307 | #if ENABLE_FEATURE_VI_READONLY | 318 | #if ENABLE_FEATURE_VI_READONLY |
308 | smallint readonly_mode; | 319 | smallint readonly_mode; |
@@ -2130,8 +2141,13 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2130 | showmatching(p - 1); | 2141 | showmatching(p - 1); |
2131 | } | 2142 | } |
2132 | if (autoindent && c == '\n') { // auto indent the new line | 2143 | if (autoindent && c == '\n') { // auto indent the new line |
2133 | q = prev_line(p); // use prev line as template | 2144 | // use current/previous line as template |
2145 | q = openabove ? p : prev_line(p); | ||
2134 | len = strspn(q, " \t"); // space or tab | 2146 | len = strspn(q, " \t"); // space or tab |
2147 | if (openabove) { | ||
2148 | p--; // this replaces dot_prev() in do_cmd() | ||
2149 | q += len; // template will be shifted by text_hole_make() | ||
2150 | } | ||
2135 | if (len) { | 2151 | if (len) { |
2136 | uintptr_t bias; | 2152 | uintptr_t bias; |
2137 | bias = text_hole_make(p, len); | 2153 | bias = text_hole_make(p, len); |
@@ -2445,6 +2461,7 @@ static void setops(char *args, int flg_no) | |||
2445 | index = 1 << (index >> 1); // convert to VI_bit | 2461 | index = 1 << (index >> 1); // convert to VI_bit |
2446 | 2462 | ||
2447 | if (index & VI_TABSTOP) { | 2463 | if (index & VI_TABSTOP) { |
2464 | // don't set this bit in vi_setops, it's reused as 'openabove' | ||
2448 | int t; | 2465 | int t; |
2449 | if (!eq || flg_no) // no "=NNN" or it is "notabstop"? | 2466 | if (!eq || flg_no) // no "=NNN" or it is "notabstop"? |
2450 | goto bad; | 2467 | goto bad; |
@@ -3841,19 +3858,19 @@ static void do_cmd(int c) | |||
3841 | dot = next_line(dot); | 3858 | dot = next_line(dot); |
3842 | dot_skip_over_ws(); | 3859 | dot_skip_over_ws(); |
3843 | break; | 3860 | break; |
3844 | case 'O': // O- open a empty line above | 3861 | case 'O': // O- open an empty line above |
3845 | // 0i\n ESC -i | 3862 | dot_begin(); |
3846 | p = begin_line(dot); | 3863 | set_openabove(); |
3847 | if (p[-1] == '\n') { | 3864 | goto dc3; |
3865 | case 'o': // o- open an empty line below | ||
3866 | dot_end(); | ||
3867 | dc3: | ||
3868 | dot = char_insert(dot, '\n', ALLOW_UNDO); | ||
3869 | if (c == 'O' && !autoindent) { | ||
3870 | // done in char_insert() for openabove+autoindent | ||
3848 | dot_prev(); | 3871 | dot_prev(); |
3849 | case 'o': // o- open a empty line below; Yes, I know it is in the middle of the "if (..." | ||
3850 | dot_end(); | ||
3851 | dot = char_insert(dot, '\n', ALLOW_UNDO); | ||
3852 | } else { | ||
3853 | dot_begin(); // 0 | ||
3854 | dot = char_insert(dot, '\n', ALLOW_UNDO); // i\n ESC | ||
3855 | dot_prev(); // - | ||
3856 | } | 3872 | } |
3873 | clear_openabove(); | ||
3857 | goto dc_i; | 3874 | goto dc_i; |
3858 | break; | 3875 | break; |
3859 | case 'R': // R- continuous Replace char | 3876 | case 'R': // R- continuous Replace char |