From 5333d6371bfa2fe048e5d99e0e843657b3b0e33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Bettencourt?= Date: Tue, 15 Apr 2025 14:27:51 +0100 Subject: [PATCH] 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 --- runtime/lua/man.lua | 17 +++++++++++++++-- test/functional/plugin/man_spec.lua | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 61950f184e..90a6fe1087 100644 --- 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 index f357aab4d6..a77879aa7d 100644 --- 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()