mirror of
https://github.com/neovim/neovim.git
synced 2026-09-13 01:21:06 +00:00
fix(autocmd): dot-repeat triggers InsertCharPre #41806
Problem:
InsertCharPre is triggered for stuffed text (".", i_CTRL-R, i_CTRL-A).
But that text was already transformed when it was typed: the `v:char`
result is appended to the redo buffer literally (`redo_append_lit()`).
So "." transforms it again, e.g. an autopair handler turns "()" into
"())".
Solution:
Skip InsertCharPre for stuffed text.
Precedent: `vgetorpeek()` disables abbreviations for stuffed text for
the same reason (it is post-expansion).
Macros are unaffected.
This commit is contained in:
@@ -903,6 +903,8 @@ InsertCharPre When a character is typed in Insert mode,
|
||||
to more than one character this text is
|
||||
inserted literally.
|
||||
|
||||
Not triggered for |.| redo, |i_CTRL-R|, |i_CTRL-A|.
|
||||
|
||||
Cannot change the text. |textlock|
|
||||
|
||||
*InsertEnter*
|
||||
|
||||
@@ -349,6 +349,8 @@ Editor:
|
||||
|
||||
Events (autocommands):
|
||||
- Fixed inconsistent behavior in execution of nested autocommands #23368
|
||||
- |InsertCharPre| is not triggered for stuffed text (|.| redo, |i_CTRL-R|,
|
||||
|i_CTRL-A|), which also skips mappings and abbreviations.
|
||||
- |OptionSet| is triggered for 'modified' when writing a file, undoing changes,
|
||||
or using |:set| modified.
|
||||
- |Progress|
|
||||
|
||||
@@ -4384,14 +4384,14 @@ static char *do_insert_char_pre(int c)
|
||||
char buf[MB_MAXBYTES + 1];
|
||||
const int save_State = State;
|
||||
|
||||
if (c == Ctrl_RSB) {
|
||||
if (c == Ctrl_RSB // i_CTRL-] only triggers abbreviations.
|
||||
// Stuffed text was transformed when typed and appended to redobuf (redo_append_lit).
|
||||
// Like abbreviations (vgetorpeek()), don't transform it again.
|
||||
|| KeyStuffed
|
||||
|| !has_event(EVENT_INSERTCHARPRE)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return quickly when there is nothing to do.
|
||||
if (!has_event(EVENT_INSERTCHARPRE)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t buflen = (size_t)utf_char2bytes(c, buf);
|
||||
buf[buflen] = NUL;
|
||||
|
||||
|
||||
@@ -49,6 +49,56 @@ describe('insert-mode', function()
|
||||
expect('hellhellhellhelloxo')
|
||||
end)
|
||||
|
||||
it('InsertCharPre is not triggered for stuffed text (redo/dot-repeat) #25296', function()
|
||||
n.exec_lua([[
|
||||
_G.n = 0
|
||||
vim.api.nvim_create_autocmd('InsertCharPre', {
|
||||
callback = function()
|
||||
_G.n = _G.n + 1
|
||||
if vim.v.char == '(' then
|
||||
vim.v.char = '()'
|
||||
end
|
||||
end,
|
||||
})
|
||||
]])
|
||||
local function calls()
|
||||
return n.exec_lua('return _G.n')
|
||||
end
|
||||
api.nvim_buf_set_lines(0, 0, -1, true, { 'a', 'b', 'c', 'd' })
|
||||
feed('gg0i(<Esc>')
|
||||
eq(1, calls())
|
||||
|
||||
-- Dot-repeat ("redo") inserts literally (no InsertCharPre).
|
||||
feed('j.')
|
||||
expect([[
|
||||
()a
|
||||
()b
|
||||
c
|
||||
d]])
|
||||
eq(1, calls())
|
||||
|
||||
-- i_CTRL-R, i_CTRL-A inserts as stuffed text (no InsertCharPre).
|
||||
n.fn.setreg('a', '(')
|
||||
feed('ji<C-R>a<Esc>')
|
||||
feed('ji<C-A><Esc>')
|
||||
expect([[
|
||||
()a
|
||||
()b
|
||||
(c
|
||||
(d]])
|
||||
eq(1, calls())
|
||||
|
||||
-- Macro keys are typeahead, not stuffed, thus trigger InsertCharPre.
|
||||
n.fn.setreg('q', 'A(\27')
|
||||
feed('gg@q')
|
||||
expect([[
|
||||
()a()
|
||||
()b
|
||||
(c
|
||||
(d]])
|
||||
eq(2, calls())
|
||||
end)
|
||||
|
||||
describe('Ctrl-R', function()
|
||||
it('works', function()
|
||||
command("let @@ = 'test'")
|
||||
|
||||
Reference in New Issue
Block a user