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.

Raspunde prin e-mail lui