mirror of
https://github.com/neovim/neovim.git
synced 2026-07-17 14:41:33 +00:00
fix(prompt): clear undo when changing/appending prompt
Problem: undoing after the prompt is changed breaks it (and causes init_prompt to abort it and append a new one), as the undo history contains the old prompt. Solution: like submitting, clear the undo buffer. Don't do it in init_prompt if the line was empty; that may not result in a new prompt, and causes commands like "S" to lose the history. As u_save, etc. wasn't being called by prompt_setprompt, undoing after it fixes the prompt usually gave undesirable results anyway. Remove the added undo_spec.lua test, as its approach no longer works as a repro, and finding a new one seems fiddly.
This commit is contained in:
@@ -1615,6 +1615,8 @@ static void init_prompt(int cmdchar_todo)
|
|||||||
ml_append(lnum, prompt, 0, false);
|
ml_append(lnum, prompt, 0, false);
|
||||||
appended_lines_mark(lnum, 1);
|
appended_lines_mark(lnum, 1);
|
||||||
curbuf->b_prompt_start.mark.lnum = curbuf->b_ml.ml_line_count;
|
curbuf->b_prompt_start.mark.lnum = curbuf->b_ml.ml_line_count;
|
||||||
|
// Like submitting, undo history was relevant to the old prompt.
|
||||||
|
u_clearallandblockfree(curbuf);
|
||||||
}
|
}
|
||||||
curbuf->b_prompt_start.mark.col = prompt_len;
|
curbuf->b_prompt_start.mark.col = prompt_len;
|
||||||
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
||||||
|
|||||||
@@ -792,7 +792,7 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
// If for some odd reason the old prompt is missing,
|
// If for some odd reason the old prompt is missing,
|
||||||
// replace prompt line with new-prompt (discards user-input).
|
// replace prompt line with new-prompt (discards user-input).
|
||||||
ml_replace_buf(buf, prompt_lno, (char *)new_prompt, true, false);
|
ml_replace_buf(buf, prompt_lno, (char *)new_prompt, true, false);
|
||||||
extmark_splice_cols(buf, prompt_lno - 1, 0, old_line_len, new_prompt_len, kExtmarkUndo);
|
extmark_splice_cols(buf, prompt_lno - 1, 0, old_line_len, new_prompt_len, kExtmarkNoUndo);
|
||||||
cursor_col = new_prompt_len;
|
cursor_col = new_prompt_len;
|
||||||
} else {
|
} else {
|
||||||
// Replace prev-prompt + user-input with new-prompt + user-input
|
// Replace prev-prompt + user-input with new-prompt + user-input
|
||||||
@@ -801,7 +801,7 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
xfree(new_line);
|
xfree(new_line);
|
||||||
}
|
}
|
||||||
extmark_splice_cols(buf, prompt_lno - 1, 0, buf->b_prompt_start.mark.col, new_prompt_len,
|
extmark_splice_cols(buf, prompt_lno - 1, 0, buf->b_prompt_start.mark.col, new_prompt_len,
|
||||||
kExtmarkUndo);
|
kExtmarkNoUndo);
|
||||||
cursor_col += new_prompt_len - buf->b_prompt_start.mark.col;
|
cursor_col += new_prompt_len - buf->b_prompt_start.mark.col;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,6 +810,8 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
check_cursor_col(curwin);
|
check_cursor_col(curwin);
|
||||||
}
|
}
|
||||||
changed_lines(buf, prompt_lno, 0, prompt_lno + 1, 0, true);
|
changed_lines(buf, prompt_lno, 0, prompt_lno + 1, 0, true);
|
||||||
|
// Undo history contains the old prompt.
|
||||||
|
u_clearallandblockfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear old prompt text and replace with the new one
|
// Clear old prompt text and replace with the new one
|
||||||
|
|||||||
@@ -225,22 +225,3 @@ describe(':undo! command', function()
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('undo', function()
|
|
||||||
before_each(clear)
|
|
||||||
|
|
||||||
it('u_savecommon uses correct buffer with reload = true', function()
|
|
||||||
-- Easiest to repro in a prompt buffer. prompt_setprompt's buffer must not yet have an undo
|
|
||||||
-- header to trigger this. Will crash if it wrongly uses the unloaded curbuf in nvim_buf_call,
|
|
||||||
-- as that has no undo buffer.
|
|
||||||
eq(0, #fn.undotree().entries)
|
|
||||||
exec_lua(function()
|
|
||||||
local buf = vim.api.nvim_get_current_buf()
|
|
||||||
vim.bo.buftype = 'prompt'
|
|
||||||
vim.api.nvim_buf_call(vim.fn.bufadd(''), function()
|
|
||||||
vim.fn.prompt_setprompt(buf, 'hej > ')
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
eq('hej > ', fn.prompt_getprompt(''))
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|||||||
@@ -514,6 +514,60 @@ describe('prompt buffer', function()
|
|||||||
{1:~ }|*3
|
{1:~ }|*3
|
||||||
1 line {MATCH:.*} |
|
1 line {MATCH:.*} |
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
-- "S" does not clear undo
|
||||||
|
feed('ihello<Esc>S')
|
||||||
|
screen:expect([[
|
||||||
|
cmd: tests-initial |
|
||||||
|
Command: "tests-initial" |
|
||||||
|
cmd: ^ |
|
||||||
|
{1:~ }|
|
||||||
|
{3:[Prompt] [+] }|
|
||||||
|
other buffer |
|
||||||
|
{1:~ }|*3
|
||||||
|
{5:-- INSERT --} |
|
||||||
|
]])
|
||||||
|
feed('<Esc>u')
|
||||||
|
screen:expect([[
|
||||||
|
cmd: tests-initial |
|
||||||
|
Command: "tests-initial" |
|
||||||
|
^cmd: hello |
|
||||||
|
{1:~ }|
|
||||||
|
{3:[Prompt] [+] }|
|
||||||
|
other buffer |
|
||||||
|
{1:~ }|*3
|
||||||
|
1 change; {MATCH:.*} |
|
||||||
|
]])
|
||||||
|
|
||||||
|
-- undo cleared if prompt changes
|
||||||
|
-- (otherwise undoing would abort it and append a new prompt, which isn't useful)
|
||||||
|
fn('prompt_setprompt', '', 'cmd > ')
|
||||||
|
feed('u')
|
||||||
|
screen:expect([[
|
||||||
|
cmd: tests-initial |
|
||||||
|
Command: "tests-initial" |
|
||||||
|
c^md > hello |
|
||||||
|
{1:~ }|
|
||||||
|
{3:[Prompt] [+] }|
|
||||||
|
other buffer |
|
||||||
|
{1:~ }|*3
|
||||||
|
Already at oldest change |
|
||||||
|
]])
|
||||||
|
|
||||||
|
-- new prompt line appended to fix missing prompt also clears undo
|
||||||
|
feed('A there')
|
||||||
|
fn('setpos', "':", { 0, fn('line', '.'), 99, 0 })
|
||||||
|
feed('<Esc>u')
|
||||||
|
screen:expect([[
|
||||||
|
cmd: tests-initial |
|
||||||
|
Command: "tests-initial" |
|
||||||
|
cmd > hello there |
|
||||||
|
cmd >^ |
|
||||||
|
{3:[Prompt] [+] }|
|
||||||
|
other buffer |
|
||||||
|
{1:~ }|*3
|
||||||
|
Already at oldest change |
|
||||||
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('o/O can create new lines', function()
|
it('o/O can create new lines', function()
|
||||||
|
|||||||
Reference in New Issue
Block a user