aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-04-10 10:20:31 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-11 00:18:55 +0200
commitb18c7bf702b2d7d967b2baf7d70fd8c408191eb4 (patch)
treea80485dce8f0a1ad2414daff33b36fb09cb7a89b
parente577afca7c94a7827bc216f4d8c95823d0f86489 (diff)
downloadbusybox-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.c35
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)) {