0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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 <girishji@gmail.com>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Girish Palya 2025-07-21 21:26:32 +02:00 committed by Christian Brabandt
parent 689f3bf313
commit b486ed8266
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
15 changed files with 191 additions and 70 deletions

View File

@ -1,4 +1,4 @@
*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 17
*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 21
VIM REFERENCE MANUAL by Bram Moolenaar
@ -757,6 +757,7 @@ virtcol2col({winid}, {lnum}, {col})
Number byte index of a character on screen
visualmode([{expr}]) String last visual mode used
wildmenumode() Number whether 'wildmenu' mode is active
wildtrigger() Number start wildcard expansion
win_execute({id}, {command} [, {silent}])
String execute {command} in window {id}
win_findbuf({bufnr}) List find windows containing {bufnr}
@ -12331,6 +12332,33 @@ wildmenumode() *wildmenumode()*
Return type: |Number|
wildtrigger() *wildtrigger()*
Start wildcard expansion in the command-line, using the
behavior defined by the 'wildmode' and 'wildoptions' settings.
See |cmdline-completion|.
This function also enables completion in search patterns such
as |/|, |?|, |:s|, |:g|, |:v| and |:vimgrep|.
Unlike pressing 'wildchar' manually, this function does not
produce a beep when no matches are found and generally
operates more quietly. This makes it suitable for triggering
completion automatically, such as from an |:autocmd|.
*cmdline-autocompletion*
Example: To make the completion menu pop up automatically as
you type on the command line, use: >
autocmd CmdlineChanged [:/?] call wildtrigger()
set wildmode=noselect:lastused,full wildoptions=pum
<
To retain normal history navigation (up/down keys): >
cnoremap <Up> <C-U><Up>
cnoremap <Down> <C-U><Down>
<
Return value is always 0.
Return type: |Number|
win_execute({id}, {command} [, {silent}]) *win_execute()*
Like `execute()` but in the context of window {id}.
The window will temporarily be made the current window,

View File

@ -1,4 +1,4 @@
*cmdline.txt* For Vim version 9.1. Last change: 2025 Jun 28
*cmdline.txt* For Vim version 9.1. Last change: 2025 Jul 21
VIM REFERENCE MANUAL by Bram Moolenaar
@ -479,6 +479,8 @@ When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
ending up back to what was typed. If the first match is not what you wanted,
you can use <S-Tab> or CTRL-P to go straight back to what you typed.
See also |wildtrigger()|.
The 'wildmenu' option can be set to show the matches just above the command
line.

View File

@ -1,4 +1,4 @@
*options.txt* For Vim version 9.1. Last change: 2025 Jul 20
*options.txt* For Vim version 9.1. Last change: 2025 Jul 21
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|.
< 'wildchar' also enables completion in search pattern contexts such as
|/|, |?|, |:s|, |:g|, |:v|, and |:vim|. To insert a literal <Tab>
instead of triggering completion, type <C-V><Tab> or "\t".
See also |'wildoptions'|.
See also 'wildoptions' and |wildtrigger()|.
NOTE: This option is set to the Vi default value when 'compatible' is
set and to the Vim default value when 'compatible' is reset.

View File

@ -6620,6 +6620,7 @@ cmdarg-variable eval.txt /*cmdarg-variable*
cmdbang-variable eval.txt /*cmdbang-variable*
cmdcomplete_info() builtin.txt /*cmdcomplete_info()*
cmdline-arguments vi_diff.txt /*cmdline-arguments*
cmdline-autocompletion builtin.txt /*cmdline-autocompletion*
cmdline-changed version5.txt /*cmdline-changed*
cmdline-completion cmdline.txt /*cmdline-completion*
cmdline-editing cmdline.txt /*cmdline-editing*
@ -11608,6 +11609,7 @@ whitespace pattern.txt /*whitespace*
wildcard editing.txt /*wildcard*
wildcards editing.txt /*wildcards*
wildmenumode() builtin.txt /*wildmenumode()*
wildtrigger() builtin.txt /*wildtrigger()*
win-scrolled-resized windows.txt /*win-scrolled-resized*
win16 os_win32.txt /*win16*
win32 os_win32.txt /*win32*

View File

@ -1,4 +1,4 @@
*usr_41.txt* For Vim version 9.1. Last change: 2025 Jul 05
*usr_41.txt* For Vim version 9.1. Last change: 2025 Jul 21
VIM USER MANUAL - by Bram Moolenaar
@ -1233,6 +1233,7 @@ Mappings and Menus: *mapping-functions*
mapset() restore a mapping
menu_info() get information about a menu item
wildmenumode() check if the wildmode is active
wildtrigger() start wildcard expansion
Testing: *test-functions*
assert_equal() assert that two expressions values are equal

View File

@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2025 Jul 20
*version9.txt* For Vim version 9.1. Last change: 2025 Jul 21
VIM REFERENCE MANUAL by Bram Moolenaar
@ -41601,6 +41601,7 @@ Completion~
"nosort" - do not sort completion results
"preinsert" - highlight to be inserted values
"nearest" - sort completion results by distance to cursor
- new function |wildtrigger()| to trigger wildcard expansion
Platform specific~
-----------------
@ -41765,6 +41766,7 @@ Functions: ~
|str2blob()| convert a List of strings into a blob
|test_null_tuple()| return a null tuple
|tuple2list()| turn a Tuple of items into a List
|wildtrigger()| trigger wildcard expansion
Autocommands: ~

View File

@ -2,7 +2,7 @@
" Language: Vim script
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
" Doug Kearns <dougkearns@gmail.com>
" Last Change: 2025 Jul 18
" Last Change: 2025 Jul 21
" Former Maintainer: Charles E. Campbell
" DO NOT CHANGE DIRECTLY.
@ -141,7 +141,7 @@ syn match vimUserAutoEvent contained "\<\h\w*\>" skipwhite nextgroup=vimUserAuto
" Highlight commonly used Groupnames {{{2
" GEN_SYN_VIM: vimGroup, START_STR='syn keyword vimGroup contained', END_STR=''
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
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
" Default highlighting groups {{{2
" 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
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
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
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
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
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
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
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
" Predefined variable names {{{2
" GEN_SYN_VIM: vimVarName, START_STR='syn keyword vimVimVarName contained', END_STR=''
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

View File

@ -238,6 +238,7 @@ nextwild(
cmdline_info_T *ccline = get_cmdline_info();
int i;
char_u *p;
int from_wildtrigger_func = options & WILD_FUNC_TRIGGER;
if (xp->xp_numfiles == -1)
{
@ -269,17 +270,22 @@ nextwild(
return FAIL;
}
i = (int)(xp->xp_pattern - ccline->cmdbuff);
xp->xp_pattern_len = ccline->cmdpos - i;
// Skip showing matches if prefix is invalid during wildtrigger()
if (from_wildtrigger_func && xp->xp_context == EXPAND_COMMANDS
&& xp->xp_pattern_len == 0)
return FAIL;
// If cmd_silent is set then don't show the dots, because redrawcmd() below
// won't remove them.
if (!cmd_silent)
if (!cmd_silent && !from_wildtrigger_func)
{
msg_puts("..."); // show that we are busy
out_flush();
}
i = (int)(xp->xp_pattern - ccline->cmdbuff);
xp->xp_pattern_len = ccline->cmdpos - i;
if (type == WILD_NEXT || type == WILD_PREV
|| type == WILD_PAGEUP || type == WILD_PAGEDOWN)
{

View File

@ -3126,6 +3126,8 @@ static funcentry_T global_functions[] =
ret_string, f_visualmode},
{"wildmenumode", 0, 0, 0, NULL,
ret_number, f_wildmenumode},
{"wildtrigger", 0, 0, 0, NULL,
ret_void, f_wildtrigger},
{"win_execute", 2, 3, FEARG_2, arg23_win_execute,
ret_string, f_win_execute},
{"win_findbuf", 1, 1, FEARG_1, arg1_number,

View File

@ -957,9 +957,11 @@ cmdline_wildchar_complete(
}
else // typed p_wc first time
{
if (c == p_wc || c == p_wcm)
if (c == p_wc || c == p_wcm || c == K_WILD)
{
options |= WILD_MAY_EXPAND_PATTERN;
if (c == K_WILD)
options |= WILD_FUNC_TRIGGER;
if (pre_incsearch_pos)
xp->xp_pre_incsearch_pos = *pre_incsearch_pos;
else
@ -2058,9 +2060,11 @@ getcmdline_int(
}
}
// Completion for 'wildchar' or 'wildcharm' key.
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
// Completion for 'wildchar', 'wildcharm', and wildtrigger()
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm || c == K_WILD)
{
if (c == K_WILD)
++emsg_silent; // Silence the bell
res = cmdline_wildchar_complete(c, firstc != '@', &did_wild_list,
&wim_index, &xpc, &gotesc,
#ifdef FEAT_SEARCH_EXTRA
@ -2069,8 +2073,12 @@ getcmdline_int(
NULL
#endif
);
if (c == K_WILD)
--emsg_silent;
if (res == CMDLINE_CHANGED)
goto cmdline_changed;
if (c == K_WILD)
goto cmdline_not_changed;
}
gotesc = FALSE;
@ -5109,3 +5117,30 @@ get_user_input(
cmd_silent = cmd_silent_save;
}
#endif
/*
* "wildtrigger()" function
*/
void
f_wildtrigger(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
if (!(State & MODE_CMDLINE) || char_avail() || wild_menu_showing
|| cmdline_pum_active())
return;
int cmd_type = get_cmdline_type();
if (cmd_type == ':' || cmd_type == '/' || cmd_type == '?')
{
// Add K_WILD as a single special key
char_u key_string[4];
key_string[0] = K_SPECIAL;
key_string[1] = KS_EXTRA;
key_string[2] = KE_WILD;
key_string[3] = NUL;
// Insert it into the typeahead buffer
ins_typebuf(key_string, REMAP_NONE, 0, TRUE, FALSE);
}
}

View File

@ -279,6 +279,7 @@ enum key_extra
, KE_S_BS = 105 // shift + <BS>
, KE_SID = 106 // <SID> special key, followed by {nr};
, KE_ESC = 107 // used for K_ESC
, KE_WILD = 108 // triggers wildmode completion
};
/*
@ -491,6 +492,8 @@ enum key_extra
#define K_SCRIPT_COMMAND TERMCAP2KEY(KS_EXTRA, KE_SCRIPT_COMMAND)
#define K_SID TERMCAP2KEY(KS_EXTRA, KE_SID)
#define K_WILD TERMCAP2KEY(KS_EXTRA, KE_WILD)
// Bits for modifier mask
// 0x01 cannot be used, because the modifier must be 0x02 or higher
#define MOD_MASK_SHIFT 0x02

View File

@ -39,6 +39,7 @@ void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv);
void f_getcmdtype(typval_T *argvars, typval_T *rettv);
void f_setcmdline(typval_T *argvars, typval_T *rettv);
void f_setcmdpos(typval_T *argvars, typval_T *rettv);
void f_wildtrigger(typval_T *argvars, typval_T *rettv);
int get_cmdline_firstc(void);
int get_list_range(char_u **str, int *num1, int *num2);
char *did_set_cedit(optset_T *args);

View File

@ -4329,42 +4329,63 @@ func Test_cmdcomplete_info()
autocmd CmdlineLeavePre * call expand('test_cmdline.*')
autocmd CmdlineLeavePre * let g:cmdcomplete_info = string(cmdcomplete_info())
augroup END
" Disable char_avail so that wildtrigger() does not bail out
call test_override("char_avail", 1)
cnoremap <F8> <C-R>=wildtrigger()[-1]<CR>
call assert_equal({}, cmdcomplete_info())
for trig in ["\<Tab>", "\<F8>"]
new
call assert_equal({}, cmdcomplete_info())
call feedkeys(":h echom\<cr>", "tx") " No expansion
call assert_equal('{}', g:cmdcomplete_info)
call feedkeys(":h echoms\<tab>\<cr>", "tx")
call feedkeys($":h echoms{trig}\<cr>", "tx")
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
\ g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<tab>\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': 1}',
\ g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<tab>\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<tab>\<tab>\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 0, ''matches'': ['':echom'', '':echomsg''], ''selected'': -1}',
\ g:cmdcomplete_info)
set wildoptions=pum
call feedkeys(":h echoms\<tab>\<cr>", "tx")
call feedkeys($":h echoms{trig}\<cr>", "tx")
call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 0}',
\ g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<tab>\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': 1}',
\ g:cmdcomplete_info)
call feedkeys(":h echom\<tab>\<tab>\<tab>\<cr>", "tx")
call feedkeys($":h echom{trig}\<tab>\<tab>\<cr>", "tx")
call assert_equal(
\ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': -1}',
\ g:cmdcomplete_info)
bw!
set wildoptions&
endfor
" wildtrigger() should not show matches when prefix is invalid
for pat in ["", " ", "22"]
call feedkeys($":{pat}\<F8>\<cr>", "tx") " No expansion
call assert_equal('{}', g:cmdcomplete_info)
endfor
augroup test_CmdlineLeavePre | autocmd! | augroup END
call test_override("char_avail", 0)
unlet g:cmdcomplete_info
cunmap <F8>
endfunc
func Test_redrawtabpanel_error()
@ -4387,6 +4408,7 @@ func Test_search_complete()
new
cnoremap <buffer><expr> <F9> GetComplInfo()
cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR>
" Pressing <Tab> inserts tab character
set wildchar=0
@ -4397,7 +4419,7 @@ func Test_search_complete()
call setline(1, ['the', 'these', 'thethe', 'thethere', 'foobar'])
for trig in ["\<tab>", "\<c-z>"]
for trig in ["\<tab>", "\<c-z>", "\<F8>"]
" Test menu first item and order
call feedkeys($"gg2j/t{trig}\<f9>", 'tx')
call assert_equal(['the', 'thethere', 'there', 'these', 'thethe'], g:compl_info.matches)
@ -4610,10 +4632,11 @@ func Test_range_complete()
endfunc
new
cnoremap <buffer><expr> <F9> GetComplInfo()
cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR>
call setline(1, ['ab', 'ba', 'ca', 'af'])
for trig in ["\<tab>", "\<c-z>"]
for trig in ["\<tab>", "\<c-z>", "\<F8>"]
call feedkeys($":%s/a{trig}\<f9>", 'xt')
call assert_equal(['ab', 'a', 'af'], g:compl_info.matches)
call feedkeys($":vim9cmd :%s/a{trig}\<f9>", 'xt')
@ -4699,25 +4722,35 @@ func Test_cmdline_changed()
autocmd CmdlineChanged * if getcmdline() =~ g:cmdprefix | let g:cmdchg_count += 1 | endif
augroup END
" Disable char_avail so that wildtrigger() does not bail out
call test_override("char_avail", 1)
new
cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR>
set wildmenu
set wildmode=full
let g:cmdprefix = 'echomsg'
for trig in ["\<Tab>", "\<F8>"]
let g:cmdchg_count = 0
call feedkeys(":echomsg\<Tab>", "tx")
call feedkeys($":echomsg{trig}", "tx")
call assert_equal(1, g:cmdchg_count) " once only for 'g', not again for <Tab>
endfor
let g:cmdchg_count = 0
let g:cmdprefix = 'echo'
call feedkeys(":ech\<Tab>", "tx")
for trig in ["\<Tab>", "\<F8>"]
let g:cmdchg_count = 0
call feedkeys($":ech{trig}", "tx")
call assert_equal(1, g:cmdchg_count) " (once for 'h' and) once for 'o'
endfor
set wildmode=noselect,full
let g:cmdchg_count = 0
let g:cmdprefix = 'ech'
call feedkeys(":ech\<Tab>", "tx")
for trig in ["\<Tab>", "\<F8>"]
let g:cmdchg_count = 0
call feedkeys($":ech{trig}", "tx")
call assert_equal(1, g:cmdchg_count) " once for 'h', not again for <tab>
endfor
command! -nargs=+ -complete=custom,TestComplete Test echo
@ -4726,10 +4759,12 @@ func Test_cmdline_changed()
endfunc
set wildoptions=fuzzy wildmode=full
let g:cmdchg_count = 0
let g:cmdprefix = 'Test \(AbC\|abc\)'
call feedkeys(":Test abc\<Tab>", "tx")
for trig in ["\<Tab>", "\<F8>"]
let g:cmdchg_count = 0
call feedkeys($":Test abc{trig}", "tx")
call assert_equal(2, g:cmdchg_count) " once for 'c', again for 'AbC'
endfor
bw!
set wildmode& wildmenu& wildoptions&
@ -4738,6 +4773,7 @@ func Test_cmdline_changed()
unlet g:cmdprefix
delfunc TestComplete
delcommand Test
call test_override("char_avail", 0)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1576,
/**/
1575,
/**/

View File

@ -897,6 +897,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define BUF_DIFF_FILTER 0x2000
#define WILD_KEEP_SOLE_ITEM 0x4000
#define WILD_MAY_EXPAND_PATTERN 0x8000
#define WILD_FUNC_TRIGGER 0x10000 // called from wildtrigger()
// Flags for expand_wildcards()
#define EW_DIR 0x01 // include directory names