Commit: patch 9.1.1850: completion: not triggered after i_Ctrl-W/i_Ctrl-U

4 views
Skip to first unread message

Christian Brabandt

unread,
Oct 12, 2025, 10:45:14 AMOct 12
to vim...@googlegroups.com
patch 9.1.1850: completion: not triggered after i_Ctrl-W/i_Ctrl-U

Commit: https://github.com/vim/vim/commit/da2dabc6f740b1ed3397797af8a8b0b2ec02bc31
Author: Girish Palya <giri...@gmail.com>
Date: Sun Oct 12 14:37:02 2025 +0000

patch 9.1.1850: completion: not triggered after i_Ctrl-W/i_Ctrl-U

Problem: completion: not triggered after i_Ctrl-W/i_Ctrl-U
Solution: Trigger autocomplete when entering Insert mode
(Girish Palya).

fixes: #18535
closes: #18543

Signed-off-by: Girish Palya <giri...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index 914e9fc83..5ed3e803a 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt* For Vim version 9.1. Last change: 2025 Sep 16
+*insert.txt* For Vim version 9.1. Last change: 2025 Oct 12


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -80,10 +80,11 @@ CTRL-W Delete the word before the cursor (see |i_backspacing| about
joining lines). See the section "word motions",
|word-motions|, for the definition of a word.
*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/edit.c b/src/edit.c
index 2a765467d..891d51cf9 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -100,6 +100,25 @@ static int ins_need_undo; // call u_save() before inserting a
static int dont_sync_undo = FALSE; // CTRL-G U prevents syncing undo for
// the next left/right cursor key

+#define TRIGGER_AUTOCOMPLETE() \
+ do { \
+ update_screen(UPD_VALID); /* Show char (deletion) immediately */ \
+ out_flush(); \
+ ins_compl_enable_autocomplete(); \
+ goto docomplete; \
+ } 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)
+
/*
* edit(): Start inserting text.
*
@@ -146,6 +165,7 @@ edit(
#ifdef FEAT_CONCEAL
int cursor_line_was_concealed;
#endif
+ int ins_just_started = TRUE;

// Remember whether editing was restarted after CTRL-O.
did_restart_edit = restart_edit;
@@ -593,6 +613,30 @@ edit(
// Got here from normal mode when bracketed paste started.
c = K_PS;
else
+ {
+ // Trigger autocomplete when entering Insert mode, either directly
+ // or via change commands like 'ciw', 'cw', etc., before the first
+ // character is typed.
+ if (ins_just_started)
+ {
+ ins_just_started = FALSE;
+ if (ins_compl_has_autocomplete() && !char_avail()
+ && curwin->w_cursor.col > 0)
+ {
+ c = char_before_cursor();
+ if (vim_isprintc(c))
+ {
+ ins_compl_enable_autocomplete();
+ ins_compl_init_get_longest();
+#ifdef FEAT_RIGHTLEFT
+ if (p_hkmap)
+ c = hkmap(c); // Hebrew mode mapping
+#endif
+ goto docomplete;
+ }
+ }
+ }
+
do
{
c = safe_vgetc();
@@ -622,6 +666,7 @@ edit(
goto doESCkey;
}
} while (c == K_IGNORE || c == K_NOP);
+ }

// Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V.
did_cursorhold = TRUE;
@@ -991,18 +1036,8 @@ doESCkey:
case Ctrl_H:
did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
auto_format(FALSE, TRUE);
- if (did_backspace && ins_compl_has_autocomplete() && !char_avail()
- && curwin->w_cursor.col > 0)
- {
- c = char_before_cursor();
- if (vim_isprintc(c))
- {
- update_screen(UPD_VALID); // Show char deletion immediately
- out_flush();
- ins_compl_enable_autocomplete();
- goto docomplete; // Trigger autocompletion
- }
- }
+ if (did_backspace)
+ MAY_TRIGGER_AUTOCOMPLETE(c);
break;

case Ctrl_W: // delete word before the cursor
@@ -1020,6 +1055,8 @@ doESCkey:
#endif
did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
auto_format(FALSE, TRUE);
+ if (did_backspace)
+ MAY_TRIGGER_AUTOCOMPLETE(c);
break;

case Ctrl_U: // delete all inserted text in current line
@@ -1031,6 +1068,8 @@ doESCkey:
did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
auto_format(FALSE, TRUE);
inserted_space = FALSE;
+ if (did_backspace)
+ MAY_TRIGGER_AUTOCOMPLETE(c);
break;

case K_LEFTMOUSE: // mouse keys
@@ -1424,12 +1463,7 @@ normalchar:
// Trigger autocompletion
if (ins_compl_has_autocomplete() && !char_avail()
&& vim_isprintc(c))
- {
- update_screen(UPD_VALID); // Show character immediately
- out_flush();
- ins_compl_enable_autocomplete();
- goto docomplete;
- }
+ TRIGGER_AUTOCOMPLETE();

break;
} // end of switch (c)
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 23c84b28b..6d492373c 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -5416,10 +5416,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 test_override("char_avail", 0)
delfunc NonKeywordComplete
- set autocomplete&
+ delfunc TestComplete
+ set autocomplete& omnifunc& complete&
unlet g:CallCount
endfunc

diff --git a/src/version.c b/src/version.c
index c28ce040a..3f6baf6bb 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1850,
/**/
1849,
/**/
Reply all
Reply to author
Forward
0 new messages