Skip to content

Commit b486ed8

Browse files
girishjizeertzjq
authored andcommitted
patch 9.1.1576: cannot easily trigger wildcard expansion
Problem: cannot easily trigger wildcard expansion Solution: Introduce wildtrigger() function (Girish Palya) This PR introduces a new `wildtrigger()` function. See `:h wildtrigger()` `wildtrigger()` behaves like pressing the `wildchar,` but provides a more refined and controlled completion experience: - Suppresses beeps when no matches are found. - Avoids displaying irrelevant completions (like full command lists) when the prefix is insufficient or doesn't match. - Skips completion if the typeahead buffer has pending input or if a wildmenu is already active. - Does not print "..." before completion. This is an improvement on the `feedkeys()` based autocompletion script given in #16759. closes: #17806 Signed-off-by: Girish Palya <[email protected]> Co-authored-by: zeertzjq <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 689f3bf commit b486ed8

File tree

15 files changed

+190
-69
lines changed

15 files changed

+190
-69
lines changed

runtime/doc/builtin.txt

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 17
1+
*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -757,6 +757,7 @@ virtcol2col({winid}, {lnum}, {col})
757757
Number byte index of a character on screen
758758
visualmode([{expr}]) String last visual mode used
759759
wildmenumode() Number whether 'wildmenu' mode is active
760+
wildtrigger() Number start wildcard expansion
760761
win_execute({id}, {command} [, {silent}])
761762
String execute {command} in window {id}
762763
win_findbuf({bufnr}) List find windows containing {bufnr}
@@ -12331,6 +12332,33 @@ wildmenumode() *wildmenumode()*
1233112332
Return type: |Number|
1233212333

1233312334

12335+
wildtrigger() *wildtrigger()*
12336+
Start wildcard expansion in the command-line, using the
12337+
behavior defined by the 'wildmode' and 'wildoptions' settings.
12338+
See |cmdline-completion|.
12339+
12340+
This function also enables completion in search patterns such
12341+
as |/|, |?|, |:s|, |:g|, |:v| and |:vimgrep|.
12342+
12343+
Unlike pressing 'wildchar' manually, this function does not
12344+
produce a beep when no matches are found and generally
12345+
operates more quietly. This makes it suitable for triggering
12346+
completion automatically, such as from an |:autocmd|.
12347+
*cmdline-autocompletion*
12348+
Example: To make the completion menu pop up automatically as
12349+
you type on the command line, use: >
12350+
autocmd CmdlineChanged [:/?] call wildtrigger()
12351+
set wildmode=noselect:lastused,full wildoptions=pum
12352+
<
12353+
To retain normal history navigation (up/down keys): >
12354+
cnoremap <Up> <C-U><Up>
12355+
cnoremap <Down> <C-U><Down>
12356+
<
12357+
Return value is always 0.
12358+
12359+
Return type: |Number|
12360+
12361+
1233412362
win_execute({id}, {command} [, {silent}]) *win_execute()*
1233512363
Like `execute()` but in the context of window {id}.
1233612364
The window will temporarily be made the current window,

runtime/doc/cmdline.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*cmdline.txt* For Vim version 9.1. Last change: 2025 Jun 28
1+
*cmdline.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -479,6 +479,8 @@ When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
479479
ending up back to what was typed. If the first match is not what you wanted,
480480
you can use <S-Tab> or CTRL-P to go straight back to what you typed.
481481

482+
See also |wildtrigger()|.
483+
482484
The 'wildmenu' option can be set to show the matches just above the command
483485
line.
484486

runtime/doc/options.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2025 Jul 20
1+
*options.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -9797,7 +9797,7 @@ A jump table for the options with a short description can be found at |Q_op|.
97979797
< 'wildchar' also enables completion in search pattern contexts such as
97989798
|/|, |?|, |:s|, |:g|, |:v|, and |:vim|. To insert a literal <Tab>
97999799
instead of triggering completion, type <C-V><Tab> or "\t".
9800-
See also |'wildoptions'|.
9800+
See also 'wildoptions' and |wildtrigger()|.
98019801
NOTE: This option is set to the Vi default value when 'compatible' is
98029802
set and to the Vim default value when 'compatible' is reset.
98039803

runtime/doc/tags

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6620,6 +6620,7 @@ cmdarg-variable eval.txt /*cmdarg-variable*
66206620
cmdbang-variable eval.txt /*cmdbang-variable*
66216621
cmdcomplete_info() builtin.txt /*cmdcomplete_info()*
66226622
cmdline-arguments vi_diff.txt /*cmdline-arguments*
6623+
cmdline-autocompletion builtin.txt /*cmdline-autocompletion*
66236624
cmdline-changed version5.txt /*cmdline-changed*
66246625
cmdline-completion cmdline.txt /*cmdline-completion*
66256626
cmdline-editing cmdline.txt /*cmdline-editing*
@@ -11608,6 +11609,7 @@ whitespace pattern.txt /*whitespace*
1160811609
wildcard editing.txt /*wildcard*
1160911610
wildcards editing.txt /*wildcards*
1161011611
wildmenumode() builtin.txt /*wildmenumode()*
11612+
wildtrigger() builtin.txt /*wildtrigger()*
1161111613
win-scrolled-resized windows.txt /*win-scrolled-resized*
1161211614
win16 os_win32.txt /*win16*
1161311615
win32 os_win32.txt /*win32*

runtime/doc/usr_41.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*usr_41.txt* For Vim version 9.1. Last change: 2025 Jul 05
1+
*usr_41.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33
VIM USER MANUAL - by Bram Moolenaar
44

@@ -1233,6 +1233,7 @@ Mappings and Menus: *mapping-functions*
12331233
mapset() restore a mapping
12341234
menu_info() get information about a menu item
12351235
wildmenumode() check if the wildmode is active
1236+
wildtrigger() start wildcard expansion
12361237

12371238
Testing: *test-functions*
12381239
assert_equal() assert that two expressions values are equal

runtime/doc/version9.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*version9.txt* For Vim version 9.1. Last change: 2025 Jul 20
1+
*version9.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41601,6 +41601,7 @@ Completion~
4160141601
"nosort" - do not sort completion results
4160241602
"preinsert" - highlight to be inserted values
4160341603
"nearest" - sort completion results by distance to cursor
41604+
- new function |wildtrigger()| to trigger wildcard expansion
4160441605

4160541606
Platform specific~
4160641607
-----------------
@@ -41765,6 +41766,7 @@ Functions: ~
4176541766
|str2blob()| convert a List of strings into a blob
4176641767
|test_null_tuple()| return a null tuple
4176741768
|tuple2list()| turn a Tuple of items into a List
41769+
|wildtrigger()| trigger wildcard expansion
4176841770

4176941771

4177041772
Autocommands: ~

runtime/syntax/vim.vim

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
" Language: Vim script
33
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
44
" Doug Kearns <[email protected]>
5-
" Last Change: 2025 Jul 18
5+
" Last Change: 2025 Jul 21
66
" Former Maintainer: Charles E. Campbell
77

88
" DO NOT CHANGE DIRECTLY.
@@ -141,7 +141,7 @@ syn match vimUserAutoEvent contained "\<\h\w*\>" skipwhite nextgroup=vimUserAuto
141141

142142
" Highlight commonly used Groupnames {{{2
143143
" GEN_SYN_VIM: vimGroup, START_STR='syn keyword vimGroup contained', END_STR=''
144-
syn keyword vimGroup contained Added Boolean Changed Character Comment Conditional Constant Debug Define Delimiter Error Exception Float Function Identifier Ignore Include Keyword Label Macro Number Operator PreCondit PreProc Removed Repeat Special SpecialChar SpecialComment Statement StorageClass String Structure Tag Todo Type Typedef Underlined
144+
syn keyword vimGroup contained Added Bold BoldItalic Boolean Changed Character Comment Conditional Constant Debug Define Delimiter Error Exception Float Function Identifier Ignore Include Italic Keyword Label Macro Number Operator PreCondit PreProc Removed Repeat Special SpecialChar SpecialComment Statement StorageClass String Structure Tag Todo Type Typedef Underlined
145145

146146
" Default highlighting groups {{{2
147147
" GEN_SYN_VIM: vimHLGroup, START_STR='syn keyword vimHLGroup contained', END_STR=''
@@ -159,8 +159,8 @@ syn keyword vimFuncName contained histadd histdel histget histnr hlID hlexists h
159159
syn keyword vimFuncName contained mzeval nextnonblank ngettext nr2char or pathshorten perleval popup_atcursor popup_beval popup_clear popup_close popup_create popup_dialog popup_filter_menu popup_filter_yesno popup_findecho popup_findinfo popup_findpreview popup_getoptions popup_getpos popup_hide popup_list popup_locate popup_menu popup_move popup_notification popup_setbuf popup_setoptions popup_settext popup_show pow prevnonblank printf prompt_getprompt prompt_setcallback prompt_setinterrupt prompt_setprompt prop_add prop_add_list prop_clear prop_find prop_list prop_remove prop_type_add prop_type_change prop_type_delete prop_type_get prop_type_list pum_getpos pumvisible py3eval pyeval pyxeval rand range readblob readdir readdirex readfile reduce reg_executing
160160
syn keyword vimFuncName contained reg_recording reltime reltimefloat reltimestr remote_expr remote_foreground remote_peek remote_read remote_send remote_startserver remove rename repeat resolve reverse round rubyeval screenattr screenchar screenchars screencol screenpos screenrow screenstring search searchcount searchdecl searchpair searchpairpos searchpos server2client serverlist setbufline setbufvar setcellwidths setcharpos setcharsearch setcmdline setcmdpos setcursorcharpos setenv setfperm setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar settagstack setwinvar sha256 shellescape shiftwidth sign_define sign_getdefined sign_getplaced sign_jump sign_place sign_placelist sign_undefine sign_unplace sign_unplacelist simplify sin sinh slice
161161
syn keyword vimFuncName contained sort sound_clear sound_playevent sound_playfile sound_stop soundfold spellbadword spellsuggest split sqrt srand state str2blob str2float str2list str2nr strcharlen strcharpart strchars strdisplaywidth strftime strgetchar stridx string strlen strpart strptime strridx strtrans strutf16len strwidth submatch substitute swapfilelist swapinfo swapname synID synIDattr synIDtrans synconcealed synstack system systemlist tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname term_dumpdiff term_dumpload term_dumpwrite term_getaltscreen term_getansicolors term_getattr term_getcursor term_getjob term_getline term_getscrolled term_getsize term_getstatus term_gettitle term_gettty term_list term_scrape term_sendkeys term_setansicolors
162-
syn keyword vimFuncName contained term_setapi term_setkill term_setrestore term_setsize term_start term_wait terminalprops test_alloc_fail test_autochdir test_feedinput test_garbagecollect_now test_garbagecollect_soon test_getvalue test_gui_event test_ignore_error test_mswin_event test_null_blob test_null_channel test_null_dict test_null_function test_null_job test_null_list test_null_partial test_null_string test_null_tuple test_option_not_set test_override test_refcount test_setmouse test_settime test_srand_seed test_unknown test_void timer_info timer_pause timer_start timer_stop timer_stopall tolower toupper tr trim trunc tuple2list type typename undofile undotree uniq utf16idx values virtcol virtcol2col visualmode wildmenumode win_execute win_findbuf win_getid
163-
syn keyword vimFuncName contained win_gettype win_gotoid win_id2tabwin win_id2win win_move_separator win_move_statusline win_screenpos win_splitmove winbufnr wincol windowsversion winheight winlayout winline winnr winrestcmd winrestview winsaveview winwidth wordcount writefile xor
162+
syn keyword vimFuncName contained term_setapi term_setkill term_setrestore term_setsize term_start term_wait terminalprops test_alloc_fail test_autochdir test_feedinput test_garbagecollect_now test_garbagecollect_soon test_getvalue test_gui_event test_ignore_error test_mswin_event test_null_blob test_null_channel test_null_dict test_null_function test_null_job test_null_list test_null_partial test_null_string test_null_tuple test_option_not_set test_override test_refcount test_setmouse test_settime test_srand_seed test_unknown test_void timer_info timer_pause timer_start timer_stop timer_stopall tolower toupper tr trim trunc tuple2list type typename undofile undotree uniq utf16idx values virtcol virtcol2col visualmode wildmenumode wildtrigger win_execute win_findbuf
163+
syn keyword vimFuncName contained win_getid win_gettype win_gotoid win_id2tabwin win_id2win win_move_separator win_move_statusline win_screenpos win_splitmove winbufnr wincol windowsversion winheight winlayout winline winnr winrestcmd winrestview winsaveview winwidth wordcount writefile xor
164164
" Predefined variable names {{{2
165165
" GEN_SYN_VIM: vimVarName, START_STR='syn keyword vimVimVarName contained', END_STR=''
166166
syn keyword vimVimVarName contained count count1 prevcount errmsg warningmsg statusmsg shell_error this_session version lnum termresponse fname lang lc_time ctype charconvert_from charconvert_to fname_in fname_out fname_new fname_diff cmdarg foldstart foldend folddashes foldlevel progname servername dying exception throwpoint register cmdbang insertmode val key profiling fcs_reason fcs_choice beval_bufnr beval_winnr beval_winid beval_lnum beval_col beval_text scrollstart swapname swapchoice swapcommand char mouse_win mouse_winid mouse_lnum mouse_col operator searchforward hlsearch oldfiles windowid progpath completed_item option_new option_old option_oldlocal option_oldglobal option_command option_type errors false true none null numbermax numbermin numbersize

src/cmdexpand.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ nextwild(
238238
cmdline_info_T *ccline = get_cmdline_info();
239239
int i;
240240
char_u *p;
241+
int from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
241242

242243
if (xp->xp_numfiles == -1)
243244
{
@@ -269,17 +270,22 @@ nextwild(
269270
return FAIL;
270271
}
271272

273+
i = (int)(xp->xp_pattern - ccline->cmdbuff);
274+
xp->xp_pattern_len = ccline->cmdpos - i;
275+
276+
// Skip showing matches if prefix is invalid during wildtrigger()
277+
if (from_wildtrigger_func && xp->xp_context == EXPAND_COMMANDS
278+
&& xp->xp_pattern_len == 0)
279+
return FAIL;
280+
272281
// If cmd_silent is set then don't show the dots, because redrawcmd() below
273282
// won't remove them.
274-
if (!cmd_silent)
283+
if (!cmd_silent && !from_wildtrigger_func)
275284
{
276285
msg_puts("..."); // show that we are busy
277286
out_flush();
278287
}
279288

280-
i = (int)(xp->xp_pattern - ccline->cmdbuff);
281-
xp->xp_pattern_len = ccline->cmdpos - i;
282-
283289
if (type == WILD_NEXT || type == WILD_PREV
284290
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN)
285291
{

src/evalfunc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3126,6 +3126,8 @@ static funcentry_T global_functions[] =
31263126
ret_string, f_visualmode},
31273127
{"wildmenumode", 0, 0, 0, NULL,
31283128
ret_number, f_wildmenumode},
3129+
{"wildtrigger", 0, 0, 0, NULL,
3130+
ret_void, f_wildtrigger},
31293131
{"win_execute", 2, 3, FEARG_2, arg23_win_execute,
31303132
ret_string, f_win_execute},
31313133
{"win_findbuf", 1, 1, FEARG_1, arg1_number,

src/ex_getln.c

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -957,9 +957,11 @@ cmdline_wildchar_complete(
957957
}
958958
else // typed p_wc first time
959959
{
960-
if (c == p_wc || c == p_wcm)
960+
if (c == p_wc || c == p_wcm || c == K_WILD)
961961
{
962962
options |= WILD_MAY_EXPAND_PATTERN;
963+
if (c == K_WILD)
964+
options |= WILD_FUNC_TRIGGER;
963965
if (pre_incsearch_pos)
964966
xp->xp_pre_incsearch_pos = *pre_incsearch_pos;
965967
else
@@ -1395,7 +1397,7 @@ cmdline_browse_history(
13951397
for (;;)
13961398
{
13971399
// one step backwards
1398-
if (c == K_UP|| c == K_S_UP || c == Ctrl_P
1400+
if (c == K_UP || c == K_S_UP || c == Ctrl_P
13991401
|| c == K_PAGEUP || c == K_KPAGEUP)
14001402
{
14011403
if (hiscnt == get_hislen()) // first time
@@ -1818,9 +1820,9 @@ getcmdline_int(
18181820
*/
18191821
for (;;)
18201822
{
1821-
int trigger_cmdlinechanged = TRUE;
1822-
int end_wildmenu;
1823-
int prev_cmdpos = ccline.cmdpos;
1823+
int trigger_cmdlinechanged = TRUE;
1824+
int end_wildmenu;
1825+
int prev_cmdpos = ccline.cmdpos;
18241826

18251827
VIM_CLEAR(prev_cmdbuff);
18261828

@@ -2058,9 +2060,11 @@ getcmdline_int(
20582060
}
20592061
}
20602062

2061-
// Completion for 'wildchar' or 'wildcharm' key.
2062-
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
2063+
// Completion for 'wildchar', 'wildcharm', and wildtrigger()
2064+
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm || c == K_WILD)
20632065
{
2066+
if (c == K_WILD)
2067+
++emsg_silent; // Silence the bell
20642068
res = cmdline_wildchar_complete(c, firstc != '@', &did_wild_list,
20652069
&wim_index, &xpc, &gotesc,
20662070
#ifdef FEAT_SEARCH_EXTRA
@@ -2069,8 +2073,12 @@ getcmdline_int(
20692073
NULL
20702074
#endif
20712075
);
2076+
if (c == K_WILD)
2077+
--emsg_silent;
20722078
if (res == CMDLINE_CHANGED)
20732079
goto cmdline_changed;
2080+
if (c == K_WILD)
2081+
goto cmdline_not_changed;
20742082
}
20752083

20762084
gotesc = FALSE;
@@ -5109,3 +5117,30 @@ get_user_input(
51095117
cmd_silent = cmd_silent_save;
51105118
}
51115119
#endif
5120+
5121+
/*
5122+
* "wildtrigger()" function
5123+
*/
5124+
void
5125+
f_wildtrigger(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
5126+
{
5127+
if (!(State & MODE_CMDLINE) || char_avail() || wild_menu_showing
5128+
|| cmdline_pum_active())
5129+
return;
5130+
5131+
int cmd_type = get_cmdline_type();
5132+
5133+
if (cmd_type == ':' || cmd_type == '/' || cmd_type == '?')
5134+
{
5135+
// Add K_WILD as a single special key
5136+
char_u key_string[4];
5137+
5138+
key_string[0] = K_SPECIAL;
5139+
key_string[1] = KS_EXTRA;
5140+
key_string[2] = KE_WILD;
5141+
key_string[3] = NUL;
5142+
5143+
// Insert it into the typeahead buffer
5144+
ins_typebuf(key_string, REMAP_NONE, 0, TRUE, FALSE);
5145+
}
5146+
}

0 commit comments

Comments
 (0)