diff options
-rw-r--r-- | runtime/doc/options.txt | 2 | ||||
-rw-r--r-- | src/ex_getln.c | 14 | ||||
-rw-r--r-- | src/option.c | 15 | ||||
-rw-r--r-- | src/optiondefs.h | 4 | ||||
-rw-r--r-- | src/proto/option.pro | 1 | ||||
-rw-r--r-- | src/testdir/dumps/Test_wildmenu_5.dump | 8 | ||||
-rw-r--r-- | src/testdir/dumps/Test_wildmenu_6.dump | 8 | ||||
-rw-r--r-- | src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_1.dump (renamed from src/testdir/dumps/Test_wildmenu_pum_clear_entries_1.dump) | 0 | ||||
-rw-r--r-- | src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_2.dump | 10 | ||||
-rw-r--r-- | src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_3.dump | 10 | ||||
-rw-r--r-- | src/testdir/test_cmdline.vim | 51 | ||||
-rw-r--r-- | src/testdir/test_options.vim | 5 | ||||
-rw-r--r-- | src/version.c | 2 |
13 files changed, 121 insertions, 9 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6f38bc02be..86a734f6e6 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -9253,6 +9253,8 @@ A jump table for the options with a short description can be found at |Q_op|. The character is not recognized when used inside a macro. See 'wildcharm' for that. Some keys will not work, such as CTRL-C, <CR> and Enter. + <Esc> can be used, but hitting it twice in a row will still exit + command-line as a failsafe measure. Although 'wc' is a number option, you can set it to a special key: > :set wc=<Tab> < NOTE: This option is set to the Vi default value when 'compatible' is diff --git a/src/ex_getln.c b/src/ex_getln.c index 5baffa77fb..711e08e886 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1877,7 +1877,8 @@ getcmdline_int( if (p_wmnu) c = wildmenu_translate_key(&ccline, c, &xpc, did_wild_list); - if (cmdline_pum_active()) + int key_is_wc = (c == p_wc && KeyTyped) || c == p_wcm; + if (cmdline_pum_active() && !key_is_wc) { // Ctrl-Y: Accept the current selection and close the popup menu. // Ctrl-E: cancel the cmdline popup menu and return the original @@ -1897,7 +1898,7 @@ getcmdline_int( // 'wildcharm' or Ctrl-N or Ctrl-P or Ctrl-A or Ctrl-L). // If the popup menu is displayed, then PageDown and PageUp keys are // also used to navigate the menu. - end_wildmenu = (!(c == p_wc && KeyTyped) && c != p_wcm + end_wildmenu = (!key_is_wc && c != Ctrl_N && c != Ctrl_P && c != Ctrl_A && c != Ctrl_L); end_wildmenu = end_wildmenu && (!cmdline_pum_active() || (c != K_PAGEDOWN && c != K_PAGEUP @@ -2504,6 +2505,15 @@ returncmd: cmdmsg_rl = FALSE; #endif + // We could have reached here without having a chance to clean up wild menu + // if certain special keys like <Esc> or <C-\> were used as wildchar. Make + // sure to still clean up to avoid memory corruption. + if (cmdline_pum_active()) + cmdline_pum_remove(); + wildmenu_cleanup(&ccline); + did_wild_list = FALSE; + wim_index = 0; + ExpandCleanup(&xpc); ccline.xpc = NULL; diff --git a/src/option.c b/src/option.c index 53e956c8b1..180aca221d 100644 --- a/src/option.c +++ b/src/option.c @@ -4393,6 +4393,21 @@ did_set_weirdinvert(optset_T *args) } /* + * Process the new 'wildchar' / 'wildcharm' option value. + */ + char * +did_set_wildchar(optset_T *args) +{ + long c = *(long *)args->os_varp; + + // Don't allow key values that wouldn't work as wildchar. + if (c == Ctrl_C || c == '\n' || c == '\r' || c == K_KENTER) + return e_invalid_argument; + + return NULL; +} + +/* * Process the new 'window' option value. */ char * diff --git a/src/optiondefs.h b/src/optiondefs.h index c4810e7d5d..d5887e1d41 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -2812,11 +2812,11 @@ static struct vimoption options[] = (char_u *)&p_ww, PV_NONE, did_set_whichwrap, expand_set_whichwrap, {(char_u *)"", (char_u *)"b,s"} SCTX_INIT}, {"wildchar", "wc", P_NUM|P_VIM, - (char_u *)&p_wc, PV_NONE, NULL, NULL, + (char_u *)&p_wc, PV_NONE, did_set_wildchar, NULL, {(char_u *)(long)Ctrl_E, (char_u *)(long)TAB} SCTX_INIT}, {"wildcharm", "wcm", P_NUM|P_VI_DEF, - (char_u *)&p_wcm, PV_NONE, NULL, NULL, + (char_u *)&p_wcm, PV_NONE, did_set_wildchar, NULL, {(char_u *)0L, (char_u *)0L} SCTX_INIT}, {"wildignore", "wig", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, (char_u *)&p_wig, PV_NONE, NULL, NULL, diff --git a/src/proto/option.pro b/src/proto/option.pro index ec0013dbfa..effa81315b 100644 --- a/src/proto/option.pro +++ b/src/proto/option.pro @@ -81,6 +81,7 @@ char *did_set_undofile(optset_T *args); char *did_set_undolevels(optset_T *args); char *did_set_updatecount(optset_T *args); char *did_set_weirdinvert(optset_T *args); +char *did_set_wildchar(optset_T *args); char *did_set_window(optset_T *args); char *did_set_winheight_helpheight(optset_T *args); char *did_set_winminheight(optset_T *args); diff --git a/src/testdir/dumps/Test_wildmenu_5.dump b/src/testdir/dumps/Test_wildmenu_5.dump new file mode 100644 index 0000000000..ca9c5be126 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_5.dump @@ -0,0 +1,8 @@ +| +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|v|i|m| > @69 diff --git a/src/testdir/dumps/Test_wildmenu_6.dump b/src/testdir/dumps/Test_wildmenu_6.dump new file mode 100644 index 0000000000..6b7ef83555 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_6.dump @@ -0,0 +1,8 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_wildmenu_pum_clear_entries_1.dump b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_1.dump index b5825eb195..b5825eb195 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_clear_entries_1.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_1.dump diff --git a/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_2.dump b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_2.dump new file mode 100644 index 0000000000..2887895b60 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_2.dump @@ -0,0 +1,10 @@ +| +0#0000001#ffd7ff255|!| @14| +0#0000000#0000001| +0&#ffffff0@56 +| +0#0000001#e0e0e08|#| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|&| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|*| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|+@1| @13| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|-@1| @13| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|<| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|=| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +| +0#0000001#ffd7ff255|>| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@56 +|:+0#0000000&|#> @72 diff --git a/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_3.dump b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_3.dump new file mode 100644 index 0000000000..270a23344e --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_pum_odd_wildchar_3.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index ddfeba28ff..c285b087a4 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -171,6 +171,7 @@ func Test_wildmenu_screendump() [SCRIPT] call writefile(lines, 'XTest_wildmenu', 'D') + " Test simple wildmenu let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8}) call term_sendkeys(buf, ":vim\<Tab>") call VerifyScreenDump(buf, 'Test_wildmenu_1', {}) @@ -181,9 +182,23 @@ func Test_wildmenu_screendump() call term_sendkeys(buf, "\<Tab>") call VerifyScreenDump(buf, 'Test_wildmenu_3', {}) + " Looped back to the original value call term_sendkeys(buf, "\<Tab>\<Tab>") call VerifyScreenDump(buf, 'Test_wildmenu_4', {}) + + " Test that the wild menu is cleared properly + call term_sendkeys(buf, " ") + call VerifyScreenDump(buf, 'Test_wildmenu_5', {}) + + " Test that a different wildchar still works + call term_sendkeys(buf, "\<Esc>:set wildchar=<Esc>\<CR>") + call term_sendkeys(buf, ":vim\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_1', {}) + + " Double-<Esc> is a hard-coded method to escape while wildchar=<Esc>. Make + " sure clean up is properly done in edge case like this. call term_sendkeys(buf, "\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_6', {}) " clean up call StopVimInTerminal(buf) @@ -2636,10 +2651,11 @@ func Test_wildmenu_pum_from_terminal() call StopVimInTerminal(buf) endfunc -func Test_wildmenu_pum_clear_entries() +func Test_wildmenu_pum_odd_wildchar() CheckRunVimInTerminal - " This was using freed memory. Run in a terminal to get the pum to update. + " Test odd wildchar interactions with pum. Make sure they behave properly + " and don't lead to memory corruption due to improperly cleaned up memory. let lines =<< trim END set wildoptions=pum set wildchar=<C-E> @@ -2647,10 +2663,35 @@ func Test_wildmenu_pum_clear_entries() call writefile(lines, 'XwildmenuTest', 'D') let buf = RunVimInTerminal('-S XwildmenuTest', #{rows: 10}) - call term_sendkeys(buf, ":\<C-E>\<C-E>") - call VerifyScreenDump(buf, 'Test_wildmenu_pum_clear_entries_1', {}) + call term_sendkeys(buf, ":\<C-E>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {}) + + " <C-E> being a wildchar takes priority over its original functionality + call term_sendkeys(buf, "\<C-E>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_2', {}) + + call term_sendkeys(buf, "\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {}) - set wildoptions& wildchar& + " Escape key can be wildchar too. Double-<Esc> is hard-coded to escape + " command-line, and we need to make sure to clean up properly. + call term_sendkeys(buf, ":set wildchar=<Esc>\<CR>") + call term_sendkeys(buf, ":\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {}) + + call term_sendkeys(buf, "\<Esc>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {}) + + " <C-\> can also be wildchar. <C-\><C-N> however will still escape cmdline + " and we again need to make sure we clean up properly. + call term_sendkeys(buf, ":set wildchar=<C-\\>\<CR>") + call term_sendkeys(buf, ":\<C-\>\<C-\>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_1', {}) + + call term_sendkeys(buf, "\<C-N>") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_odd_wildchar_3', {}) + + call StopVimInTerminal(buf) endfunc " Test for completion after a :substitute command followed by a pipe (|) diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index ba0808956d..6b2b7482a7 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -228,6 +228,11 @@ func Test_keymap_valid() call assert_fails(":set kmp=trunc\x00name", "trunc") endfunc +func Test_wildchar_valid() + call assert_fails("set wildchar=<CR>", "E474:") + call assert_fails("set wildcharm=<C-C>", "E474:") +endfunc + func Check_dir_option(name) " Check that it's possible to set the option. exe 'set ' . a:name . '=/usr/share/dict/words' diff --git a/src/version.c b/src/version.c index 695b0cd56e..6f39f950f8 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2035, +/**/ 2034, /**/ 2033, |