0
0
mirror of https://github.com/vim/vim.git synced 2025-08-27 20:13:38 -04:00

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 <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Girish Palya 2025-07-20 10:41:02 +02:00 committed by Christian Brabandt
parent 1afe8c3a4d
commit 239c4e4abe
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
3 changed files with 71 additions and 5 deletions

View File

@ -1633,7 +1633,6 @@ getcmdline_int(
int res; int res;
int save_msg_scroll = msg_scroll; int save_msg_scroll = msg_scroll;
int save_State = State; // remember State when called int save_State = State; // remember State when called
int prev_cmdpos = -1;
int some_key_typed = FALSE; // one of the keys was typed int some_key_typed = FALSE; // one of the keys was typed
// mouse drag and release events are ignored, unless they are // mouse drag and release events are ignored, unless they are
// preceded with a mouse down event // preceded with a mouse down event
@ -1649,6 +1648,7 @@ getcmdline_int(
int cmdline_type; int cmdline_type;
int wild_type = 0; int wild_type = 0;
int event_cmdlineleavepre_triggered = FALSE; int event_cmdlineleavepre_triggered = FALSE;
char_u *prev_cmdbuff = NULL;
// one recursion level deeper // one recursion level deeper
++depth; ++depth;
@ -1820,6 +1820,7 @@ getcmdline_int(
{ {
int trigger_cmdlinechanged = TRUE; int trigger_cmdlinechanged = TRUE;
int end_wildmenu; int end_wildmenu;
int prev_cmdpos = ccline.cmdpos;
redir_off = TRUE; // Don't redirect the typed command. redir_off = TRUE; // Don't redirect the typed command.
// Repeated, because a ":redir" inside // Repeated, because a ":redir" inside
@ -1836,6 +1837,13 @@ getcmdline_int(
// Trigger SafeState if nothing is pending. // Trigger SafeState if nothing is pending.
may_trigger_safestate(xpc.xp_numfiles <= 0); 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 // Get a character. Ignore K_IGNORE and K_NOP, they should not do
// anything, such as stop completion. // anything, such as stop completion.
do do
@ -2566,7 +2574,10 @@ cmdline_not_changed:
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
if (!is_state.incsearch_postponed) if (!is_state.incsearch_postponed)
{
VIM_CLEAR(prev_cmdbuff);
continue; continue;
}
#endif #endif
cmdline_changed: cmdline_changed:
@ -2578,15 +2589,17 @@ cmdline_changed:
may_do_incsearch_highlighting(firstc, count, &is_state); may_do_incsearch_highlighting(firstc, count, &is_state);
#endif #endif
// Trigger CmdlineChanged autocommands. // 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); trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED);
VIM_CLEAR(prev_cmdbuff);
// Trigger CursorMovedC autocommands. // Trigger CursorMovedC autocommands.
if (ccline.cmdpos != prev_cmdpos) if (ccline.cmdpos != prev_cmdpos)
{
trigger_cmd_autocmd(cmdline_type, EVENT_CURSORMOVEDC); trigger_cmd_autocmd(cmdline_type, EVENT_CURSORMOVEDC);
prev_cmdpos = ccline.cmdpos;
}
#ifdef FEAT_RIGHTLEFT #ifdef FEAT_RIGHTLEFT
if (cmdmsg_rl if (cmdmsg_rl
@ -2695,6 +2708,8 @@ theend:
restore_cmdline(&save_ccline); restore_cmdline(&save_ccline);
else else
ccline.cmdbuff = NULL; ccline.cmdbuff = NULL;
vim_free(prev_cmdbuff);
return p; return p;
} }
} }

View File

@ -4691,4 +4691,53 @@ func Test_pum_scroll_noselect()
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1571,
/**/ /**/
1570, 1570,
/**/ /**/