Skip to content

Commit 239c4e4

Browse files
girishjichrisbra
authored andcommitted
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]>
1 parent 1afe8c3 commit 239c4e4

3 files changed

Lines changed: 71 additions & 5 deletions

File tree

src/ex_getln.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,6 @@ getcmdline_int(
16331633
int res;
16341634
int save_msg_scroll = msg_scroll;
16351635
int save_State = State; // remember State when called
1636-
int prev_cmdpos = -1;
16371636
int some_key_typed = FALSE; // one of the keys was typed
16381637
// mouse drag and release events are ignored, unless they are
16391638
// preceded with a mouse down event
@@ -1649,6 +1648,7 @@ getcmdline_int(
16491648
int cmdline_type;
16501649
int wild_type = 0;
16511650
int event_cmdlineleavepre_triggered = FALSE;
1651+
char_u *prev_cmdbuff = NULL;
16521652

16531653
// one recursion level deeper
16541654
++depth;
@@ -1820,6 +1820,7 @@ getcmdline_int(
18201820
{
18211821
int trigger_cmdlinechanged = TRUE;
18221822
int end_wildmenu;
1823+
int prev_cmdpos = ccline.cmdpos;
18231824

18241825
redir_off = TRUE; // Don't redirect the typed command.
18251826
// Repeated, because a ":redir" inside
@@ -1836,6 +1837,13 @@ getcmdline_int(
18361837
// Trigger SafeState if nothing is pending.
18371838
may_trigger_safestate(xpc.xp_numfiles <= 0);
18381839

1840+
if (ccline.cmdbuff != NULL)
1841+
{
1842+
prev_cmdbuff = vim_strnsave(ccline.cmdbuff, ccline.cmdpos);
1843+
if (prev_cmdbuff == NULL)
1844+
goto returncmd;
1845+
}
1846+
18391847
// Get a character. Ignore K_IGNORE and K_NOP, they should not do
18401848
// anything, such as stop completion.
18411849
do
@@ -2566,7 +2574,10 @@ getcmdline_int(
25662574

25672575
#ifdef FEAT_SEARCH_EXTRA
25682576
if (!is_state.incsearch_postponed)
2577+
{
2578+
VIM_CLEAR(prev_cmdbuff);
25692579
continue;
2580+
}
25702581
#endif
25712582

25722583
cmdline_changed:
@@ -2578,15 +2589,17 @@ getcmdline_int(
25782589
may_do_incsearch_highlighting(firstc, count, &is_state);
25792590
#endif
25802591
// Trigger CmdlineChanged autocommands.
2581-
if (trigger_cmdlinechanged)
2592+
if (trigger_cmdlinechanged
2593+
&& (ccline.cmdpos != prev_cmdpos
2594+
|| (prev_cmdbuff != NULL && STRNCMP(prev_cmdbuff,
2595+
ccline.cmdbuff, prev_cmdpos) != 0)))
25822596
trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED);
25832597

2598+
VIM_CLEAR(prev_cmdbuff);
2599+
25842600
// Trigger CursorMovedC autocommands.
25852601
if (ccline.cmdpos != prev_cmdpos)
2586-
{
25872602
trigger_cmd_autocmd(cmdline_type, EVENT_CURSORMOVEDC);
2588-
prev_cmdpos = ccline.cmdpos;
2589-
}
25902603

25912604
#ifdef FEAT_RIGHTLEFT
25922605
if (cmdmsg_rl
@@ -2695,6 +2708,8 @@ getcmdline_int(
26952708
restore_cmdline(&save_ccline);
26962709
else
26972710
ccline.cmdbuff = NULL;
2711+
2712+
vim_free(prev_cmdbuff);
26982713
return p;
26992714
}
27002715
}

src/testdir/test_cmdline.vim

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4691,4 +4691,53 @@ func Test_pum_scroll_noselect()
46914691
call StopVimInTerminal(buf)
46924692
endfunc
46934693

4694+
" CmdlineChanged shouldn't trigger if command-line text is unchanged
4695+
func Test_cmdline_changed()
4696+
let g:cmdchg_count = 0
4697+
let g:cmdprefix = ''
4698+
augroup test_CmdlineAugrp | autocmd!
4699+
autocmd CmdlineChanged * if getcmdline() =~ g:cmdprefix | let g:cmdchg_count += 1 | endif
4700+
augroup END
4701+
4702+
new
4703+
set wildmenu
4704+
set wildmode=full
4705+
4706+
let g:cmdprefix = 'echomsg'
4707+
let g:cmdchg_count = 0
4708+
call feedkeys(":echomsg\<Tab>", "tx")
4709+
call assert_equal(1, g:cmdchg_count) " once only for 'g', not again for <Tab>
4710+
4711+
let g:cmdchg_count = 0
4712+
let g:cmdprefix = 'echo'
4713+
call feedkeys(":ech\<Tab>", "tx")
4714+
call assert_equal(1, g:cmdchg_count) " (once for 'h' and) once for 'o'
4715+
4716+
set wildmode=noselect,full
4717+
let g:cmdchg_count = 0
4718+
let g:cmdprefix = 'ech'
4719+
call feedkeys(":ech\<Tab>", "tx")
4720+
call assert_equal(1, g:cmdchg_count) " once for 'h', not again for <tab>
4721+
4722+
command! -nargs=+ -complete=custom,TestComplete Test echo
4723+
4724+
func TestComplete(arglead, cmdline, cursorpos)
4725+
return "AbC"
4726+
endfunc
4727+
4728+
set wildoptions=fuzzy wildmode=full
4729+
let g:cmdchg_count = 0
4730+
let g:cmdprefix = 'Test \(AbC\|abc\)'
4731+
call feedkeys(":Test abc\<Tab>", "tx")
4732+
call assert_equal(2, g:cmdchg_count) " once for 'c', again for 'AbC'
4733+
4734+
bw!
4735+
set wildmode& wildmenu& wildoptions&
4736+
augroup test_CmdlineAugrp | autocmd! | augroup END
4737+
unlet g:cmdchg_count
4738+
unlet g:cmdprefix
4739+
delfunc TestComplete
4740+
delcommand Test
4741+
endfunc
4742+
46944743
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,8 @@ static char *(features[]) =
719719

720720
static int included_patches[] =
721721
{ /* Add new patch number below this line */
722+
/**/
723+
1571,
722724
/**/
723725
1570,
724726
/**/

0 commit comments

Comments
 (0)