Skip to content

Commit 97b6e8b

Browse files
zeertzjqchrisbra
authored andcommitted
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]>
1 parent 4eef8ba commit 97b6e8b

File tree

5 files changed

+81
-5
lines changed

5 files changed

+81
-5
lines changed

runtime/doc/change.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*change.txt* For Vim version 9.1. Last change: 2025 Oct 14
1+
*change.txt* For Vim version 9.1. Last change: 2025 Oct 26
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1324,7 +1324,7 @@ and ":put" commands and with CTRL-R.
13241324
"@:" to repeat the previous command-line command.
13251325
The command-line is only stored in this register when at least
13261326
one character of it was typed. Thus it remains unchanged if
1327-
the command was completely from a mapping.
1327+
the command was executed completely from a mapping.
13281328
{not available when compiled without the |+cmdline_hist|
13291329
feature}
13301330
*quote_#* *quote#*

runtime/doc/cmdline.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*cmdline.txt* For Vim version 9.1. Last change: 2025 Oct 12
1+
*cmdline.txt* For Vim version 9.1. Last change: 2025 Oct 26
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -61,8 +61,8 @@ Notes:
6161
- When you enter a command-line that is exactly the same as an older one, the
6262
old one is removed (to avoid repeated commands moving older commands out of
6363
the history).
64-
- Only commands that are typed are remembered. Ones that completely come from
65-
mappings are not put in the history.
64+
- Only commands that are typed are remembered. A command executed completely
65+
from a mapping is not put in the history.
6666
- All searches are put in the search history, including the ones that come
6767
from commands like "*" and "#". But for a mapping, only the last search is
6868
remembered (to avoid that long mappings trash the history).

src/ex_getln.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,12 @@ getcmdline_int(
18711871
// that occurs while typing a command should
18721872
// cause the command not to be executed.
18731873

1874+
if (stuff_empty() && typebuf.tb_len == 0)
1875+
// There is no pending input from sources other than user input, so
1876+
// Vim is going to wait for the user to type a key. Consider the
1877+
// command line typed even if next key will trigger a mapping.
1878+
some_key_typed = TRUE;
1879+
18741880
// Trigger SafeState if nothing is pending.
18751881
may_trigger_safestate(xpc.xp_numfiles <= 0);
18761882

src/testdir/test_cmdline.vim

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,6 +2606,74 @@ func Test_recalling_cmdline()
26062606
cunmap <Plug>(save-cmdline)
26072607
endfunc
26082608

2609+
func Test_recalling_cmdline_with_mappings()
2610+
CheckFeature cmdline_hist
2611+
2612+
cnoremap <F2> <Cmd>let g:cmdline = getcmdline()<CR>
2613+
cnoremap <CR> <CR>
2614+
cnoremap <Up> <Up>
2615+
let save_a = ['a', getreg('a'), getregtype('a')]
2616+
2617+
call feedkeys(":echo 'foo'\<CR>", 'tx')
2618+
call assert_equal("echo 'foo'", @:)
2619+
call feedkeys(":echo 'bar'\<CR>", 'tx')
2620+
call assert_equal("echo 'bar'", @:)
2621+
2622+
call assert_equal("echo 'bar'", histget(':', -1))
2623+
call assert_equal("echo 'foo'", histget(':', -2))
2624+
2625+
" This command comes completely from a mapping.
2626+
nmap <F3> :echo 'baz'<F2><CR>
2627+
call feedkeys("\<F3>", 'tx')
2628+
call assert_equal('baz', Screenline(&lines)->trim())
2629+
call assert_equal("echo 'baz'", g:cmdline)
2630+
call assert_equal("echo 'bar'", @:)
2631+
call assert_equal("echo 'bar'", histget(':', -1))
2632+
call assert_equal("echo 'foo'", histget(':', -2))
2633+
2634+
if has('unix')
2635+
new
2636+
call setline(1, ['aaa'])
2637+
setlocal formatprg=cat
2638+
" Formatting with non-typed "gq" should not change cmdline history.
2639+
normal! gqgq
2640+
call assert_equal(":.!cat", Screenline(&lines)->trim())
2641+
call assert_equal("echo 'bar'", @:)
2642+
call assert_equal("echo 'bar'", histget(':', -1))
2643+
call assert_equal("echo 'foo'", histget(':', -2))
2644+
bwipe!
2645+
endif
2646+
2647+
" This case can still be considered a typed command.
2648+
call timer_start(1, {-> feedkeys("\<CR>", 't')})
2649+
call feedkeys(":\<Up>\<Up>", 'tx!')
2650+
call assert_equal('foo', Screenline(&lines)->trim())
2651+
call assert_equal("echo 'foo'", @:)
2652+
call assert_equal("echo 'foo'", histget(':', -1))
2653+
call assert_equal("echo 'bar'", histget(':', -2))
2654+
2655+
call feedkeys(":\<Up>\<F2>\<Esc>", 'tx')
2656+
call assert_equal("echo 'foo'", g:cmdline)
2657+
call assert_equal("echo 'foo'", @:)
2658+
2659+
" A command from an executed register is also ignored in the history.
2660+
call feedkeys(':let @a=":echo ''zzz''\<cr>"' .. "\<CR>", 'tx')
2661+
call feedkeys(":norm @a\<cr>", 'tx')
2662+
call assert_equal('zzz', Screenline(&lines)->trim())
2663+
call assert_equal('norm @a', @:)
2664+
call assert_equal('norm @a', histget(':', -1))
2665+
call assert_equal('let @a=":echo ''zzz''\<cr>"', histget(':', -2))
2666+
call assert_equal("echo 'foo'", histget(':', -3))
2667+
call assert_equal("echo 'bar'", histget(':', -4))
2668+
2669+
unlet g:cmdline
2670+
call call('setreg', save_a)
2671+
cunmap <F2>
2672+
cunmap <CR>
2673+
cunmap <Up>
2674+
nunmap <F3>
2675+
endfunc
2676+
26092677
func Test_cmd_map_cmdlineChanged()
26102678
let g:log = []
26112679
cnoremap <F1> l<Cmd><CR>s

src/version.c

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

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
1872,
737739
/**/
738740
1871,
739741
/**/

0 commit comments

Comments
 (0)