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>
This commit is contained in:
parent
e577afca7c
commit
b18c7bf702
35
editors/vi.c
35
editors/vi.c
@ -3213,6 +3213,10 @@ static void do_cmd(int c)
|
|||||||
int dir;
|
int dir;
|
||||||
int cnt, i, j;
|
int cnt, i, j;
|
||||||
int c1;
|
int c1;
|
||||||
|
#if ENABLE_FEATURE_VI_UNDO
|
||||||
|
int allow_undo = ALLOW_UNDO;
|
||||||
|
int undo_del = UNDO_DEL;
|
||||||
|
#endif
|
||||||
|
|
||||||
// c1 = c; // quiet the compiler
|
// c1 = c; // quiet the compiler
|
||||||
// cnt = yf = 0; // quiet the compiler
|
// cnt = yf = 0; // quiet the compiler
|
||||||
@ -3614,24 +3618,29 @@ static void do_cmd(int c)
|
|||||||
cnt = count_lines(text, dot); // remember what line we are on
|
cnt = count_lines(text, dot); // remember what line we are on
|
||||||
if (find_range(&p, &q, c) == -1)
|
if (find_range(&p, &q, c) == -1)
|
||||||
goto dc6;
|
goto dc6;
|
||||||
yank_delete(p, q, WHOLE, YANKONLY, NO_UNDO); // save copy before change
|
|
||||||
i = count_lines(p, q); // # of lines we are shifting
|
i = count_lines(p, q); // # of lines we are shifting
|
||||||
for ( ; i > 0; i--, p = next_line(p)) {
|
for ( ; i > 0; i--, p = next_line(p)) {
|
||||||
if (c == '<') {
|
if (c == '<') {
|
||||||
// shift left- remove tab or 8 spaces
|
// shift left- remove tab or 8 spaces
|
||||||
if (*p == '\t') {
|
if (*p == '\t') {
|
||||||
// shrink buffer 1 char
|
// shrink buffer 1 char
|
||||||
text_hole_delete(p, p, NO_UNDO);
|
text_hole_delete(p, p, allow_undo);
|
||||||
} else if (*p == ' ') {
|
} else if (*p == ' ') {
|
||||||
// we should be calculating columns, not just SPACE
|
// we should be calculating columns, not just SPACE
|
||||||
for (j = 0; *p == ' ' && j < tabstop; j++) {
|
for (j = 0; *p == ' ' && j < tabstop; j++) {
|
||||||
text_hole_delete(p, p, NO_UNDO);
|
text_hole_delete(p, p, allow_undo);
|
||||||
|
#if ENABLE_FEATURE_VI_UNDO
|
||||||
|
allow_undo = ALLOW_UNDO_CHAIN;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (c == '>') {
|
} else /* if (c == '>') */ {
|
||||||
// shift right -- add tab or 8 spaces
|
// shift right -- add tab or 8 spaces
|
||||||
char_insert(p, '\t', ALLOW_UNDO);
|
char_insert(p, '\t', allow_undo);
|
||||||
}
|
}
|
||||||
|
#if ENABLE_FEATURE_VI_UNDO
|
||||||
|
allow_undo = ALLOW_UNDO_CHAIN;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
dot = find_line(cnt); // what line were we on
|
dot = find_line(cnt); // what line were we on
|
||||||
dot_skip_over_ws();
|
dot_skip_over_ws();
|
||||||
@ -3785,7 +3794,10 @@ static void do_cmd(int c)
|
|||||||
if (dot[dir] != '\n') {
|
if (dot[dir] != '\n') {
|
||||||
if (c == 'X')
|
if (c == 'X')
|
||||||
dot--; // delete prev char
|
dot--; // delete prev char
|
||||||
dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); // delete char
|
dot = yank_delete(dot, dot, PARTIAL, YANKDEL, allow_undo); // delete char
|
||||||
|
#if ENABLE_FEATURE_VI_UNDO
|
||||||
|
allow_undo = ALLOW_UNDO_CHAIN;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} while (--cmdcnt > 0);
|
} while (--cmdcnt > 0);
|
||||||
end_cmd_q(); // stop adding to q
|
end_cmd_q(); // stop adding to q
|
||||||
@ -3945,14 +3957,11 @@ static void do_cmd(int c)
|
|||||||
case '~': // ~- flip the case of letters a-z -> A-Z
|
case '~': // ~- flip the case of letters a-z -> A-Z
|
||||||
do {
|
do {
|
||||||
#if ENABLE_FEATURE_VI_UNDO
|
#if ENABLE_FEATURE_VI_UNDO
|
||||||
if (islower(*dot)) {
|
if (isalpha(*dot)) {
|
||||||
undo_push(dot, 1, UNDO_DEL);
|
undo_push(dot, 1, undo_del);
|
||||||
*dot = toupper(*dot);
|
*dot = islower(*dot) ? toupper(*dot) : tolower(*dot);
|
||||||
undo_push(dot, 1, UNDO_INS_CHAIN);
|
|
||||||
} else if (isupper(*dot)) {
|
|
||||||
undo_push(dot, 1, UNDO_DEL);
|
|
||||||
*dot = tolower(*dot);
|
|
||||||
undo_push(dot, 1, UNDO_INS_CHAIN);
|
undo_push(dot, 1, UNDO_INS_CHAIN);
|
||||||
|
undo_del = UNDO_DEL_CHAIN;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (islower(*dot)) {
|
if (islower(*dot)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user