undo: :earlier, g-: Set b_u_seq_cur correctly. (#6016)

Previously alternate branches were not accounted for properly, with this
change g- after an undo to a branch point works.

The current sequence number b_u_seq_cur is used in undo_time(), in
u_doit() this was calculated by subtracting one from the curhead
sequence number.

The curhead header entry represents the change that was just undone, so
the sequence number we want is that of the change we have moved to. This
is the sequence number of the undo head that is the uh_next element of
this curhead. That sequence number is not always one less than the
curhead sequence number -- there may have been an alternate branch at
this point.

Instead of subtracting one, we now directly find the sequence number of
curhead->uh_next.
This commit is contained in:
Matthew Malcomson 2017-01-26 10:41:05 +00:00 committed by Justin M. Keyes
parent 39a6f835e7
commit d25649fa01
4 changed files with 75 additions and 6 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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)

View File

@ -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