neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 9a864d0a3c91f8b7666ad4b2197c6f3b4b8007f2
parent 2c97ea3f04544ea8a93166f8ca22a10529e4a774
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Thu, 27 Nov 2025 11:30:02 +0800

fix(edit): handle cindent properly with completion (#36711)

Don't handle cindent in insert_check(). Instead, do that just before
returning from insert_execute() if required.
This also makes the in_cinkeys() change from #12894 unnecessary.
Diffstat:
Msrc/nvim/edit.c | 56+++++++++++++++++++++++++++++---------------------------
Msrc/nvim/indent_c.c | 4++--
Mtest/functional/editor/mode_insert_spec.lua | 8++++++++
3 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/src/nvim/edit.c b/src/nvim/edit.c @@ -396,31 +396,6 @@ static int insert_check(VimState *state) { InsertState *s = (InsertState *)state; - // If typed something may trigger CursorHoldI again. - if (s->c != K_EVENT - // but not in CTRL-X mode, a script can't restore the state - && ctrl_x_mode_normal()) { - did_cursorhold = false; - } - - // Check if we need to cancel completion mode because the window - // or tab page was changed - if (ins_compl_active() && !ins_compl_win_active(curwin)) { - ins_compl_cancel(); - } - - // If the cursor was moved we didn't just insert a space - if (arrow_used) { - s->inserted_space = false; - } - - if (can_cindent - && cindent_on() - && ctrl_x_mode_normal() - && !ins_compl_active()) { - insert_do_cindent(s); - } - if (!revins_legal) { revins_scol = -1; // reset on illegal motions } else { @@ -565,6 +540,7 @@ static int insert_check(VimState *state) ins_compl_enable_autocomplete(); ins_compl_init_get_longest(); insert_do_complete(s); + insert_handle_key_post(s); return 1; } } @@ -648,7 +624,7 @@ static int insert_execute(VimState *state, int key) if (ins_compl_preinsert_longest() && !ins_compl_is_match_selected()) { ins_compl_insert(false, true); ins_compl_init_get_longest(); - return 1; + return 1; // continue } else { ins_compl_insert(false, false); } @@ -697,6 +673,7 @@ static int insert_execute(VimState *state, int key) if ((s->c == Ctrl_V || s->c == Ctrl_Q) && ctrl_x_mode_cmdline()) { insert_do_complete(s); + insert_handle_key_post(s); return 1; } @@ -715,7 +692,6 @@ static int insert_execute(VimState *state, int key) do_c_expr_indent(); return 1; // continue } - // A key name preceded by a star means that indenting has to be // done before inserting the key. if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white) @@ -1285,6 +1261,7 @@ normalchar: break; } // end of switch (s->c) + insert_handle_key_post(s); return 1; // continue } @@ -1311,6 +1288,31 @@ static void insert_do_cindent(InsertState *s) } } +static void insert_handle_key_post(InsertState *s) +{ + // If typed something may trigger CursorHoldI again. + if (s->c != K_EVENT + // but not in CTRL-X mode, a script can't restore the state + && ctrl_x_mode_normal()) { + did_cursorhold = false; + } + + // Check if we need to cancel completion mode because the window + // or tab page was changed + if (ins_compl_active() && !ins_compl_win_active(curwin)) { + ins_compl_cancel(); + } + + // If the cursor was moved we didn't just insert a space + if (arrow_used) { + s->inserted_space = false; + } + + if (can_cindent && cindent_on() && ctrl_x_mode_normal()) { + insert_do_cindent(s); + } +} + /// edit(): Start inserting text. /// /// "cmdchar" can be: diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c @@ -3760,7 +3760,7 @@ static int find_match(int lookfor, linenr_T ourscope) /// Check that "cinkeys" contains the key "keytyped", /// when == '*': Only if key is preceded with '*' (indent before insert) /// when == '!': Only if key is preceded with '!' (don't insert) -/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards) +/// when == ' ': Only if key is not preceded with '*' (indent afterwards) /// /// "keytyped" can have a few special values: /// KEY_OPEN_FORW : @@ -3797,7 +3797,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) case '!': try_match = (*look == '!'); break; default: - try_match = (*look != '*') && (*look != '!'); break; + try_match = (*look != '*'); break; } if (*look == '*' || *look == '!') { look++; diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua @@ -24,6 +24,14 @@ describe('insert-mode', function() eq(' x', curbuf_contents()) end) + it('indent works properly with autocompletion enabled #35381', function() + command('set autoindent cindent autocomplete') + feed('ivoid func(void) {<CR>') + expect('void func(void) {\n\t') + feed('}') + expect('void func(void) {\n}') + end) + it('CTRL-@', function() -- Inserts last-inserted text, leaves insert-mode. insert('hello')