diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-08-21 09:33:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-21 09:33:09 +0200 |
commit | 38075200015e0e47d930a0ac7550546fd4cb2f9e (patch) | |
tree | 804f1f8d75dd403f21061f37ffe3bcbd82c48457 /src | |
parent | 0c9888cdbe800f1945823ec9affa3056b8feeeac (diff) | |
parent | ee51061b8c00eb1ac8ce628ba3831236b327ead2 (diff) | |
download | rneovim-38075200015e0e47d930a0ac7550546fd4cb2f9e.tar.gz rneovim-38075200015e0e47d930a0ac7550546fd4cb2f9e.tar.bz2 rneovim-38075200015e0e47d930a0ac7550546fd4cb2f9e.zip |
Merge #8877 from janlazo/vim-8.0.1441
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_docmd.c | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_undo.vim | 44 | ||||
-rw-r--r-- | src/nvim/undo.c | 228 |
3 files changed, 177 insertions, 118 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 20c188ed55..b22f799da0 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7577,10 +7577,11 @@ static void ex_bang(exarg_T *eap) */ static void ex_undo(exarg_T *eap) { - if (eap->addr_count == 1) /* :undo 123 */ - undo_time(eap->line2, FALSE, FALSE, TRUE); - else + if (eap->addr_count == 1) { // :undo 123 + undo_time(eap->line2, false, false, true); + } else { u_undo(1); + } } static void ex_wundo(exarg_T *eap) @@ -7613,8 +7614,8 @@ static void ex_redo(exarg_T *eap) static void ex_later(exarg_T *eap) { long count = 0; - int sec = FALSE; - int file = FALSE; + bool sec = false; + bool file = false; char_u *p = eap->arg; if (*p == NUL) @@ -7622,11 +7623,11 @@ static void ex_later(exarg_T *eap) else if (isdigit(*p)) { count = getdigits_long(&p); switch (*p) { - case 's': ++p; sec = TRUE; break; - case 'm': ++p; sec = TRUE; count *= 60; break; - case 'h': ++p; sec = TRUE; count *= 60 * 60; break; - case 'd': ++p; sec = TRUE; count *= 24 * 60 * 60; break; - case 'f': ++p; file = TRUE; break; + case 's': ++p; sec = true; break; + case 'm': ++p; sec = true; count *= 60; break; + case 'h': ++p; sec = true; count *= 60 * 60; break; + case 'd': ++p; sec = true; count *= 24 * 60 * 60; break; + case 'f': ++p; file = true; break; } } @@ -7634,7 +7635,7 @@ static void ex_later(exarg_T *eap) EMSG2(_(e_invarg2), eap->arg); else undo_time(eap->cmdidx == CMD_earlier ? -count : count, - sec, file, FALSE); + sec, file, false); } /* diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim index f31499607b..83ede1dc37 100644 --- a/src/nvim/testdir/test_undo.vim +++ b/src/nvim/testdir/test_undo.vim @@ -390,3 +390,47 @@ funct Test_undofile() set undodir& endfunc + +func Test_undo_0() + new + set ul=100 + normal i1 + undo + normal i2 + undo + normal i3 + + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('3', getline(1)) + call assert_equal(3, d.seq_cur) + + undo 2 + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('2', getline(1)) + call assert_equal(2, d.seq_cur) + + undo 1 + undo 0 + let d = undotree() + call assert_equal('', getline(1)) + call assert_equal(0, d.seq_cur) + + redo + let d = undotree() + call assert_equal('1', getline(1)) + call assert_equal(1, d.seq_cur) + + bwipe! +endfunc diff --git a/src/nvim/undo.c b/src/nvim/undo.c index f4eb50b3b5..e15b9ec796 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -122,7 +122,7 @@ static long u_newcount, u_oldcount; * When 'u' flag included in 'cpoptions', we behave like vi. Need to remember * the action that "u" should do. */ -static int undo_undoes = FALSE; +static bool undo_undoes = false; static int lastmark = 0; @@ -591,7 +591,7 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) uep->ue_next = curbuf->b_u_newhead->uh_entry; curbuf->b_u_newhead->uh_entry = uep; curbuf->b_u_synced = false; - undo_undoes = FALSE; + undo_undoes = false; #ifdef U_DEBUG u_check(FALSE); @@ -1675,10 +1675,11 @@ void u_undo(int count) count = 1; } - if (vim_strchr(p_cpo, CPO_UNDO) == NULL) - undo_undoes = TRUE; - else + if (vim_strchr(p_cpo, CPO_UNDO) == NULL) { + undo_undoes = true; + } else { undo_undoes = !undo_undoes; + } u_doit(count, false, true); } @@ -1804,31 +1805,29 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) u_undo_end(undo_undoes, false, quiet); } -/* - * Undo or redo over the timeline. - * When "step" is negative go back in time, otherwise goes forward in time. - * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as - * seconds. - * When "file" is TRUE use "step" as a number of file writes. - * When "absolute" is TRUE use "step" as the sequence number to jump to. - * "sec" must be FALSE then. - */ -void undo_time(long step, int sec, int file, int absolute) +// Undo or redo over the timeline. +// When "step" is negative go back in time, otherwise goes forward in time. +// When "sec" is false make "step" steps, when "sec" is true use "step" as +// seconds. +// When "file" is true use "step" as a number of file writes. +// When "absolute" is true use "step" as the sequence number to jump to. +// "sec" must be false then. +void undo_time(long step, bool sec, bool file, bool absolute) { long target; long closest; long closest_start; long closest_seq = 0; long val; - u_header_T *uhp; + u_header_T *uhp = NULL; u_header_T *last; int mark; int nomark; int round; - int dosec = sec; - int dofile = file; - int above = FALSE; - int did_undo = TRUE; + bool dosec = sec; + bool dofile = file; + bool above = false; + bool did_undo = true; /* First make sure the current undoable change is synced. */ if (curbuf->b_u_synced == false) @@ -1842,13 +1841,7 @@ void undo_time(long step, int sec, int file, int absolute) /* "target" is the node below which we want to be. * Init "closest" to a value we can't reach. */ if (absolute) { - if (step == 0) { - // target 0 does not exist, got to 1 and above it. - target = 1; - above = true; - } else { - target = step; - } + target = step; closest = -1; } else { if (dosec) { @@ -1873,7 +1866,7 @@ void undo_time(long step, int sec, int file, int absolute) if (target <= 0) /* Go to before first write: before the oldest change. Use * the sequence number for that. */ - dofile = FALSE; + dofile = false; } else { /* Moving forward to a newer write. */ target = curbuf->b_u_save_nr_cur + step; @@ -1881,7 +1874,7 @@ void undo_time(long step, int sec, int file, int absolute) /* Go to after last write: after the latest change. Use * the sequence number for that. */ target = curbuf->b_u_seq_last + 1; - dofile = FALSE; + dofile = false; } } } else @@ -1906,6 +1899,11 @@ void undo_time(long step, int sec, int file, int absolute) closest_start = closest; closest_seq = curbuf->b_u_seq_cur; + // When "target" is 0; Back to origin. + if (target == 0) { + goto found; + } + /* * May do this twice: * 1. Search for "target", update "closest" to the best match found. @@ -2015,17 +2013,17 @@ void undo_time(long step, int sec, int file, int absolute) } target = closest_seq; - dosec = FALSE; - dofile = FALSE; - if (step < 0) - above = TRUE; /* stop above the header */ + dosec = false; + dofile = false; + if (step < 0) { + above = true; // stop above the header + } } - /* If we found it: Follow the path to go to where we want to be. */ - if (uhp != NULL) { - /* - * First go up the tree as much as needed. - */ +found: + // If we found it: Follow the path to go to where we want to be. + if (uhp != NULL || target == 0) { + // First go up the tree as much as needed. while (!got_int) { /* Do the change warning now, for the same reason as above. */ change_warning(0); @@ -2035,83 +2033,97 @@ void undo_time(long step, int sec, int file, int absolute) uhp = curbuf->b_u_newhead; else uhp = uhp->uh_next.ptr; - if (uhp == NULL || uhp->uh_walk != mark - || (uhp->uh_seq == target && !above)) + if (uhp == NULL + || (target > 0 && uhp->uh_walk != mark) + || (uhp->uh_seq == target && !above)) { break; + } curbuf->b_u_curhead = uhp; u_undoredo(true, true); - uhp->uh_walk = nomark; // don't go back down here + if (target > 0) { + uhp->uh_walk = nomark; // don't go back down here + } } - /* - * And now go down the tree (redo), branching off where needed. - */ - while (!got_int) { - /* Do the change warning now, for the same reason as above. */ - change_warning(0); + // When back to origin, redo is not needed. + if (target > 0) { + // And now go down the tree (redo), branching off where needed. + while (!got_int) { + // Do the change warning now, for the same reason as above. + change_warning(0); - uhp = curbuf->b_u_curhead; - if (uhp == NULL) - break; - - /* Go back to the first branch with a mark. */ - while (uhp->uh_alt_prev.ptr != NULL - && uhp->uh_alt_prev.ptr->uh_walk == mark) - uhp = uhp->uh_alt_prev.ptr; + uhp = curbuf->b_u_curhead; + if (uhp == NULL) { + break; + } - /* Find the last branch with a mark, that's the one. */ - last = uhp; - while (last->uh_alt_next.ptr != NULL - && last->uh_alt_next.ptr->uh_walk == mark) - last = last->uh_alt_next.ptr; - if (last != uhp) { - /* Make the used branch the first entry in the list of - * alternatives to make "u" and CTRL-R take this branch. */ - while (uhp->uh_alt_prev.ptr != NULL) + // Go back to the first branch with a mark. + while (uhp->uh_alt_prev.ptr != NULL + && uhp->uh_alt_prev.ptr->uh_walk == mark) { uhp = uhp->uh_alt_prev.ptr; - if (last->uh_alt_next.ptr != NULL) - last->uh_alt_next.ptr->uh_alt_prev.ptr = - last->uh_alt_prev.ptr; - last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr; - last->uh_alt_prev.ptr = NULL; - last->uh_alt_next.ptr = uhp; - uhp->uh_alt_prev.ptr = last; - - if (curbuf->b_u_oldhead == uhp) - curbuf->b_u_oldhead = last; - uhp = last; - if (uhp->uh_next.ptr != NULL) - uhp->uh_next.ptr->uh_prev.ptr = uhp; - } - curbuf->b_u_curhead = uhp; + } - if (uhp->uh_walk != mark) - break; /* must have reached the target */ + // Find the last branch with a mark, that's the one. + last = uhp; + while (last->uh_alt_next.ptr != NULL + && last->uh_alt_next.ptr->uh_walk == mark) { + last = last->uh_alt_next.ptr; + } + if (last != uhp) { + // Make the used branch the first entry in the list of + // alternatives to make "u" and CTRL-R take this branch. + while (uhp->uh_alt_prev.ptr != NULL) { + uhp = uhp->uh_alt_prev.ptr; + } + if (last->uh_alt_next.ptr != NULL) { + last->uh_alt_next.ptr->uh_alt_prev.ptr = last->uh_alt_prev.ptr; + } + last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr; + last->uh_alt_prev.ptr = NULL; + last->uh_alt_next.ptr = uhp; + uhp->uh_alt_prev.ptr = last; - /* Stop when going backwards in time and didn't find the exact - * header we were looking for. */ - if (uhp->uh_seq == target && above) { - curbuf->b_u_seq_cur = target - 1; - break; - } + if (curbuf->b_u_oldhead == uhp) { + curbuf->b_u_oldhead = last; + } + uhp = last; + if (uhp->uh_next.ptr != NULL) { + uhp->uh_next.ptr->uh_prev.ptr = uhp; + } + } + curbuf->b_u_curhead = uhp; - u_undoredo(false, true); + if (uhp->uh_walk != mark) { + break; // must have reached the target + } - /* Advance "curhead" to below the header we last used. If it - * becomes NULL then we need to set "newhead" to this leaf. */ - if (uhp->uh_prev.ptr == NULL) - curbuf->b_u_newhead = uhp; - curbuf->b_u_curhead = uhp->uh_prev.ptr; - did_undo = FALSE; + // Stop when going backwards in time and didn't find the exact + // header we were looking for. + if (uhp->uh_seq == target && above) { + curbuf->b_u_seq_cur = target - 1; + break; + } - if (uhp->uh_seq == target) /* found it! */ - break; + u_undoredo(false, true); - uhp = uhp->uh_prev.ptr; - if (uhp == NULL || uhp->uh_walk != mark) { - // Need to redo more but can't find it... - internal_error("undo_time()"); - break; + // Advance "curhead" to below the header we last used. If it + // becomes NULL then we need to set "newhead" to this leaf. + if (uhp->uh_prev.ptr == NULL) { + curbuf->b_u_newhead = uhp; + } + curbuf->b_u_curhead = uhp->uh_prev.ptr; + did_undo = false; + + if (uhp->uh_seq == target) { // found it! + break; + } + + uhp = uhp->uh_prev.ptr; + if (uhp == NULL || uhp->uh_walk != mark) { + // Need to redo more but can't find it... + internal_error("undo_time()"); + break; + } } } } @@ -2375,8 +2387,8 @@ static void u_undoredo(int undo, bool do_buf_event) /// Otherwise, report the number of changes (this may be incorrect /// in some cases, but it's better than nothing). static void u_undo_end( - int did_undo, ///< just did an undo - int absolute, ///< used ":undo N" + bool did_undo, ///< just did an undo + bool absolute, ///< used ":undo N" bool quiet) { char *msgstr; @@ -2416,13 +2428,15 @@ static void u_undo_end( /* For ":undo N" we prefer a "after #N" message. */ if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) { uhp = curbuf->b_u_curhead->uh_next.ptr; - did_undo = FALSE; - } else if (did_undo) + did_undo = false; + } else if (did_undo) { uhp = curbuf->b_u_curhead; - else + } else { uhp = curbuf->b_u_curhead->uh_next.ptr; - } else + } + } else { uhp = curbuf->b_u_newhead; + } if (uhp == NULL) *msgbuf = NUL; |