patch 9.1.1576: cannot easily trigger wildcard expansion Commit: https://github.com/vim/vim/commit/b486ed8266d3b8cd1ffab7d7f302fbd6d5a55c70 Author: Girish Palya <giris...@gmail.com> Date: Mon Jul 21 21:26:32 2025 +0200
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 <giris...@gmail.com> Co-authored-by: zeertzjq <zeert...@outlook.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index e1847b1d3..c7d3b401f 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -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, diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index a15debe5e..edc0f0fc3 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -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. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d4bdc8196..0a1d955fb 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -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 " ". - 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. diff --git a/runtime/doc/tags b/runtime/doc/tags index 8e2fb0e96..5535036b2 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -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* diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 02d58f0d8..d263bed9e 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -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 diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index b49b86a2b..79aec13ad 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -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: ~ diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index c6f3943d2..4e394d35a 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -2,7 +2,7 @@ " Language: Vim script " Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com> " Doug Kearns <dougkea...@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 diff --git a/src/cmdexpand.c b/src/cmdexpand.c index a7a5acf95..bddfe8ca6 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -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) { diff --git a/src/evalfunc.c b/src/evalfunc.c index ec21087e2..3c8339ee3 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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, diff --git a/src/ex_getln.c b/src/ex_getln.c index 5ee94d219..560324c6e 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -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 @@ -1395,7 +1397,7 @@ cmdline_browse_history( for (;;) { // one step backwards - if (c == K_UP|| c == K_S_UP || c == Ctrl_P + if (c == K_UP || c == K_S_UP || c == Ctrl_P || c == K_PAGEUP || c == K_KPAGEUP) { if (hiscnt == get_hislen()) // first time @@ -1818,9 +1820,9 @@ getcmdline_int( */ for (;;) { - int trigger_cmdlinechanged = TRUE; - int end_wildmenu; - int prev_cmdpos = ccline.cmdpos; + int trigger_cmdlinechanged = TRUE; + int end_wildmenu; + int prev_cmdpos = ccline.cmdpos; VIM_CLEAR(prev_cmdbuff); @@ -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); + } +} diff --git a/src/keymap.h b/src/keymap.h index 29e2a055c..e993e0999 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -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 diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro index 6c93ac755..7270469a2 100644 --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -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); diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 697b01acd..4e4d34caa 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -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 - new + + " 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()) - 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& + 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' - 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 @@ -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") - 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& @@ -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 diff --git a/src/version.c b/src/version.c index 8e4cfcc2b..11357b22e 100644 --- a/src/version.c +++ b/src/version.c @@ -719,6 +719,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1576, /**/ 1575, /**/ diff --git a/src/vim.h b/src/vim.h index 74a349dcc..94a10a322 100644 --- a/src/vim.h +++ b/src/vim.h @@ -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 -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1udwRg-002B9t-99%40256bit.org.