diff options
-rw-r--r-- | src/nvim/undo.c | 6 | ||||
-rw-r--r-- | test/functional/helpers.lua | 2 | ||||
-rw-r--r-- | test/functional/normal/undo_spec.lua | 61 | ||||
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 12 |
4 files changed, 75 insertions, 6 deletions
diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 4d56046bc1..129308ad3e 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1710,7 +1710,8 @@ bool u_undo_and_forget(int count) if (curbuf->b_u_curhead) { to_forget->uh_alt_next.ptr = NULL; curbuf->b_u_curhead->uh_alt_prev.ptr = to_forget->uh_alt_prev.ptr; - curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq-1; + curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_next.ptr ? + curbuf->b_u_curhead->uh_next.ptr->uh_seq : 0; } else if (curbuf->b_u_newhead) { curbuf->b_u_seq_cur = curbuf->b_u_newhead->uh_seq; } @@ -2321,7 +2322,8 @@ static void u_undoredo(int undo) if (undo) /* We are below the previous undo. However, to make ":earlier 1s" * work we compute this as being just above the just undone change. */ - --curbuf->b_u_seq_cur; + curbuf->b_u_seq_cur = curhead->uh_next.ptr ? + curhead->uh_next.ptr->uh_seq : 0; /* Remember where we are for ":earlier 1f" and ":later 1f". */ if (curhead->uh_save_nr != 0) { diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 7de1d0f2c6..880cb6546c 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -195,7 +195,7 @@ local function dedent(str) indent = line_indent end end - if #indent == 0 then + if indent == nil or #indent == 0 then -- no minimum common indent return str end diff --git a/test/functional/normal/undo_spec.lua b/test/functional/normal/undo_spec.lua new file mode 100644 index 0000000000..55429f2e1e --- /dev/null +++ b/test/functional/normal/undo_spec.lua @@ -0,0 +1,61 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local execute = helpers.execute +local expect = helpers.expect +local feed = helpers.feed +local insert = helpers.insert + +describe('u CTRL-R g- g+', function() + before_each(clear) + + local function create_history(num_steps) + if num_steps == 0 then return end + insert('1') + if num_steps == 1 then return end + feed('o2<esc>') + feed('o3<esc>') + feed('u') + if num_steps == 2 then return end + feed('o4<esc>') + if num_steps == 3 then return end + feed('u') + end + + local function undo_and_redo(hist_pos, undo, redo, expect_str) + execute('enew!') + create_history(hist_pos) + local cur_contents = helpers.curbuf_contents() + feed(undo) + expect(expect_str) + feed(redo) + expect(cur_contents) + end + + -- TODO Look for message saying 'Already at oldest change' + it('does nothing when no changes have happened', function() + undo_and_redo(0, 'u', '<C-r>', '') + undo_and_redo(0, 'g-', 'g+', '') + end) + it('undoes a change when at a leaf', function() + undo_and_redo(1, 'u', '<C-r>', '') + undo_and_redo(1, 'g-', 'g+', '') + end) + it('undoes a change when in a non-leaf', function() + undo_and_redo(2, 'u', '<C-r>', '1') + undo_and_redo(2, 'g-', 'g+', '1') + end) + it('undoes properly around a branch point', function() + undo_and_redo(3, 'u', '<C-r>', [[ + 1 + 2]]) + undo_and_redo(3, 'g-', 'g+', [[ + 1 + 2 + 3]]) + end) + it('can find the previous sequence after undoing to a branch', function() + undo_and_redo(4, 'u', '<C-r>', '1') + undo_and_redo(4, 'g-', 'g+', '1') + end) +end) diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 41ebfd2334..6da22b6a3a 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -352,6 +352,14 @@ describe(":substitute, 'inccommand' preserves undo", function() feed("2u") feed(substring .. "<esc>") + expect([[ + 1]]) + feed("g-") + expect([[ + ]]) + feed("g+") + expect([[ + 1]]) feed("<c-r>") expect([[ 1 @@ -374,9 +382,7 @@ describe(":substitute, 'inccommand' preserves undo", function() 2]]) end - -- TODO(vim): This does not work, even in Vim. - -- Waiting for fix (perhaps from upstream). - pending("at a non-leaf of the undo tree", function() + it("at a non-leaf of the undo tree", function() for _, case in pairs(cases) do for _, str in pairs(substrings) do for _, redoable in pairs({true}) do |