fix(help): :helptags on CRLF helpfiles

Problem:
The vimdoc parser does not treat "\r" as whitespace, so in a CRLF
helpfile the codeblock rule fails and "*" pairs inside examples become
tags. On Windows this generates duplicate "." and "/" tags:

    D:/a/neovim/neovim/build/bin/nvim.exe -u NONE -i NONE -e --headless -c "helptags ++t doc" -c "exe 'cquit' !empty(v:errmsg)""
    Error in command line:
    E154: Duplicate tag "." in gui.txt and repeat.txt
    E154: Duplicate tag "/" in pattern.txt and usr_08.txt
    E154: Duplicate tag "/" in usr_08.txt and pattern.txt

Note: The old C parser was unaffected because it read helpfiles in text
mode (`os_fopen(…, "r")`).

Solution:
Strip "\r" before parsing.
This commit is contained in:
Justin M. Keyes
2026-08-24 22:43:47 +02:00
parent 1ef030f162
commit fb5d466a35
2 changed files with 5 additions and 1 deletions

View File

@@ -433,6 +433,8 @@ local function extract_tags(tags, file, name)
return
end
--- @cast source string
-- The grammar treats "\r" as part of a word, so CRLF files would yield bogus tags.
source = source:gsub('\r\n', '\n')
local query = ts.query.parse('vimdoc', '(tag (word) @tagname)')
local parser = ts.get_string_parser(source, 'vimdoc')

View File

@@ -354,11 +354,13 @@ describe(':helptags', function()
fn.mkdir('Xhelptags/doc/sub', 'p')
-- A "|" in a tag would break |links|, and "*Xd" is not closed, so neither is a tag.
write_file('Xhelptags/doc/sub/Xc.txt', '*Xc*\n*X|c*\n*Xd\n')
-- CRLF helpfile: "\r" must not confuse the parser into finding tags in an example.
write_file('Xhelptags/doc/Xe.txt', '*Xe*\r\n>\r\n\t+-----+\r\n\t|/* a.c */ |/* b.c */ |\r\n')
command('helptags Xhelptags/doc')
eq(
eval("['Xa Xa.txt /*Xa*','Xb Xb.txt /*Xb*','Xc sub/Xc.txt /*Xc*']"),
eval("['Xa Xa.txt /*Xa*','Xb Xb.txt /*Xb*','Xc sub/Xc.txt /*Xc*','Xe Xe.txt /*Xe*']"),
eval("readfile('Xhelptags/doc/tags')")
)