vim-patch:9.1.1969: Wrong cursor position after formatting with long 'formatprg' (#36918)

Problem:  Wrong cursor position after formatting with long 'formatprg'.
Solution: Don't show hit-enter prompt when there are stuffed characters.

Previously a stuffed character at the hit-enter prompt will dismiss the
prompt immediately and be put in the typeahead buffer, which leads to
incorrect behavior as the typeahead buffer is processed after the stuff
buffers. Using vungetc() when KeyStuffed is TRUE can fix this problem,
but since the hit-enter prompt isn't visible anyway (and is likely not
desired here), just skip the prompt instead, which also avoids a wait
when using "wait" instead of "hit-enter" in 'messagesopt'.

fixes:  vim/vim#18905
closes: vim/vim#18906

50325c3d59
(cherry picked from commit 18642a63be)
This commit is contained in:
zeertzjq
2025-12-12 08:07:55 +08:00
committed by github-actions[bot]
parent 808d973fb0
commit d1604e0f38
4 changed files with 81 additions and 1 deletions

View File

@@ -426,7 +426,7 @@ bool stuff_empty(void)
}
/// @return true if readbuf1 is empty. There may still be redo characters in
/// redbuf2.
/// readbuf2.
bool readbuf1_empty(void)
FUNC_ATTR_PURE
{

View File

@@ -1273,6 +1273,11 @@ void wait_return(int redraw)
msg_puts(" "); // make sure the cursor is on the right line
c = CAR; // no need for a return in ex mode
got_int = false;
} else if (!stuff_empty()) {
// When there are stuffed characters, the next stuffed character will
// dismiss the hit-enter prompt immediately and have to be put back, so
// instead just don't show the hit-enter prompt at all.
c = CAR;
} else {
State = MODE_HITRETURN;
setmouse();

View File

@@ -1,3 +1,4 @@
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
@@ -6,6 +7,7 @@ local command = n.command
local exec = n.exec
local feed = n.feed
local api = n.api
local fn = n.fn
local nvim_dir = n.nvim_dir
local assert_alive = n.assert_alive
@@ -751,4 +753,52 @@ describe('messages', function()
|
]])
end)
-- oldtest: Test_long_formatprg_no_hit_enter()
it("long 'formatprg' doesn't cause hit-enter prompt or wrong cursor pos", function()
t.skip(fn.executable('sed') == 0, 'missing "sed" command')
screen = Screen.new(75, 10)
exec([[
setlocal scrolloff=0
call setline(1, range(1, 40))
let &l:formatprg = $'sed{repeat(' ', &columns)}p'
normal 20Gmz
normal 10Gzt
]])
screen:expect([[
^10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
|
]])
feed('gq2j')
screen:expect([[
10 |*2
11 |*2
12 |
^12 |
13 |
14 |
15 |
|
]])
feed(':messages<CR>')
screen:expect([[
10 |*2
11 |*2
12 |
^12 |
13 |
14 |
15 |
3 lines filtered |
]])
end)
end)

View File

@@ -681,4 +681,29 @@ func Test_messagesopt_wait()
call StopVimInTerminal(buf)
endfunc
" Check that using a long 'formatprg' doesn't cause a hit-enter prompt or
" wrong cursor position.
func Test_long_formatprg_no_hit_enter()
CheckScreendump
CheckExecutable sed
let lines =<< trim END
setlocal scrolloff=0
call setline(1, range(1, 40))
let &l:formatprg = $'sed{repeat(' ', &columns)}p'
normal 20Gmz
normal 10Gzt
END
call writefile(lines, 'XtestLongFormatprg', 'D')
let buf = RunVimInTerminal('-S XtestLongFormatprg', #{rows: 10})
call VerifyScreenDump(buf, 'Test_long_formatprg_no_hit_enter_1', {})
call term_sendkeys(buf, 'gq2j')
call VerifyScreenDump(buf, 'Test_long_formatprg_no_hit_enter_2', {})
call term_sendkeys(buf, ":messages\<CR>")
call VerifyScreenDump(buf, 'Test_long_formatprg_no_hit_enter_3', {})
" clean up
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab