neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 9377db2545090fbea740a5befcf931f6db11c2e1
parent 8b5d8dfc732eff3a7ba1cc25d6e5b7c210f761a4
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Wed, 23 Jul 2025 06:12:50 +0800

vim-patch:9.1.1576: cannot easily trigger wildcard expansion (#35022)

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 vim/vim#16759.

closes: vim/vim#17806

https://github.com/vim/vim/commit/b486ed8266d3b8cd1ffab7d7f302fbd6d5a55c70

While at it, also make Ctrl-Z trigger search completion.

Co-authored-by: Girish Palya <girishji@gmail.com>
Diffstat:
Mruntime/doc/cmdline.txt | 2++
Mruntime/doc/news.txt | 1+
Mruntime/doc/options.txt | 2+-
Mruntime/doc/usr_41.txt | 1+
Mruntime/doc/vimfn.txt | 27+++++++++++++++++++++++++++
Mruntime/lua/vim/_meta/options.lua | 2+-
Mruntime/lua/vim/_meta/vimfn.lua | 26++++++++++++++++++++++++++
Mruntime/syntax/vim.vim | 2+-
Msrc/nvim/cmdexpand.c | 18+++++++++++++-----
Msrc/nvim/cmdexpand.h | 1+
Msrc/nvim/eval.lua | 30++++++++++++++++++++++++++++++
Msrc/nvim/ex_getln.c | 46++++++++++++++++++++++++++++++++++++++++++----
Msrc/nvim/keycodes.h | 9++++++++-
Msrc/nvim/options.lua | 2+-
Mtest/old/testdir/test_cmdline.vim | 133++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
15 files changed, 240 insertions(+), 62 deletions(-)

diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt @@ -451,6 +451,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. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt @@ -296,6 +296,7 @@ VIMSCRIPT • |cmdcomplete_info()| gets current cmdline completion info. • |getcompletiontype()| gets command-line completion type for any string. • |prompt_getinput()| gets current user-input in prompt-buffer. +• |wildtrigger()| triggers command-line expansion. ============================================================================== CHANGED FEATURES *news-changed* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt @@ -7212,7 +7212,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()|. *'wildcharm'* *'wcm'* 'wildcharm' 'wcm' number (default 0) diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt @@ -1036,6 +1036,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 Signs: *sign-functions* sign_define() define or update a sign diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt @@ -11878,6 +11878,33 @@ wildmenumode() *wildmenumode()* Return: ~ (`any`) +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: >vim + autocmd CmdlineChanged [:/?] call wildtrigger() + set wildmode=noselect:lastused,full wildoptions=pum +< + To retain normal history navigation (up/down keys): >vim + cnoremap <Up> <C-U><Up> + cnoremap <Down> <C-U><Down> +< + Return value is always 0. + + Return: ~ + (`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, diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua @@ -7865,7 +7865,7 @@ vim.go.ww = vim.go.whichwrap --- '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()`. --- --- @type integer vim.o.wildchar = 9 diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua @@ -10813,6 +10813,32 @@ function vim.fn.wait(timeout, condition, interval) end --- @return any function vim.fn.wildmenumode() end +--- 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: >vim +--- autocmd CmdlineChanged [:/?] call wildtrigger() +--- set wildmode=noselect:lastused,full wildoptions=pum +--- < +--- To retain normal history navigation (up/down keys): >vim +--- cnoremap <Up> <C-U><Up> +--- cnoremap <Down> <C-U><Down> +--- < +--- Return value is always 0. +--- +--- @return number +function vim.fn.wildtrigger() end + --- Like `execute()` but in the context of window {id}. --- The window will temporarily be made the current window, --- without triggering autocommands or changing directory. When diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim @@ -99,7 +99,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='' diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c @@ -254,6 +254,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape) { CmdlineInfo *const ccline = get_cmdline_info(); char *p; + bool from_wildtrigger_func = options & WILD_FUNC_TRIGGER; if (xp->xp_numfiles == -1) { pre_incsearch_pos = xp->xp_pre_incsearch_pos; @@ -280,17 +281,24 @@ int nextwild(expand_T *xp, int type, int options, bool escape) return FAIL; } + int i = (int)(xp->xp_pattern - ccline->cmdbuff); + assert(ccline->cmdpos >= i); + xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)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 && !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) { + if (!cmd_silent && !from_wildtrigger_func + && !(ui_has(kUICmdline) || ui_has(kUIWildmenu))) { msg_puts("..."); // show that we are busy ui_flush(); } - int i = (int)(xp->xp_pattern - ccline->cmdbuff); - assert(ccline->cmdpos >= i); - xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i; - if (type == WILD_NEXT || type == WILD_PREV || type == WILD_PAGEUP || type == WILD_PAGEDOWN || type == WILD_PUM_WANT) { diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h @@ -42,6 +42,7 @@ enum { BUF_DIFF_FILTER = 0x2000, WILD_KEEP_SOLE_ITEM = 0x4000, WILD_MAY_EXPAND_PATTERN = 0x8000, + WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger() }; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua @@ -13069,6 +13069,36 @@ M.funcs = { params = {}, signature = 'wildmenumode()', }, + wildtrigger = { + desc = [==[ + 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: >vim + autocmd CmdlineChanged [:/?] call wildtrigger() + set wildmode=noselect:lastused,full wildoptions=pum + < + To retain normal history navigation (up/down keys): >vim + cnoremap <Up> <C-U><Up> + cnoremap <Down> <C-U><Down> + < + Return value is always 0. + ]==], + name = 'wildtrigger', + params = {}, + returns = 'number', + signature = 'wildtrigger()', + }, win_execute = { args = { 2, 3 }, base = 2, diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c @@ -1147,8 +1147,11 @@ static int command_line_wildchar_complete(CommandLineState *s) res = OK; // don't insert 'wildchar' now } } else { // typed p_wc first time - if (s->c == p_wc || s->c == p_wcm) { + if (s->c == p_wc || s->c == p_wcm || s->c == K_WILD || s->c == Ctrl_Z) { options |= WILD_MAY_EXPAND_PATTERN; + if (s->c == K_WILD) { + options |= WILD_FUNC_TRIGGER; + } s->xpc.xp_pre_incsearch_pos = s->is_state.search_start; } s->wim_index = 0; @@ -1442,11 +1445,22 @@ static int command_line_execute(VimState *state, int key) } } - // Completion for 'wildchar' or 'wildcharm' key. - if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm || s->c == Ctrl_Z) { - if (command_line_wildchar_complete(s) == CMDLINE_CHANGED) { + // Completion for 'wildchar', 'wildcharm', and wildtrigger() + if ((s->c == p_wc && !s->gotesc && KeyTyped) || s->c == p_wcm || s->c == K_WILD + || s->c == Ctrl_Z) { + if (s->c == K_WILD) { + emsg_silent++; // Silence the bell + } + int res = command_line_wildchar_complete(s); + if (s->c == K_WILD) { + emsg_silent--; + } + if (res == CMDLINE_CHANGED) { return command_line_changed(s); } + if (s->c == K_WILD) { + return command_line_not_changed(s); + } } s->gotesc = false; @@ -4907,3 +4921,27 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const need_wait_return = false; msg_didout = false; } + +/// "wildtrigger()" function +void f_wildtrigger(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + if (!(State & MODE_CMDLINE) || char_avail() + || (wild_menu_showing != 0 && wild_menu_showing != WM_LIST) + || 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 + uint8_t 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((char *)key_string, REMAP_NONE, 0, true, false); + } +} diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h @@ -215,10 +215,15 @@ enum key_extra { // KE_FOCUSGAINED = 98, // focus gained // KE_FOCUSLOST = 99, // focus lost KE_MOUSEMOVE = 100, // mouse moved with no button down - // KE_CANCEL = 101, // return from vgetc() + // KE_MOUSEMOVE_XY = 101, + // KE_CANCEL = 102, // return from vgetc() KE_EVENT = 102, // event KE_LUA = 103, // Lua special key KE_COMMAND = 104, // <Cmd> special key + // KE_S_BS = 105, + // KE_SID = 106, + // KE_ESC = 107, + KE_WILD = 108, // triggers wildmode completion }; // the three byte codes are replaced with the following int when using vgetc() @@ -451,6 +456,8 @@ enum key_extra { #define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND) #define K_LUA TERMCAP2KEY(KS_EXTRA, KE_LUA) +#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 diff --git a/src/nvim/options.lua b/src/nvim/options.lua @@ -10173,7 +10173,7 @@ local options = { < '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()|. ]=], full_name = 'wildchar', scope = { 'global' }, diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim @@ -4361,42 +4361,64 @@ func Test_cmdcomplete_info() autocmd CmdlineLeavePre * call expand('test_cmdline.*') autocmd CmdlineLeavePre * let g:cmdcomplete_info = string(cmdcomplete_info()) augroup END - new + + " Disable char_avail so that wildtrigger() does not bail out + call Ntest_override("char_avail", 1) + + cnoremap <F8> <C-R>=wildtrigger()[-1]<CR> + 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 assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) - call feedkeys(":h echom\<tab>\<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 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 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 assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) - call feedkeys(":h echom\<tab>\<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 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 assert_equal( - \ '{''cmdline_orig'': ''h echom'', ''pum_visible'': 1, ''matches'': ['':echom'', '':echomsg''], ''selected'': -1}', - \ g:cmdcomplete_info) - bw! - set wildoptions& + 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{trig}\<cr>", "tx") + call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) + 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{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{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{trig}\<cr>", "tx") + call assert_equal('{''cmdline_orig'': '''', ''pum_visible'': 0, ''matches'': [], ''selected'': 0}', g:cmdcomplete_info) + 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{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{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& + set wildoptions= " Accommodate Nvim default + 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 Ntest_override("char_avail", 0) + unlet g:cmdcomplete_info + cunmap <F8> endfunc " Test wildcharm completion for '/' and '?' search @@ -4414,6 +4436,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 @@ -4424,7 +4447,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) @@ -4637,10 +4660,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') @@ -4727,25 +4751,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 Ntest_override("char_avail", 1) + new + cnoremap <buffer> <F8> <C-R>=wildtrigger()[-1]<CR> set wildmenu set wildmode=full let g:cmdprefix = 'echomsg' - let g:cmdchg_count = 0 - call feedkeys(":echomsg\<Tab>", "tx") - call assert_equal(1, g:cmdchg_count) " once only for 'g', not again for <Tab> + for trig in ["\<Tab>", "\<F8>"] + let g:cmdchg_count = 0 + 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") - call assert_equal(1, g:cmdchg_count) " (once for 'h' and) once for 'o' + 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") - call assert_equal(1, g:cmdchg_count) " once for 'h', not again for <tab> + 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 @@ -4754,10 +4788,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") - call assert_equal(2, g:cmdchg_count) " once for 'c', again for 'AbC' + 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& @@ -4766,6 +4802,7 @@ func Test_cmdline_changed() unlet g:cmdprefix delfunc TestComplete delcommand Test + call Ntest_override("char_avail", 0) endfunc " vim: shiftwidth=2 sts=2 expandtab