diff --git a/src/cmdexpand.c b/src/cmdexpand.c index ab849e2964..4ef1879117 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -455,9 +455,8 @@ cmdline_pum_active(void) * items and refresh the screen. */ void -cmdline_pum_remove(cmdline_info_T *cclp UNUSED) +cmdline_pum_remove(cmdline_info_T *cclp UNUSED, int defer_redraw) { - int save_p_lz = p_lz; int save_KeyTyped = KeyTyped; #ifdef FEAT_EVAL int save_RedrawingDisabled = RedrawingDisabled; @@ -468,9 +467,15 @@ cmdline_pum_remove(cmdline_info_T *cclp UNUSED) pum_undisplay(); VIM_CLEAR(compl_match_array); compl_match_arraysize = 0; - p_lz = FALSE; // avoid the popup menu hanging around - update_screen(0); - p_lz = save_p_lz; + if (!defer_redraw) + { + int save_p_lz = p_lz; + p_lz = FALSE; // avoid the popup menu hanging around + update_screen(0); + p_lz = save_p_lz; + } + else + pum_call_update_screen(); redrawcmd(); // When a function is called (e.g. for 'foldtext') KeyTyped might be reset @@ -485,7 +490,7 @@ cmdline_pum_remove(cmdline_info_T *cclp UNUSED) void cmdline_pum_cleanup(cmdline_info_T *cclp) { - cmdline_pum_remove(cclp); + cmdline_pum_remove(cclp, FALSE); wildmenu_cleanup(cclp); } @@ -1068,7 +1073,7 @@ ExpandOne( // The entries from xp_files may be used in the PUM, remove it. if (compl_match_array != NULL) - cmdline_pum_remove(get_cmdline_info()); + cmdline_pum_remove(get_cmdline_info(), FALSE); } xp->xp_selected = 0; diff --git a/src/ex_getln.c b/src/ex_getln.c index 93ce070626..a96ece70c5 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -939,6 +939,7 @@ cmdline_wildchar_complete( int *wim_index_p, expand_T *xp, int *gotesc, + int redraw_if_menu_empty, pos_T *pre_incsearch_pos) { int wim_index = *wim_index_p; @@ -991,6 +992,10 @@ cmdline_wildchar_complete( else res = nextwild(xp, WILD_EXPAND_KEEP, options, escape); + // Remove popup window if no completion items are available + if (redraw_if_menu_empty && xp->xp_numfiles <= 0) + update_screen(0); + // if interrupted while completing, behave like it failed if (got_int) { @@ -1633,7 +1638,7 @@ getcmdline_int( int clear_ccline) // clear ccline first { static int depth = 0; // call depth - int c; + int c = 0; int i; int j; int gotesc = FALSE; // TRUE when just typed @@ -1838,6 +1843,7 @@ getcmdline_int( int trigger_cmdlinechanged = TRUE; int end_wildmenu; int prev_cmdpos = ccline.cmdpos; + int skip_pum_redraw = FALSE; VIM_CLEAR(prev_cmdbuff); @@ -1863,6 +1869,10 @@ getcmdline_int( goto returncmd; } + // Defer screen update to avoid pum flicker during wildtrigger() + if (c == K_WILD && firstc != '@') + skip_pum_redraw = TRUE; + // Get a character. Ignore K_IGNORE and K_NOP, they should not do // anything, such as stop completion. do @@ -2002,7 +2012,12 @@ getcmdline_int( if (end_wildmenu) { if (cmdline_pum_active()) - cmdline_pum_remove(&ccline); + { + skip_pum_redraw = skip_pum_redraw && (vim_isprintc(c) + || c == K_BS || c == Ctrl_H || c == K_DEL + || c == K_KDEL || c == Ctrl_W || c == Ctrl_U); + cmdline_pum_remove(&ccline, skip_pum_redraw); + } if (xpc.xp_numfiles != -1) (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE); did_wild_list = FALSE; @@ -2081,7 +2096,7 @@ getcmdline_int( if (c == K_WILD) ++emsg_silent; // Silence the bell res = cmdline_wildchar_complete(c, firstc != '@', &did_wild_list, - &wim_index, &xpc, &gotesc, + &wim_index, &xpc, &gotesc, c == K_WILD, #ifdef FEAT_SEARCH_EXTRA &is_state.search_start #else @@ -2647,7 +2662,7 @@ returncmd: // if certain special keys like or were used as wildchar. Make // sure to still clean up to avoid memory corruption. if (cmdline_pum_active()) - cmdline_pum_remove(&ccline); + cmdline_pum_remove(&ccline, FALSE); wildmenu_cleanup(&ccline); did_wild_list = FALSE; wim_index = 0; diff --git a/src/proto/cmdexpand.pro b/src/proto/cmdexpand.pro index 2b2cc23e5a..1ace23c5c3 100644 --- a/src/proto/cmdexpand.pro +++ b/src/proto/cmdexpand.pro @@ -3,7 +3,7 @@ int cmdline_fuzzy_complete(char_u *fuzzystr); int nextwild(expand_T *xp, int type, int options, int escape); void cmdline_pum_display(void); int cmdline_pum_active(void); -void cmdline_pum_remove(cmdline_info_T *cclp); +void cmdline_pum_remove(cmdline_info_T *cclp, int defer); void cmdline_pum_cleanup(cmdline_info_T *cclp); int cmdline_compl_startcol(void); char_u *cmdline_compl_pattern(void); diff --git a/src/testdir/dumps/Test_wildtrigger_update_screen_1.dump b/src/testdir/dumps/Test_wildtrigger_update_screen_1.dump new file mode 100644 index 0000000000..0b6383ffe3 --- /dev/null +++ b/src/testdir/dumps/Test_wildtrigger_update_screen_1.dump @@ -0,0 +1,10 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @6| +0#0000001#ffd7ff255|a|b|c|1| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|2| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|3| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|4| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|5| @10| +0#4040ff13#ffffff0@50 +|:+0#0000000&|T|e|s|t|C|m|d| |a> @64 diff --git a/src/testdir/dumps/Test_wildtrigger_update_screen_2.dump b/src/testdir/dumps/Test_wildtrigger_update_screen_2.dump new file mode 100644 index 0000000000..abc804705c --- /dev/null +++ b/src/testdir/dumps/Test_wildtrigger_update_screen_2.dump @@ -0,0 +1,10 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @6| +0#0000001#ffd7ff255|a|b|c|1| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|2| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|3| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|4| @10| +0#4040ff13#ffffff0@50 +|~| @6| +0#0000001#ffd7ff255|a|b|c|5| @10| +0#4040ff13#ffffff0@50 +|:+0#0000000&|T|e|s|t|C|m|d| |a|x> @63 diff --git a/src/testdir/dumps/Test_wildtrigger_update_screen_3.dump b/src/testdir/dumps/Test_wildtrigger_update_screen_3.dump new file mode 100644 index 0000000000..836ea6d15b --- /dev/null +++ b/src/testdir/dumps/Test_wildtrigger_update_screen_3.dump @@ -0,0 +1,10 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|T|e|s|t|C|m|d| |a|x> @45|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 5bc698106a..e6dcfd3998 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -4822,4 +4822,41 @@ func Test_cmdline_changed() call test_override("char_avail", 0) endfunc +func Test_wildtrigger_update_screen() + CheckScreendump + let lines =<< trim [SCRIPT] + command! -nargs=* -complete=customlist,TestFn TestCmd echo + func TestFn(cmdarg, b, c) + if a:cmdarg == 'ax' + return [] + else + return map(range(1, 5), 'printf("abc%d", v:val)') + endif + endfunc + set wildmode=noselect,full + set wildoptions=pum + set wildmenu + cnoremap =wildtrigger()[-1] + [SCRIPT] + call writefile(lines, 'XTest_wildtrigger', 'D') + let buf = RunVimInTerminal('-S XTest_wildtrigger', {'rows': 10}) + + call term_sendkeys(buf, ":TestCmd a\") + call VerifyScreenDump(buf, 'Test_wildtrigger_update_screen_1', {}) + + " Typing a character when pum is open does not close the pum window + " This is needed to prevent pum window from flickering during + " ':h cmdline-autocompletion'. + call term_sendkeys(buf, "x") + call VerifyScreenDump(buf, 'Test_wildtrigger_update_screen_2', {}) + + " pum window is closed when no completion candidates are available + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_wildtrigger_update_screen_3', {}) + + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) + cnoremap =wildtrigger()[-1] +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index da0f7a3803..ee0bf8b413 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 */ +/**/ + 1621, /**/ 1620, /**/