diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-10 10:20:31 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-11 00:18:55 +0200 |
commit | b18c7bf702b2d7d967b2baf7d70fd8c408191eb4 (patch) | |
tree | a80485dce8f0a1ad2414daff33b36fb09cb7a89b | |
parent | e577afca7c94a7827bc216f4d8c95823d0f86489 (diff) | |
download | busybox-w32-b18c7bf702b2d7d967b2baf7d70fd8c408191eb4.tar.gz busybox-w32-b18c7bf702b2d7d967b2baf7d70fd8c408191eb4.tar.bz2 busybox-w32-b18c7bf702b2d7d967b2baf7d70fd8c408191eb4.zip |
vi: improvements to undo
The left shift operator ('<') didn't support undo at all; right
shift ('>') required changes to be undone separately for each line.
Allow both types of shift to be undone as a single operation.
Also, neither traditional vi nor vim yank the lines being shifted by
the '<' and '>' commands, so remove that call to yank_delete();
When a repetition count was specified for the '~', 'x', 'X' or 's'
commands the changes had to be undone one character at a time.
Allow undo as a single operation (though the delete and change
parts of the 's' command still have to be undone separately).
function old new delta
undo_push_insert 37 40 +3
do_cmd 4695 4663 -32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-32) Total: -29 bytes
v2: Don't break build when FEATURE_VI_UNDO is disabled. Don't reset
'undo_del' too early in '~' handling code. Code shrink '~'.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/editors/vi.c b/editors/vi.c index 7e89f58da..e752685d8 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -3213,6 +3213,10 @@ static void do_cmd(int c) | |||
3213 | int dir; | 3213 | int dir; |
3214 | int cnt, i, j; | 3214 | int cnt, i, j; |
3215 | int c1; | 3215 | int c1; |
3216 | #if ENABLE_FEATURE_VI_UNDO | ||
3217 | int allow_undo = ALLOW_UNDO; | ||
3218 | int undo_del = UNDO_DEL; | ||
3219 | #endif | ||
3216 | 3220 | ||
3217 | // c1 = c; // quiet the compiler | 3221 | // c1 = c; // quiet the compiler |
3218 | // cnt = yf = 0; // quiet the compiler | 3222 | // cnt = yf = 0; // quiet the compiler |
@@ -3614,24 +3618,29 @@ static void do_cmd(int c) | |||
3614 | cnt = count_lines(text, dot); // remember what line we are on | 3618 | cnt = count_lines(text, dot); // remember what line we are on |
3615 | if (find_range(&p, &q, c) == -1) | 3619 | if (find_range(&p, &q, c) == -1) |
3616 | goto dc6; | 3620 | goto dc6; |
3617 | yank_delete(p, q, WHOLE, YANKONLY, NO_UNDO); // save copy before change | ||
3618 | i = count_lines(p, q); // # of lines we are shifting | 3621 | i = count_lines(p, q); // # of lines we are shifting |
3619 | for ( ; i > 0; i--, p = next_line(p)) { | 3622 | for ( ; i > 0; i--, p = next_line(p)) { |
3620 | if (c == '<') { | 3623 | if (c == '<') { |
3621 | // shift left- remove tab or 8 spaces | 3624 | // shift left- remove tab or 8 spaces |
3622 | if (*p == '\t') { | 3625 | if (*p == '\t') { |
3623 | // shrink buffer 1 char | 3626 | // shrink buffer 1 char |
3624 | text_hole_delete(p, p, NO_UNDO); | 3627 | text_hole_delete(p, p, allow_undo); |
3625 | } else if (*p == ' ') { | 3628 | } else if (*p == ' ') { |
3626 | // we should be calculating columns, not just SPACE | 3629 | // we should be calculating columns, not just SPACE |
3627 | for (j = 0; *p == ' ' && j < tabstop; j++) { | 3630 | for (j = 0; *p == ' ' && j < tabstop; j++) { |
3628 | text_hole_delete(p, p, NO_UNDO); | 3631 | text_hole_delete(p, p, allow_undo); |
3632 | #if ENABLE_FEATURE_VI_UNDO | ||
3633 | allow_undo = ALLOW_UNDO_CHAIN; | ||
3634 | #endif | ||
3629 | } | 3635 | } |
3630 | } | 3636 | } |
3631 | } else if (c == '>') { | 3637 | } else /* if (c == '>') */ { |
3632 | // shift right -- add tab or 8 spaces | 3638 | // shift right -- add tab or 8 spaces |
3633 | char_insert(p, '\t', ALLOW_UNDO); | 3639 | char_insert(p, '\t', allow_undo); |
3634 | } | 3640 | } |
3641 | #if ENABLE_FEATURE_VI_UNDO | ||
3642 | allow_undo = ALLOW_UNDO_CHAIN; | ||
3643 | #endif | ||
3635 | } | 3644 | } |
3636 | dot = find_line(cnt); // what line were we on | 3645 | dot = find_line(cnt); // what line were we on |
3637 | dot_skip_over_ws(); | 3646 | dot_skip_over_ws(); |
@@ -3785,7 +3794,10 @@ static void do_cmd(int c) | |||
3785 | if (dot[dir] != '\n') { | 3794 | if (dot[dir] != '\n') { |
3786 | if (c == 'X') | 3795 | if (c == 'X') |
3787 | dot--; // delete prev char | 3796 | dot--; // delete prev char |
3788 | dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); // delete char | 3797 | dot = yank_delete(dot, dot, PARTIAL, YANKDEL, allow_undo); // delete char |
3798 | #if ENABLE_FEATURE_VI_UNDO | ||
3799 | allow_undo = ALLOW_UNDO_CHAIN; | ||
3800 | #endif | ||
3789 | } | 3801 | } |
3790 | } while (--cmdcnt > 0); | 3802 | } while (--cmdcnt > 0); |
3791 | end_cmd_q(); // stop adding to q | 3803 | end_cmd_q(); // stop adding to q |
@@ -3945,14 +3957,11 @@ static void do_cmd(int c) | |||
3945 | case '~': // ~- flip the case of letters a-z -> A-Z | 3957 | case '~': // ~- flip the case of letters a-z -> A-Z |
3946 | do { | 3958 | do { |
3947 | #if ENABLE_FEATURE_VI_UNDO | 3959 | #if ENABLE_FEATURE_VI_UNDO |
3948 | if (islower(*dot)) { | 3960 | if (isalpha(*dot)) { |
3949 | undo_push(dot, 1, UNDO_DEL); | 3961 | undo_push(dot, 1, undo_del); |
3950 | *dot = toupper(*dot); | 3962 | *dot = islower(*dot) ? toupper(*dot) : tolower(*dot); |
3951 | undo_push(dot, 1, UNDO_INS_CHAIN); | ||
3952 | } else if (isupper(*dot)) { | ||
3953 | undo_push(dot, 1, UNDO_DEL); | ||
3954 | *dot = tolower(*dot); | ||
3955 | undo_push(dot, 1, UNDO_INS_CHAIN); | 3963 | undo_push(dot, 1, UNDO_INS_CHAIN); |
3964 | undo_del = UNDO_DEL_CHAIN; | ||
3956 | } | 3965 | } |
3957 | #else | 3966 | #else |
3958 | if (islower(*dot)) { | 3967 | if (islower(*dot)) { |