commit 83c7193c119ffe5cef8a86ec290103921c15dc01
parent 72b0bfa1fb7e897e5126aabae718a5480f466b9e
Author: zeertzjq <zeertzjq@outlook.com>
Date: Mon, 13 Oct 2025 08:08:53 +0800
vim-patch:9.1.1850: completion: not triggered after i_Ctrl-W/i_Ctrl-U (#36156)
Problem: completion: not triggered after i_Ctrl-W/i_Ctrl-U
Solution: Trigger autocomplete when entering Insert mode
(Girish Palya).
fixes: vim/vim#18535
closes: vim/vim#18543
https://github.com/vim/vim/commit/da2dabc6f740b1ed3397797af8a8b0b2ec02bc31
Co-authored-by: Girish Palya <girishji@gmail.com>
Diffstat:
3 files changed, 76 insertions(+), 21 deletions(-)
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
@@ -69,10 +69,11 @@ CTRL-W Delete the word before the cursor (see |i_backspacing| about
By default, sets a new undo point before deleting.
|default-mappings|
*i_CTRL-U*
-CTRL-U Delete all entered characters before the cursor in the current
- line. If there are no newly entered characters and
- 'backspace' is not empty, delete all characters before the
- cursor in the current line.
+CTRL-U Delete all characters that were entered after starting Insert
+ mode and before the cursor in the current line.
+ If there are no newly entered characters and 'backspace' is
+ not empty, delete all characters before the cursor in the
+ current line.
If C-indenting is enabled the indent will be adjusted if the
line becomes blank.
See |i_backspacing| about joining lines.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
@@ -88,6 +88,7 @@ typedef struct {
int mincol;
int cmdchar;
int cmdchar_todo; // cmdchar to handle once in init_prompt
+ bool ins_just_started;
int startln;
int count;
int c;
@@ -144,12 +145,33 @@ static linenr_T o_lnum = 0;
static kvec_t(char) replace_stack = KV_INITIAL_VALUE;
+#define TRIGGER_AUTOCOMPLETE() \
+ do { \
+ redraw_later(curwin, UPD_VALID); \
+ update_screen(); /* Show char deletion immediately */ \
+ ui_flush(); \
+ ins_compl_enable_autocomplete(); \
+ insert_do_complete(s); \
+ break; \
+ } while (0)
+
+#define MAY_TRIGGER_AUTOCOMPLETE(c) \
+ do { \
+ if (ins_compl_has_autocomplete() && !char_avail() && curwin->w_cursor.col > 0) { \
+ (c) = char_before_cursor(); \
+ if (vim_isprintc(c)) { \
+ TRIGGER_AUTOCOMPLETE(); \
+ } \
+ } \
+ } while (0)
+
static void insert_enter(InsertState *s)
{
s->did_backspace = true;
s->old_topfill = -1;
s->replaceState = MODE_REPLACE;
s->cmdchar_todo = s->cmdchar;
+ s->ins_just_started = true;
// Remember whether editing was restarted after CTRL-O
did_restart_edit = restart_edit;
// sleep before redrawing, needed for "CTRL-O :" that results in an
@@ -532,6 +554,22 @@ static int insert_check(VimState *state)
dont_sync_undo = kFalse;
}
+ // Trigger autocomplete when entering Insert mode, either directly
+ // or via change commands like 'ciw', 'cw', etc., before the first
+ // character is typed.
+ if (s->ins_just_started) {
+ s->ins_just_started = false;
+ if (ins_compl_has_autocomplete() && !char_avail() && curwin->w_cursor.col > 0) {
+ s->c = char_before_cursor();
+ if (vim_isprintc(s->c)) {
+ ins_compl_enable_autocomplete();
+ ins_compl_init_get_longest();
+ insert_do_complete(s);
+ return 1;
+ }
+ }
+ }
+
return 1;
}
@@ -855,17 +893,8 @@ static int insert_handle_key(InsertState *s)
case Ctrl_H:
s->did_backspace = ins_bs(s->c, BACKSPACE_CHAR, &s->inserted_space);
auto_format(false, true);
- if (s->did_backspace && ins_compl_has_autocomplete() && !char_avail()
- && curwin->w_cursor.col > 0) {
- s->c = char_before_cursor();
- if (vim_isprintc(s->c)) {
- redraw_later(curwin, UPD_VALID);
- update_screen(); // Show char deletion immediately
- ui_flush();
- ins_compl_enable_autocomplete();
- insert_do_complete(s); // Trigger autocompletion
- return 1;
- }
+ if (s->did_backspace) {
+ MAY_TRIGGER_AUTOCOMPLETE(s->c);
}
break;
@@ -881,6 +910,9 @@ static int insert_handle_key(InsertState *s)
}
s->did_backspace = ins_bs(s->c, BACKSPACE_WORD, &s->inserted_space);
auto_format(false, true);
+ if (s->did_backspace) {
+ MAY_TRIGGER_AUTOCOMPLETE(s->c);
+ }
break;
case Ctrl_U: // delete all inserted text in current line
@@ -891,6 +923,9 @@ static int insert_handle_key(InsertState *s)
s->did_backspace = ins_bs(s->c, BACKSPACE_LINE, &s->inserted_space);
auto_format(false, true);
s->inserted_space = false;
+ if (s->did_backspace) {
+ MAY_TRIGGER_AUTOCOMPLETE(s->c);
+ }
}
break;
@@ -1244,11 +1279,7 @@ normalchar:
foldOpenCursor();
// Trigger autocompletion
if (ins_compl_has_autocomplete() && !char_avail() && vim_isprintc(s->c)) {
- redraw_later(curwin, UPD_VALID);
- update_screen(); // Show character immediately
- ui_flush();
- ins_compl_enable_autocomplete();
- insert_do_complete(s);
+ TRIGGER_AUTOCOMPLETE();
}
break;
diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim
@@ -5528,10 +5528,33 @@ func Test_autocomplete_trigger()
call assert_equal(['fodabc', 'fodxyz'], b:matches->mapnew('v:val.word'))
call assert_equal(-1, b:selected)
+ " Test 8: Ctrl_W / Ctrl_U (delete word/line) should restart autocompletion
+ func! TestComplete(findstart, base)
+ if a:findstart
+ return col('.') - 1
+ endif
+ return ['fooze', 'faberge']
+ endfunc
+ set omnifunc=TestComplete
+ set complete+=o
+ call feedkeys("Sprefix->fo\<F2>\<Esc>0", 'tx!')
+ call assert_equal(['fodabc', 'fodxyz', 'foobar', 'fooze'], b:matches->mapnew('v:val.word'))
+ call feedkeys("Sprefix->fo\<C-W>\<F2>\<Esc>0", 'tx!')
+ call assert_equal(['fooze', 'faberge'], b:matches->mapnew('v:val.word'))
+ call feedkeys("Sprefix->\<Esc>afo\<C-U>\<F2>\<Esc>0", 'tx!')
+ call assert_equal(['fooze', 'faberge'], b:matches->mapnew('v:val.word'))
+
+ " Test 9: Trigger autocomplete immediately upon entering Insert mode
+ call feedkeys("Sprefix->foo\<Esc>a\<F2>\<Esc>0", 'tx!')
+ call assert_equal(['foobar', 'fooze', 'faberge'], b:matches->mapnew('v:val.word'))
+ call feedkeys("Sprefix->fooxx\<Esc>hcw\<F2>\<Esc>0", 'tx!')
+ call assert_equal(['foobar', 'fooze', 'faberge'], b:matches->mapnew('v:val.word'))
+
bw!
call Ntest_override("char_avail", 0)
delfunc NonKeywordComplete
- set autocomplete&
+ delfunc TestComplete
+ set autocomplete& omnifunc& complete&
unlet g:CallCount
endfunc