patch 9.1.1571: CmdlineChanged triggered to often
Commit:
https://github.com/vim/vim/commit/239c4e4abe79c0f3611f0b4776ee34fbf0ac53cf
Author: Girish Palya <[email protected]>
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 <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
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 [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1udPfQ-00GqNk-7v%40256bit.org.