fix(ui): cmdline_show is not fired after clearing the screen (#36451)

Problem:  Resize events during startup may clear an active external
          cmdline, which is then not redrawn.
          UI2 VimResized autocommand does not work.
          UI2 message appearance may be altered by inherited window
          options. The message separator uses the wrong fillchar.

Solution: Unset cmdline_was_last_redrawn when clearing the screen, such
          that cmdline_show is re-emitted.
          Ensure set_pos function is called without arguments.
          Ensure such options are unset. Use 'fillchars'->msgsep.
This commit is contained in:
luukvbaal
2025-11-08 11:38:56 +01:00
committed by GitHub
parent 466b2ac192
commit 8d6963a6a0
6 changed files with 60 additions and 17 deletions

View File

@@ -126,7 +126,9 @@ function M.enable(opts)
api.nvim_create_autocmd({ 'VimResized', 'TabEnter' }, { api.nvim_create_autocmd({ 'VimResized', 'TabEnter' }, {
group = ext.augroup, group = ext.augroup,
callback = ext.msg.set_pos, callback = function()
ext.msg.set_pos()
end,
desc = 'Set cmdline and message window dimensions after shell resize or tabpage change.', desc = 'Set cmdline and message window dimensions after shell resize or tabpage change.',
}) })

View File

@@ -470,7 +470,7 @@ function M.set_pos(type)
local function win_set_pos(win) local function win_set_pos(win)
local texth = type and api.nvim_win_text_height(win, {}) or {} local texth = type and api.nvim_win_text_height(win, {}) or {}
local height = type and math.min(texth.all, math.ceil(o.lines * 0.5)) local height = type and math.min(texth.all, math.ceil(o.lines * 0.5))
local top = { vim.opt.fcs:get().horiz or o.ambw == 'single' and '' or '-', 'MsgSeparator' } local top = { vim.opt.fcs:get().msgsep or ' ', 'MsgSeparator' }
local border = win ~= ext.wins.msg and { '', top, '', '', '', '', '', '' } or nil local border = win ~= ext.wins.msg and { '', top, '', '', '', '', '', '' } or nil
local config = { local config = {
hide = false, hide = false,

View File

@@ -72,6 +72,10 @@ function M.check_targets()
api.nvim_set_option_value('wrap', true, { scope = 'local' }) api.nvim_set_option_value('wrap', true, { scope = 'local' })
api.nvim_set_option_value('linebreak', false, { scope = 'local' }) api.nvim_set_option_value('linebreak', false, { scope = 'local' })
api.nvim_set_option_value('smoothscroll', true, { scope = 'local' }) api.nvim_set_option_value('smoothscroll', true, { scope = 'local' })
api.nvim_set_option_value('breakindent', false, { scope = 'local' })
api.nvim_set_option_value('foldenable', false, { scope = 'local' })
api.nvim_set_option_value('showbreak', '', { scope = 'local' })
api.nvim_set_option_value('spell', false, { scope = 'local' })
api.nvim_set_option_value('swapfile', false, { scope = 'local' }) api.nvim_set_option_value('swapfile', false, { scope = 'local' })
api.nvim_set_option_value('modifiable', true, { scope = 'local' }) api.nvim_set_option_value('modifiable', true, { scope = 'local' })
api.nvim_set_option_value('bufhidden', 'hide', { scope = 'local' }) api.nvim_set_option_value('bufhidden', 'hide', { scope = 'local' })

View File

@@ -239,6 +239,7 @@ void screenclear(void)
mode_displayed = false; mode_displayed = false;
redraw_all_later(UPD_NOT_VALID); redraw_all_later(UPD_NOT_VALID);
cmdline_was_last_drawn = false;
redraw_cmdline = true; redraw_cmdline = true;
redraw_tabline = true; redraw_tabline = true;
redraw_popupmenu = true; redraw_popupmenu = true;

View File

@@ -125,3 +125,39 @@ describe('cmdline2', function()
t.eq(n.eval('v:errmsg'), "E1514: 'findfunc' did not return a List type") t.eq(n.eval('v:errmsg'), "E1514: 'findfunc' did not return a List type")
end) end)
end) end)
describe('cmdline2', function()
it('resizing during startup shows confirm prompt #36439', function()
clear({
args = {
'--clean',
'+lua require("vim._extui").enable({})',
"+call feedkeys(':')",
},
})
local screen = Screen.new()
feed('call confirm("Ok?")<CR>')
screen:try_resize(screen._width + 1, screen._height)
screen:expect([[
|
{1:~ }|*8
{3: }|
|
{6:Ok?} |
|
{6:[O]k: }^ |
]])
-- And resizing the next event loop iteration also works.
feed('k')
screen:try_resize(screen._width, screen._height + 1)
screen:expect([[
|
{1:~ }|*9
{3: }|
|
{6:Ok?} |
|
{6:[O]k: }^ |
]])
end)
end)

View File

@@ -35,7 +35,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*10 {1:~ }|*10
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar | bar |
]]) ]])
@@ -44,7 +44,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*9 {1:~ }|*9
{3:─────────────────────────────────────────────────────}| {3: }|
fo^o | fo^o |
bar | bar |
1,3 All| 1,3 All|
@@ -54,7 +54,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*5 {1:~ }|*5
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar | bar |
baz | baz |
@@ -83,7 +83,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*8 {1:~ }|*8
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar | bar |
| |
@@ -115,7 +115,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*10 {1:~ }|*10
{3:─────────────────────────────────────────────────────}| {3: }|
fo^o | fo^o |
foo | foo |
]]) ]])
@@ -195,7 +195,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar |*5 bar |*5
bar [+8] | bar [+8] |
@@ -235,7 +235,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*10 {1:~ }|*10
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar | bar |
]]) ]])
@@ -252,7 +252,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
^ | ^ |
{1:~ }|*10 {1:~ }|*10
{3:─────────────────────────────────────────────────────}| {3: }|
foo | foo |
bar | bar |
]]) ]])
@@ -271,7 +271,7 @@ describe('messages2', function()
local top = [[ local top = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
0 | 0 |
1 | 1 |
2 | 2 |
@@ -287,7 +287,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*4 {1:~ }|*4
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
1 [+1] | 1 [+1] |
2 | 2 |
3 | 3 |
@@ -303,7 +303,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*4 {1:~ }|*4
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
3 [+3] | 3 [+3] |
4 | 4 |
5 | 5 |
@@ -319,7 +319,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*4 {1:~ }|*4
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
5 [+5] | 5 [+5] |
6 | 6 |
7 | 7 |
@@ -335,7 +335,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*4 {1:~ }|*4
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
93 [+93] | 93 [+93] |
94 | 94 |
95 | 95 |
@@ -350,7 +350,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*3 {1:~ }|*3
{3:───────────────────────────────────────────────────────────────────────}| {3: }|
93 [+93] | 93 [+93] |
94 | 94 |
95 | 95 |
@@ -431,7 +431,7 @@ describe('messages2', function()
screen:expect([[ screen:expect([[
| |
{1:~ }|*9 {1:~ }|*9
{3:─────────────────────────────────────────────────────}| {3: }|
^foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo| ^foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo|
{1: }| {1: }|
| |