commit 4a4de73043060a4c0f8e91bc69ff62c69fcd8702
parent dc5d313d66c620699a926aeefaf20bb0ec0d653e
Author: Yochem van Rosmalen <git@yochem.nl>
Date: Fri, 27 Feb 2026 23:50:51 +0100
fix(help): better align local-additions #38097
Problem:
Descriptions of plugins often contain taglinks which are generally
concealed. This misaligns them by 2 characters with descriptions that
don't have a taglink in them.
Solution:
Don't count "bar" characters (`|`) for the description width.
Example:
Actual buffer content:
```
myplugin.txt |lsp| is cool
myplugin.txt this is a nice plugin
```
Rendered as:
```
myplugin.txt lsp is cool
myplugin.txt this is a nice plugin
```
Diffstat:
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/runtime/lua/vim/_core/help.lua b/runtime/lua/vim/_core/help.lua
@@ -175,7 +175,8 @@ function M.local_additions()
if plugname and desc then
-- left-align taglink and right-align description by inserting spaces in between
local plug_width = vim.fn.strdisplaywidth(plugname)
- local desc_width = vim.fn.strdisplaywidth(desc)
+ local _, concealed_chars = desc:gsub('|', '')
+ local desc_width = vim.fn.strdisplaywidth(desc) - concealed_chars
-- max(l, 1) forces at least one space for if the description is too long
local spaces = string.rep(' ', math.max(textwidth - desc_width - plug_width - 2, 1))
local fmt = string.format('|%s|%s%s', plugname, spaces, desc)
diff --git a/src/gen/gen_help_html.lua b/src/gen/gen_help_html.lua
@@ -173,11 +173,23 @@ local function url_encode(s)
end
local function to_titlecase(s)
- local text = ''
+ local special = {
+ ['UI'] = true,
+ ['API'] = true,
+ ['TUI'] = true,
+ ['LSP'] = true,
+ ['TS'] = true,
+ }
+ ---@type string[]
+ local text = {}
for w in vim.gsplit(s, '[ \t]+') do
- text = ('%s %s%s'):format(text, vim.fn.toupper(w:sub(1, 1)), w:sub(2))
+ local sub = vim.fn.toupper(w:sub(1, 1)) .. w:sub(2):lower()
+ if special[w:upper()] then
+ sub = w:upper()
+ end
+ text[#text + 1] = sub
end
- return text
+ return table.concat(text, ' ')
end
local function to_heading_tag(text)
@@ -588,7 +600,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
-- Remove tags from ToC text.
local heading_node = first(root, 'heading')
- local hname = trim(node_text(heading_node):gsub('%*.*%*', ''))
+ local hname = to_titlecase(trim(node_text(heading_node):gsub('%*.*%*', '')))
if not heading_node or hname == '' then
return '' -- Spurious "===" or "---" in the help doc.
end
@@ -606,7 +618,12 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
)
end
local el = node_name == 'h1' and 'h2' or 'h3'
- return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(el, tagname, trimmed, el)
+ return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(
+ el,
+ tagname,
+ to_titlecase(trimmed),
+ el
+ )
elseif node_name == 'heading' then
return trimmed
elseif node_name == 'column_heading' or node_name == 'column_name' then