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:
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')