fix(man.lua): cache pages until width changes #40607

Problem: :Man unloads hidden buffers, so reopening large pages reruns rendering
even when the width is unchanged.

Solution: keep regular man buffers loaded and refresh them only when the
effective width changes.
This commit is contained in:
Barrett Ruth
2026-07-06 05:45:10 -05:00
committed by GitHub
parent f034e5f66b
commit a6827be98f
2 changed files with 45 additions and 10 deletions

View File

@@ -416,7 +416,7 @@ end
local function set_options()
vim.bo.swapfile = false
vim.bo.buftype = 'nofile'
vim.bo.bufhidden = 'unload'
vim.bo.bufhidden = 'hide'
vim.bo.modified = false
vim.bo.readonly = true
vim.bo.modifiable = false
@@ -427,10 +427,8 @@ end
--- @type boolean?
local localfile_arg
--- @param path string
--- @param silent boolean?
--- @return string
local function get_page(path, silent)
--- @return integer
local function get_manwidth()
-- Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065).
-- Soft-wrap: ftplugin/man.lua sets wrap/breakindent/….
-- Hard-wrap: driven by `man`.
@@ -438,11 +436,20 @@ local function get_page(path, silent)
if (vim.g.man_hardwrap or 1) ~= 1 then
manwidth = 999
elseif vim.env.MANWIDTH then
vim.env.MANWIDTH = vim._tointeger(vim.env.MANWIDTH) or 0
manwidth = math.min(vim.env.MANWIDTH, api.nvim_win_get_width(0) - vim.o.wrapmargin)
local env_manwidth = vim._tointeger(vim.env.MANWIDTH) or 0
manwidth = math.min(env_manwidth, api.nvim_win_get_width(0) - vim.o.wrapmargin)
else
manwidth = api.nvim_win_get_width(0) - vim.o.wrapmargin
end
return manwidth
end
--- @param path string
--- @param silent boolean?
--- @param manwidth integer?
--- @return string
local function get_page(path, silent, manwidth)
manwidth = manwidth or get_manwidth()
if localfile_arg == nil then
local mpath = get_path('man')
@@ -690,6 +697,7 @@ function M.init_pager()
end
set_options()
vim.bo.bufhidden = 'unload'
end
--- Combine the name and sect into a manpage reference so that all
@@ -794,10 +802,12 @@ function M.read_page(ref)
return 'no manual entry for ' .. name
end
local _, sect1 = parse_path(path)
local page = get_page(path)
local _, page_sect = parse_path(path)
local manwidth = get_manwidth()
local page = get_page(path, nil, manwidth)
vim.b.man_sect = sect1
vim.b.manwidth = manwidth
vim.b.man_sect = page_sect
vim.bo.modifiable = true
vim.bo.readonly = false
vim.bo.swapfile = false
@@ -822,6 +832,20 @@ function M.read_page(ref)
set_options()
end
--- @return string? err
function M.refresh_page()
if vim.bo.filetype ~= 'man' then
return
end
local ref = api.nvim_buf_get_name(0):match('man://(.*)')
if not ref or vim.b.manwidth == nil or vim.b.manwidth == get_manwidth() then
return
end
return M.read_page(ref)
end
function M.show_toc()
local bufnr = api.nvim_get_current_buf()
local bufname = api.nvim_buf_get_name(bufnr)