patch 9.1.1571: CmdlineChanged triggered to often Commit: https://github.com/vim/vim/commit/239c4e4abe79c0f3611f0b4776ee34fbf0ac53cf Author: Girish Palya <giris...@gmail.com> Date: Sun Jul 20 10:41:02 2025 +0200
patch 9.1.1571: CmdlineChanged triggered to often Problem: The CmdlineChanged event was firing unnecessarily, even when the command line's content hadn't actually changed. Solution: I've added a check to compare the command-line buffer's state before and after key processing. The `CmdlineChanged` event now only triggers if the buffer's contents are genuinely different (Girish Palya). closes: #17803 Signed-off-by: Girish Palya <giris...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/ex_getln.c b/src/ex_getln.c index f63ac6022..47187aa92 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1633,7 +1633,6 @@ getcmdline_int( int res; int save_msg_scroll = msg_scroll; int save_State = State; // remember State when called - int prev_cmdpos = -1; int some_key_typed = FALSE; // one of the keys was typed // mouse drag and release events are ignored, unless they are // preceded with a mouse down event @@ -1649,6 +1648,7 @@ getcmdline_int( int cmdline_type; int wild_type = 0; int event_cmdlineleavepre_triggered = FALSE; + char_u *prev_cmdbuff = NULL; // one recursion level deeper ++depth; @@ -1820,6 +1820,7 @@ getcmdline_int( { int trigger_cmdlinechanged = TRUE; int end_wildmenu; + int prev_cmdpos = ccline.cmdpos; redir_off = TRUE; // Don't redirect the typed command. // Repeated, because a ":redir" inside @@ -1836,6 +1837,13 @@ getcmdline_int( // Trigger SafeState if nothing is pending. may_trigger_safestate(xpc.xp_numfiles <= 0); + if (ccline.cmdbuff != NULL) + { + prev_cmdbuff = vim_strnsave(ccline.cmdbuff, ccline.cmdpos); + if (prev_cmdbuff == NULL) + goto returncmd; + } + // Get a character. Ignore K_IGNORE and K_NOP, they should not do // anything, such as stop completion. do @@ -2566,7 +2574,10 @@ cmdline_not_changed: #ifdef FEAT_SEARCH_EXTRA if (!is_state.incsearch_postponed) + { + VIM_CLEAR(prev_cmdbuff); continue; + } #endif cmdline_changed: @@ -2578,15 +2589,17 @@ cmdline_changed: may_do_incsearch_highlighting(firstc, count, &is_state); #endif // Trigger CmdlineChanged autocommands. - if (trigger_cmdlinechanged) + if (trigger_cmdlinechanged + && (ccline.cmdpos != prev_cmdpos + || (prev_cmdbuff != NULL && STRNCMP(prev_cmdbuff, + ccline.cmdbuff, prev_cmdpos) != 0))) trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED); + VIM_CLEAR(prev_cmdbuff); + // Trigger CursorMovedC autocommands. if (ccline.cmdpos != prev_cmdpos) - { trigger_cmd_autocmd(cmdline_type, EVENT_CURSORMOVEDC); - prev_cmdpos = ccline.cmdpos; - } #ifdef FEAT_RIGHTLEFT if (cmdmsg_rl @@ -2695,6 +2708,8 @@ theend: restore_cmdline(&save_ccline); else ccline.cmdbuff = NULL; + + vim_free(prev_cmdbuff); return p; } } diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 203ab770f..697b01acd 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -4691,4 +4691,53 @@ func Test_pum_scroll_noselect() call StopVimInTerminal(buf) endfunc +" CmdlineChanged shouldn't trigger if command-line text is unchanged +func Test_cmdline_changed() + let g:cmdchg_count = 0 + let g:cmdprefix = '' + augroup test_CmdlineAugrp | autocmd! + autocmd CmdlineChanged * if getcmdline() =~ g:cmdprefix | let g:cmdchg_count += 1 | endif + augroup END + + new + 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> + + 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' + + 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> + + command! -nargs=+ -complete=custom,TestComplete Test echo + + func TestComplete(arglead, cmdline, cursorpos) + return "AbC" + 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' + + bw! + set wildmode& wildmenu& wildoptions& + augroup test_CmdlineAugrp | autocmd! | augroup END + unlet g:cmdchg_count + unlet g:cmdprefix + delfunc TestComplete + delcommand Test +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index c7027a68e..382ab20bb 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 */ +/**/ + 1571, /**/ 1570, /**/ -- -- 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/E1udPfQ-00GqNk-7v%40256bit.org.