Files
neovim/runtime/lua/vim/_extui/shared.lua
Luuk van Baal 76f76fb083 fix(extui): only append messages exceeding 'cmdheight' to "more"
Problem:  8defe1a declared the "more" window the most convenient place to
          route messages to if it is already open for msg.pos == 'cmd'.
          In usage, this doesn't appear to be the case. Appending messages
          as added in that commit is still useful, but should only be done
          for messages that spill 'cmdheight'.
Solution: Only append messages exceeding 'cmdheight' to the more window.
          To do this, instead of immediately writing to the more buffer,
          write to the cmd buffer and calculate its height. Then copy the
          text and its highlights to the more buffer.
2025-06-13 14:28:01 +02:00

102 lines
3.9 KiB
Lua

local api, o = vim.api, vim.o
local M = {
msg = nil, ---@type vim._extui.messages
cmd = nil, ---@type vim._extui.cmdline
ns = api.nvim_create_namespace('nvim._ext_ui'),
augroup = api.nvim_create_augroup('nvim._ext_ui', {}),
cmdheight = -1, -- 'cmdheight' option value set by user.
wins = { box = -1, cmd = -1, more = -1, prompt = -1 },
bufs = { box = -1, cmd = -1, more = -1, prompt = -1 },
cfg = {
enable = true,
msg = { -- Options related to the message module.
---@type 'box'|'cmd' Type of window used to place messages, either in the
---cmdline or in a separate ephemeral message box window.
pos = 'cmd',
box = { -- Options related to the message box window.
timeout = 4000, -- Time a message is visible.
},
},
},
}
local wincfg = { -- Default cfg for nvim_open_win().
relative = 'laststatus',
style = 'minimal',
col = 0,
row = 1,
width = 10000,
height = 1,
noautocmd = true,
}
local tab = 0
--- Ensure the various buffers and windows have not been deleted.
function M.tab_check_wins()
local curtab = api.nvim_get_current_tabpage()
for _, type in ipairs({ 'box', 'cmd', 'more', 'prompt' }) do
local setopt = not api.nvim_buf_is_valid(M.bufs[type])
if setopt then
M.bufs[type] = api.nvim_create_buf(false, true)
if type == 'cmd' then
-- Attach highlighter to the cmdline buffer.
local parser = assert(vim.treesitter.get_parser(M.bufs.cmd, 'vim', {}))
M.cmd.highlighter = vim.treesitter.highlighter.new(parser)
end
end
if
tab ~= curtab
or not api.nvim_win_is_valid(M.wins[type])
or not api.nvim_win_get_config(M.wins[type]).zindex -- no longer floating
then
local top = { vim.opt.fcs:get().horiz or o.ambw == 'single' and '' or '-', 'WinSeparator' }
local border = (type == 'more' or type == 'prompt') and { '', top, '', '', '', '', '', '' }
local cfg = vim.tbl_deep_extend('force', wincfg, {
focusable = type == 'more',
mouse = type ~= 'cmd' and true or nil,
anchor = type ~= 'cmd' and 'SE' or nil,
hide = type ~= 'cmd' or M.cmdheight == 0 or nil,
title = type == 'more' and 'Messages' or nil,
border = type == 'box' and 'single' or border or 'none',
-- kZIndexMessages < zindex < kZIndexCmdlinePopupMenu (grid_defs.h), 'more' below others.
zindex = 200 - (type == 'more' and 1 or 0),
_cmdline_offset = type == 'cmd' and 0 or nil,
})
if tab ~= curtab and api.nvim_win_is_valid(M.wins[type]) then
cfg = api.nvim_win_get_config(M.wins[type])
api.nvim_win_close(M.wins[type], true)
end
M.wins[type] = api.nvim_open_win(M.bufs[type], false, cfg)
if type == 'cmd' then
api.nvim_win_set_hl_ns(M.wins[type], M.ns)
end
setopt = true
elseif api.nvim_win_get_buf(M.wins[type]) ~= M.bufs[type] then
api.nvim_win_set_buf(M.wins[type], M.bufs[type])
setopt = true
end
if setopt then
api.nvim_buf_set_name(M.bufs[type], 'nvim.' .. type)
if type == 'more' then
-- Close more window with `q`, same as `checkhealth`
api.nvim_buf_set_keymap(M.bufs.more, 'n', 'q', '<Cmd>wincmd c<CR>', {})
end
-- Fire a FileType autocommand with window context to let the user reconfigure local options.
api.nvim_win_call(M.wins[type], function()
api.nvim_set_option_value('wrap', true, { scope = 'local' })
api.nvim_set_option_value('linebreak', false, { scope = 'local' })
api.nvim_set_option_value('smoothscroll', true, { scope = 'local' })
local ft = type == 'cmd' and 'cmdline' or ('msg' .. type)
api.nvim_set_option_value('filetype', ft, { scope = 'local' })
local ignore = 'all' .. (type == 'more' and ',-TextYankPost' or '')
api.nvim_set_option_value('eventignorewin', ignore, { scope = 'local' })
end)
end
end
tab = curtab
end
return M