diff options
author | Ron Yorston <rmy@pobox.com> | 2021-03-28 13:20:01 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-03-29 12:16:21 +0200 |
commit | 50a2db7dff696c0196fcc9a27db6154983bae149 (patch) | |
tree | 8c9805f5b29bf8e2567172a985ae270054ce0121 | |
parent | 18871c3f2b96e76269f5c5e4bbf102808b69bd42 (diff) | |
download | busybox-w32-50a2db7dff696c0196fcc9a27db6154983bae149.tar.gz busybox-w32-50a2db7dff696c0196fcc9a27db6154983bae149.tar.bz2 busybox-w32-50a2db7dff696c0196fcc9a27db6154983bae149.zip |
vi: remember cursor column during vertical motion
When the 'j'/'k' commands or up/down arrow keys are used to move
the cursor vertically 'vi' remembers the original cursor column
and positions the cursor there if possible. Also, if the '$'
command has been used to position the cursor at the end of a line
vertical movements keep the cursor at the end of the line.
Make BusyBox 'vi' do the same.
function old new delta
refresh 674 694 +20
do_cmd 4853 4861 +8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 28/0) Total: 28 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/editors/vi.c b/editors/vi.c index f4da38071..2c724a448 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -263,6 +263,8 @@ enum { | |||
263 | S_OVER_WS = 3, // used in skip_thing() for moving "dot" | 263 | S_OVER_WS = 3, // used in skip_thing() for moving "dot" |
264 | S_END_PUNCT = 4, // used in skip_thing() for moving "dot" | 264 | S_END_PUNCT = 4, // used in skip_thing() for moving "dot" |
265 | S_END_ALNUM = 5, // used in skip_thing() for moving "dot" | 265 | S_END_ALNUM = 5, // used in skip_thing() for moving "dot" |
266 | |||
267 | C_END = -1, // cursor is at end of line due to '$' command | ||
266 | }; | 268 | }; |
267 | 269 | ||
268 | 270 | ||
@@ -354,6 +356,8 @@ struct globals { | |||
354 | sigjmp_buf restart; // int_handler() jumps to location remembered here | 356 | sigjmp_buf restart; // int_handler() jumps to location remembered here |
355 | #endif | 357 | #endif |
356 | struct termios term_orig; // remember what the cooked mode was | 358 | struct termios term_orig; // remember what the cooked mode was |
359 | int cindex; // saved character index for up/down motion | ||
360 | smallint keep_index; // retain saved character index | ||
357 | #if ENABLE_FEATURE_VI_COLON | 361 | #if ENABLE_FEATURE_VI_COLON |
358 | char *initial_cmds[3]; // currently 2 entries, NULL terminated | 362 | char *initial_cmds[3]; // currently 2 entries, NULL terminated |
359 | #endif | 363 | #endif |
@@ -462,6 +466,8 @@ struct globals { | |||
462 | #define context_end (G.context_end ) | 466 | #define context_end (G.context_end ) |
463 | #define restart (G.restart ) | 467 | #define restart (G.restart ) |
464 | #define term_orig (G.term_orig ) | 468 | #define term_orig (G.term_orig ) |
469 | #define cindex (G.cindex ) | ||
470 | #define keep_index (G.keep_index ) | ||
465 | #define initial_cmds (G.initial_cmds ) | 471 | #define initial_cmds (G.initial_cmds ) |
466 | #define readbuffer (G.readbuffer ) | 472 | #define readbuffer (G.readbuffer ) |
467 | #define scr_out_buf (G.scr_out_buf ) | 473 | #define scr_out_buf (G.scr_out_buf ) |
@@ -992,6 +998,9 @@ static void refresh(int full_screen) | |||
992 | 998 | ||
993 | place_cursor(crow, ccol); | 999 | place_cursor(crow, ccol); |
994 | 1000 | ||
1001 | if (!keep_index) | ||
1002 | cindex = ccol + offset; | ||
1003 | |||
995 | old_offset = offset; | 1004 | old_offset = offset; |
996 | #undef old_offset | 1005 | #undef old_offset |
997 | } | 1006 | } |
@@ -3096,6 +3105,7 @@ static void do_cmd(int c) | |||
3096 | // cnt = yf = 0; // quiet the compiler | 3105 | // cnt = yf = 0; // quiet the compiler |
3097 | // p = q = save_dot = buf; // quiet the compiler | 3106 | // p = q = save_dot = buf; // quiet the compiler |
3098 | memset(buf, '\0', sizeof(buf)); | 3107 | memset(buf, '\0', sizeof(buf)); |
3108 | keep_index = FALSE; | ||
3099 | 3109 | ||
3100 | show_status_line(); | 3110 | show_status_line(); |
3101 | 3111 | ||
@@ -3220,9 +3230,10 @@ static void do_cmd(int c) | |||
3220 | case KEYCODE_DOWN: // cursor key Down | 3230 | case KEYCODE_DOWN: // cursor key Down |
3221 | do { | 3231 | do { |
3222 | dot_next(); // go to next B-o-l | 3232 | dot_next(); // go to next B-o-l |
3223 | // try stay in same col | ||
3224 | dot = move_to_col(dot, ccol + offset); | ||
3225 | } while (--cmdcnt > 0); | 3233 | } while (--cmdcnt > 0); |
3234 | // try to stay in saved column | ||
3235 | dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); | ||
3236 | keep_index = TRUE; | ||
3226 | break; | 3237 | break; |
3227 | case 12: // ctrl-L force redraw whole screen | 3238 | case 12: // ctrl-L force redraw whole screen |
3228 | case 18: // ctrl-R force redraw | 3239 | case 18: // ctrl-R force redraw |
@@ -3348,6 +3359,8 @@ static void do_cmd(int c) | |||
3348 | break; | 3359 | break; |
3349 | dot_next(); | 3360 | dot_next(); |
3350 | } | 3361 | } |
3362 | cindex = C_END; | ||
3363 | keep_index = TRUE; | ||
3351 | break; | 3364 | break; |
3352 | case '%': // %- find matching char of pair () [] {} | 3365 | case '%': // %- find matching char of pair () [] {} |
3353 | for (q = dot; q < end && *q != '\n'; q++) { | 3366 | for (q = dot; q < end && *q != '\n'; q++) { |
@@ -3827,8 +3840,10 @@ static void do_cmd(int c) | |||
3827 | case KEYCODE_UP: // cursor key Up | 3840 | case KEYCODE_UP: // cursor key Up |
3828 | do { | 3841 | do { |
3829 | dot_prev(); | 3842 | dot_prev(); |
3830 | dot = move_to_col(dot, ccol + offset); // try stay in same col | ||
3831 | } while (--cmdcnt > 0); | 3843 | } while (--cmdcnt > 0); |
3844 | // try to stay in saved column | ||
3845 | dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); | ||
3846 | keep_index = TRUE; | ||
3832 | break; | 3847 | break; |
3833 | case 'r': // r- replace the current char with user input | 3848 | case 'r': // r- replace the current char with user input |
3834 | c1 = get_one_char(); // get the replacement char | 3849 | c1 = get_one_char(); // get the replacement char |