patch 9.1.1872: Cmdline history not updated when mapping <Up> and <CR>
Commit: https://github.com/vim/vim/commit/97b6e8b4243cc96dbb8716d518976a5ce0515748 Author: zeertzjq <[email protected]> Date: Sun Oct 26 13:29:09 2025 +0000 patch 9.1.1872: Cmdline history not updated when mapping <Up> and <CR> Problem: Cmdline history not updated when mapping both <Up> and <CR>. Solution: Consider the command typed when in Cmdline mode and there is no pending input (zeertzjq). Although the existing behavior technically does match documentation, the "completely come from mappings" part is a bit ambiguous, because one may argue that the command doesn't completely come from mappings as long as the user has typed a key in Cmdline mode. I'm not entirely sure if this change will cause problems, but it seems unlikely. fixes: #2771 related: neovim/neovim#36256 closes: #18607 Signed-off-by: zeertzjq <[email protected]> Signed-off-by: Christian Brabandt <[email protected]> diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index ff64628e0..878d38851 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 9.1. Last change: 2025 Oct 14 +*change.txt* For Vim version 9.1. Last change: 2025 Oct 26 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1324,7 +1324,7 @@ and ":put" commands and with CTRL-R. "@:" to repeat the previous command-line command. The command-line is only stored in this register when at least one character of it was typed. Thus it remains unchanged if - the command was completely from a mapping. + the command was executed completely from a mapping. {not available when compiled without the |+cmdline_hist| feature} *quote_#* *quote#* diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index ef13d7271..ede9a5ec0 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1,4 +1,4 @@ -*cmdline.txt* For Vim version 9.1. Last change: 2025 Oct 12 +*cmdline.txt* For Vim version 9.1. Last change: 2025 Oct 26 VIM REFERENCE MANUAL by Bram Moolenaar @@ -61,8 +61,8 @@ Notes: - When you enter a command-line that is exactly the same as an older one, the old one is removed (to avoid repeated commands moving older commands out of the history). -- Only commands that are typed are remembered. Ones that completely come from - mappings are not put in the history. +- Only commands that are typed are remembered. A command executed completely + from a mapping is not put in the history. - All searches are put in the search history, including the ones that come from commands like "*" and "#". But for a mapping, only the last search is remembered (to avoid that long mappings trash the history). diff --git a/src/ex_getln.c b/src/ex_getln.c index 73f8ca22d..5fc9330bc 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1871,6 +1871,12 @@ getcmdline_int( // that occurs while typing a command should // cause the command not to be executed. + if (stuff_empty() && typebuf.tb_len == 0) + // There is no pending input from sources other than user input, so + // Vim is going to wait for the user to type a key. Consider the + // command line typed even if next key will trigger a mapping. + some_key_typed = TRUE; + // Trigger SafeState if nothing is pending. may_trigger_safestate(xpc.xp_numfiles <= 0); diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 58629b5fd..d0987c40a 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -2606,6 +2606,74 @@ func Test_recalling_cmdline() cunmap <Plug>(save-cmdline) endfunc +func Test_recalling_cmdline_with_mappings() + CheckFeature cmdline_hist + + cnoremap <F2> <Cmd>let g:cmdline = getcmdline()<CR> + cnoremap <CR> <CR> + cnoremap <Up> <Up> + let save_a = ['a', getreg('a'), getregtype('a')] + + call feedkeys(":echo 'foo'\<CR>", 'tx') + call assert_equal("echo 'foo'", @:) + call feedkeys(":echo 'bar'\<CR>", 'tx') + call assert_equal("echo 'bar'", @:) + + call assert_equal("echo 'bar'", histget(':', -1)) + call assert_equal("echo 'foo'", histget(':', -2)) + + " This command comes completely from a mapping. + nmap <F3> :echo 'baz'<F2><CR> + call feedkeys("\<F3>", 'tx') + call assert_equal('baz', Screenline(&lines)->trim()) + call assert_equal("echo 'baz'", g:cmdline) + call assert_equal("echo 'bar'", @:) + call assert_equal("echo 'bar'", histget(':', -1)) + call assert_equal("echo 'foo'", histget(':', -2)) + + if has('unix') + new + call setline(1, ['aaa']) + setlocal formatprg=cat + " Formatting with non-typed "gq" should not change cmdline history. + normal! gqgq + call assert_equal(":.!cat", Screenline(&lines)->trim()) + call assert_equal("echo 'bar'", @:) + call assert_equal("echo 'bar'", histget(':', -1)) + call assert_equal("echo 'foo'", histget(':', -2)) + bwipe! + endif + + " This case can still be considered a typed command. + call timer_start(1, {-> feedkeys("\<CR>", 't')}) + call feedkeys(":\<Up>\<Up>", 'tx!') + call assert_equal('foo', Screenline(&lines)->trim()) + call assert_equal("echo 'foo'", @:) + call assert_equal("echo 'foo'", histget(':', -1)) + call assert_equal("echo 'bar'", histget(':', -2)) + + call feedkeys(":\<Up>\<F2>\<Esc>", 'tx') + call assert_equal("echo 'foo'", g:cmdline) + call assert_equal("echo 'foo'", @:) + + " A command from an executed register is also ignored in the history. + call feedkeys(':let @a=":echo ''zzz''\<cr>"' .. "\<CR>", 'tx') + call feedkeys(":norm @a\<cr>", 'tx') + call assert_equal('zzz', Screenline(&lines)->trim()) + call assert_equal('norm @a', @:) + call assert_equal('norm @a', histget(':', -1)) + call assert_equal('let @a=":echo ''zzz''\<cr>"', histget(':', -2)) + call assert_equal("echo 'foo'", histget(':', -3)) + call assert_equal("echo 'bar'", histget(':', -4)) + + unlet g:cmdline + call call('setreg', save_a) + cunmap <F2> + cunmap <CR> + cunmap <Up> + nunmap <F3> +endfunc + func Test_cmd_map_cmdlineChanged() let g:log = [] cnoremap <F1> l<Cmd><CR>s diff --git a/src/version.c b/src/version.c index 2526c0933..d20067856 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1872, /**/ 1871, /**/ -- -- 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/E1vD13R-003eGD-SE%40256bit.org.
