commit 5333d6371bfa2fe048e5d99e0e843657b3b0e33f
parent 07b33c326697df0fd922053215fb546de5c4f1b1
Author: João Bettencourt <joao.d.bettencourt@tecnico.ulisboa.pt>
Date: Tue, 15 Apr 2025 14:27:51 +0100
fix(man.lua): E95 when piping to :Man #33068
Problem: When piping raw manpage content into `:Man!`, buf name is
set to 'man://.. ref', but the check only matches the prefix.
Allows duplicate buffers to be created, triggering E95.
Solution: Match full buf name instead of only 'man://' prefix.
If the buffer already exists, generate a unique name with
'man://' .. 'ref' .. '?new=' format.
Refs: #30132
Diffstat:
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
@@ -646,8 +646,21 @@ function M.init_pager()
local _, sect, err = pcall(parse_ref, ref)
vim.b.man_sect = err ~= nil and sect or ''
- if not fn.bufname('%'):match('man://') then -- Avoid duplicate buffers, E95.
- vim.cmd.file({ 'man://' .. fn.fnameescape(ref):lower(), mods = { silent = true } })
+ local man_bufname = 'man://' .. fn.fnameescape(ref):lower()
+
+ -- Raw manpage into (:Man!) overlooks `match('man://')` condition,
+ -- so if the buffer already exists, create new with a non existing name.
+ if vim.fn.bufexists(man_bufname) == 1 then
+ local new_bufname = man_bufname
+ for i = 1, 100 do
+ if vim.fn.bufexists(new_bufname) == 0 then
+ break
+ end
+ new_bufname = ('%s?new=%s'):format(man_bufname, i)
+ end
+ vim.cmd.file({ new_bufname, mods = { silent = true } })
+ elseif not fn.bufname('%'):match('man://') then -- Avoid duplicate buffers, E95.
+ vim.cmd.file({ man_bufname, mods = { silent = true } })
end
set_options()
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
@@ -228,6 +228,24 @@ describe(':Man', function()
matches('quit works!!', fn.system(args, { 'manpage contents' }))
end)
+ it('raw manpage into (:Man!) creates a new buffer #30132', function()
+ local args = {
+ nvim_prog,
+ '--headless',
+ '+Man! foo',
+ '+echo bufname()',
+ '+enew',
+ '+Man! foo',
+ '+echo bufname()',
+ '+enew',
+ '+Man! foo',
+ '+echo bufname()',
+ '+q',
+ }
+ local out = fn.system(args, { 'manpage contents' })
+ assert(out and out:match('man://%?new=%d'))
+ end)
+
it('reports non-existent man pages for absolute paths', function()
skip(is_ci('cirrus'))
local actual_file = tmpname()