mirror of
https://github.com/neovim/neovim
synced 2025-07-18 18:21:46 +00:00
fix(extui): adjust "more" window routing (#34251)
Problem: Message lines from multiple message events that end up spilling 'cmdheight' end up spread out over the cmdline and "more" window. Messages emitted as feedback to a typed :command (rather than its sole purpose like :echo/:=) are routed to the more window. The more window isn't closed when entering the cmdwin, and doesn't allow `vim.hl.on_yank()`. Solution: When first opening the "more" window for spilled messages, move the message buffer to the more window. Restrict routing of typed commands to echo kinds. Ignore all events but WinLeave and TextYankPost.
This commit is contained in:
@ -110,10 +110,8 @@ function M.enable(opts)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if vim.v.vim_did_enter == 1 then
|
ext.tab_check_wins()
|
||||||
ext.tab_check_wins()
|
check_opt('cmdheight', vim.o.cmdheight)
|
||||||
check_opt('cmdheight', vim.o.cmdheight)
|
|
||||||
end
|
|
||||||
|
|
||||||
api.nvim_create_autocmd('OptionSet', {
|
api.nvim_create_autocmd('OptionSet', {
|
||||||
group = ext.augroup,
|
group = ext.augroup,
|
||||||
|
@ -42,8 +42,8 @@ local M = {
|
|||||||
---@param len integer Number of rows that should be removed.
|
---@param len integer Number of rows that should be removed.
|
||||||
function M.box:start_timer(buf, len)
|
function M.box:start_timer(buf, len)
|
||||||
self.timer = vim.defer_fn(function()
|
self.timer = vim.defer_fn(function()
|
||||||
if self.count == 0 or not api.nvim_buf_is_valid(buf) then
|
if buf ~= ext.bufs.box or not api.nvim_buf_is_valid(buf) then
|
||||||
return -- Messages moved to split or buffer was closed.
|
return -- Messages moved to more or buffer was closed.
|
||||||
end
|
end
|
||||||
api.nvim_buf_set_lines(buf, 0, len, false, {})
|
api.nvim_buf_set_lines(buf, 0, len, false, {})
|
||||||
self.count = self.count - 1
|
self.count = self.count - 1
|
||||||
@ -168,6 +168,16 @@ local function set_virttext(type)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Move message buffer to more window.
|
||||||
|
local function msg_to_more(tar)
|
||||||
|
api.nvim_win_set_buf(ext.wins[ext.tab].more, ext.bufs[tar])
|
||||||
|
api.nvim_buf_delete(ext.bufs.more, { force = true })
|
||||||
|
api.nvim_buf_set_name(ext.bufs[tar], 'vim._extui.more')
|
||||||
|
ext.bufs.more, ext.bufs[tar], M[tar].count = ext.bufs[tar], -1, 0
|
||||||
|
ext.tab_check_wins()
|
||||||
|
M.set_pos('more')
|
||||||
|
end
|
||||||
|
|
||||||
-- We need to keep track of the current message column to be able to
|
-- We need to keep track of the current message column to be able to
|
||||||
-- append or overwrite messages for :echon or carriage returns.
|
-- append or overwrite messages for :echon or carriage returns.
|
||||||
local col = 0
|
local col = 0
|
||||||
@ -231,6 +241,7 @@ function M.show_msg(tar, content, replace_last, append, more)
|
|||||||
hl_group = chunk[3],
|
hl_group = chunk[3],
|
||||||
undo_restore = false,
|
undo_restore = false,
|
||||||
invalidate = true,
|
invalidate = true,
|
||||||
|
priority = 1,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -245,21 +256,20 @@ function M.show_msg(tar, content, replace_last, append, more)
|
|||||||
if tar == 'box' then
|
if tar == 'box' then
|
||||||
api.nvim_win_set_width(ext.wins[ext.tab].box, width)
|
api.nvim_win_set_width(ext.wins[ext.tab].box, width)
|
||||||
local h = api.nvim_win_text_height(ext.wins[ext.tab].box, { start_row = start_row })
|
local h = api.nvim_win_text_height(ext.wins[ext.tab].box, { start_row = start_row })
|
||||||
if h.all > (more and 1 or math.ceil(o.lines * 0.5)) then
|
if more and h.all > 1 then
|
||||||
api.nvim_buf_set_lines(ext.bufs.box, start_row, -1, false, {})
|
msg_to_more(tar)
|
||||||
api.nvim_win_set_width(ext.wins[ext.tab].box, M.box.width)
|
api.nvim_win_set_width(ext.wins[ext.tab].box, M.box.width)
|
||||||
M.msg_history_show({ { 'spill', content } }) -- show message in 'more' window
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
M.set_pos('box')
|
M.set_pos('box')
|
||||||
|
M.box.width = width
|
||||||
if restart then
|
if restart then
|
||||||
M.box.timer:stop()
|
M.box.timer:stop()
|
||||||
M.box.timer:set_repeat(4000)
|
M.box.timer:set_repeat(4000)
|
||||||
M.box.timer:again()
|
M.box.timer:again()
|
||||||
else
|
else
|
||||||
M.box:start_timer(ext.bufs.box, row - start_row + 1)
|
M.box:start_timer(ext.bufs.box, row - start_row + 1)
|
||||||
M.box.width = width
|
|
||||||
end
|
end
|
||||||
elseif tar == 'cmd' and dupe == 0 then
|
elseif tar == 'cmd' and dupe == 0 then
|
||||||
fn.clearmatches(ext.wins[ext.tab].cmd) -- Clear matchparen highlights.
|
fn.clearmatches(ext.wins[ext.tab].cmd) -- Clear matchparen highlights.
|
||||||
@ -272,8 +282,8 @@ function M.show_msg(tar, content, replace_last, append, more)
|
|||||||
else
|
else
|
||||||
local h = api.nvim_win_text_height(ext.wins[ext.tab].cmd, {})
|
local h = api.nvim_win_text_height(ext.wins[ext.tab].cmd, {})
|
||||||
if more and h.all > ext.cmdheight then
|
if more and h.all > ext.cmdheight then
|
||||||
api.nvim_buf_set_lines(ext.bufs.cmd, start_row, -1, false, {})
|
ext.cmd.highlighter:destroy()
|
||||||
M.msg_history_show({ { 'spill', content } }) -- show message in 'more' window
|
msg_to_more(tar)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -302,7 +312,6 @@ function M.show_msg(tar, content, replace_last, append, more)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local append_more = 0
|
|
||||||
local replace_bufwrite = false
|
local replace_bufwrite = false
|
||||||
--- Route the message to the appropriate sink.
|
--- Route the message to the appropriate sink.
|
||||||
---
|
---
|
||||||
@ -329,7 +338,7 @@ function M.msg_show(kind, content, _, _, append)
|
|||||||
-- Verbose messages are sent too often to be meaningful in the cmdline:
|
-- Verbose messages are sent too often to be meaningful in the cmdline:
|
||||||
-- always route to box regardless of cfg.msg.pos.
|
-- always route to box regardless of cfg.msg.pos.
|
||||||
M.show_msg('box', content, false, append)
|
M.show_msg('box', content, false, append)
|
||||||
elseif append_more > 0 and ext.cfg.msg.pos == 'cmd' then
|
elseif ext.cfg.msg.pos == 'cmd' and api.nvim_get_current_win() == ext.wins[ext.tab].more then
|
||||||
-- Append message to already open 'more' window.
|
-- Append message to already open 'more' window.
|
||||||
M.msg_history_show({ { 'spill', content } })
|
M.msg_history_show({ { 'spill', content } })
|
||||||
api.nvim_command('norm! G')
|
api.nvim_command('norm! G')
|
||||||
@ -351,8 +360,9 @@ function M.msg_show(kind, content, _, _, append)
|
|||||||
M.virt.last[M.virt.idx.search][1] = nil
|
M.virt.last[M.virt.idx.search][1] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Messages sent as a result of a typed command should be routed to the more window.
|
-- Typed "inspection" messages should be routed to the more window.
|
||||||
local more = ext.cmd.level >= 0 or kind == 'list_cmd'
|
local typed_more = { 'echo', 'echomsg', 'lua_print' }
|
||||||
|
local more = kind == 'list_cmd' or (ext.cmd.level >= 0 and vim.tbl_contains(typed_more, kind))
|
||||||
M.show_msg(tar, content, replace_bufwrite, append, more)
|
M.show_msg(tar, content, replace_bufwrite, append, more)
|
||||||
-- Replace message for every second bufwrite message.
|
-- Replace message for every second bufwrite message.
|
||||||
replace_bufwrite = not replace_bufwrite and kind == 'bufwrite'
|
replace_bufwrite = not replace_bufwrite and kind == 'bufwrite'
|
||||||
@ -402,13 +412,13 @@ function M.msg_history_show(entries)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Appending messages while 'more' window is open.
|
-- Appending messages while 'more' window is open.
|
||||||
if append_more == 0 then
|
local append_more = api.nvim_get_current_win() == ext.wins[ext.tab].more
|
||||||
|
if not append_more then
|
||||||
api.nvim_buf_set_lines(ext.bufs.more, 0, -1, false, {})
|
api.nvim_buf_set_lines(ext.bufs.more, 0, -1, false, {})
|
||||||
end
|
end
|
||||||
append_more = append_more + 1
|
|
||||||
|
|
||||||
for i, entry in ipairs(entries) do
|
for i, entry in ipairs(entries) do
|
||||||
M.show_msg('more', entry[2], i == 1 and append_more < 2, false)
|
M.show_msg('more', entry[2], i == 1 and not append_more, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
M.set_pos('more')
|
M.set_pos('more')
|
||||||
@ -443,17 +453,16 @@ function M.set_pos(type)
|
|||||||
end
|
end
|
||||||
-- It's actually closed one event iteration later so schedule in case it was open.
|
-- It's actually closed one event iteration later so schedule in case it was open.
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
api.nvim_create_autocmd('WinEnter', {
|
api.nvim_set_current_win(win)
|
||||||
|
api.nvim_create_autocmd('WinLeave', {
|
||||||
once = true,
|
once = true,
|
||||||
callback = function()
|
callback = function()
|
||||||
if api.nvim_win_is_valid(win) then
|
if api.nvim_win_is_valid(win) then
|
||||||
api.nvim_win_set_config(win, { hide = true })
|
api.nvim_win_set_config(win, { hide = true })
|
||||||
end
|
end
|
||||||
append_more = 0
|
|
||||||
end,
|
end,
|
||||||
desc = 'Hide inactive "more" window.',
|
desc = 'Hide inactive "more" window.',
|
||||||
})
|
})
|
||||||
api.nvim_set_current_win(win)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -88,7 +88,8 @@ function M.tab_check_wins()
|
|||||||
api.nvim_set_option_value('smoothscroll', true, { scope = 'local' })
|
api.nvim_set_option_value('smoothscroll', true, { scope = 'local' })
|
||||||
local ft = type == 'cmd' and 'cmdline' or ('msg' .. type)
|
local ft = type == 'cmd' and 'cmdline' or ('msg' .. type)
|
||||||
api.nvim_set_option_value('filetype', ft, { scope = 'local' })
|
api.nvim_set_option_value('filetype', ft, { scope = 'local' })
|
||||||
api.nvim_set_option_value('eventignorewin', 'all', { scope = 'local' })
|
local ignore = 'all' .. (type == 'more' and ',-WinLeave,-TextYankPost' or '')
|
||||||
|
api.nvim_set_option_value('eventignorewin', ignore, { scope = 'local' })
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user