aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/develop.txt3
-rw-r--r--runtime/doc/lua.txt116
-rw-r--r--runtime/lua/vim/shared.lua8
-rw-r--r--scripts/gen_help_html.lua60
4 files changed, 110 insertions, 77 deletions
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index 14b66a0736..1ba6ae757b 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -164,6 +164,9 @@ Strict "vimdoc" subset:
that you don't want auto-wrapped. Lists are always rendered with "flow"
(soft-wrapped) layout instead of preformatted (hard-wrapped) layout common
in legacy :help docs.
+ - Limitation: currently the parser https://github.com/neovim/tree-sitter-vimdoc
+ does not understand numbered listitems, so use a bullet symbol (- or •)
+ before numbered items, e.g. "- 1." instead of "1.".
- Separate blocks (paragraphs) of content by a blank line(s).
- Do not use indentation in random places—that prevents the page from using
"flow" layout. If you need a preformatted section, put it in
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 29e0508f60..7330453778 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -144,7 +144,7 @@ documentation at https://www.lua.org/manual/5.1/manual.html#pdf-require.
For example, if 'runtimepath' is `foo,bar` and |package.cpath| was
`./?.so;./?.dll` at startup, `require('mod')` searches these paths in order
-and loads the first module found ("first wins"):
+and loads the first module found ("first wins"): >
foo/lua/mod.lua
foo/lua/mod/init.lua
bar/lua/mod.lua
@@ -153,7 +153,7 @@ and loads the first module found ("first wins"):
foo/lua/mod.dll
bar/lua/mod.so
bar/lua/mod.dll
-
+<
*lua-package-path*
Nvim automatically adjusts |package.path| and |package.cpath| according to the
effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
@@ -166,37 +166,33 @@ added to |package.cpath|. In this case, instead of appending `/lua/?.lua` and
`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of
the existing |package.cpath| are used. Example:
-1. Given that
+- 1. Given that
- 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`;
- - initial (defined at compile-time or derived from
- `$LUA_CPATH`/`$LUA_INIT`) |package.cpath| contains
- `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`.
-2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in
- order: parts of the path starting from the first path component containing
- question mark and preceding path separator.
-3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same
- as the suffix of the first path from |package.path| (i.e. `./?.so`). Which
- leaves `/?.so` and `/a?d/j/g.elf`, in this order.
-4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The
- second one contains a semicolon which is a paths separator so it is out,
- leaving only `/foo/bar` and `/abc`, in order.
-5. The cartesian product of paths from 4. and suffixes from 3. is taken,
- giving four variants. In each variant, a `/lua` path segment is inserted
- between path and suffix, leaving:
-
- - `/foo/bar/lua/?.so`
- - `/foo/bar/lua/a?d/j/g.elf`
- - `/abc/lua/?.so`
- - `/abc/lua/a?d/j/g.elf`
-
-6. New paths are prepended to the original |package.cpath|.
-
-The result will look like this:
-
- `/foo/bar,/xxx;yyy/baz,/abc` ('runtimepath')
- × `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so` (`package.cpath`)
-
- = `/foo/bar/lua/?.so;/foo/bar/lua/a?d/j/g.elf;/abc/lua/?.so;/abc/lua/a?d/j/g.elf;./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`
+ - initial |package.cpath| (defined at compile-time or derived from
+ `$LUA_CPATH` / `$LUA_INIT`) contains `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`.
+- 2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in
+ order: parts of the path starting from the first path component containing
+ question mark and preceding path separator.
+- 3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same
+ as the suffix of the first path from |package.path| (i.e. `./?.so`). Which
+ leaves `/?.so` and `/a?d/j/g.elf`, in this order.
+- 4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The
+ second one contains a semicolon which is a paths separator so it is out,
+ leaving only `/foo/bar` and `/abc`, in order.
+- 5. The cartesian product of paths from 4. and suffixes from 3. is taken,
+ giving four variants. In each variant a `/lua` path segment is inserted
+ between path and suffix, leaving:
+ - `/foo/bar/lua/?.so`
+ - `/foo/bar/lua/a?d/j/g.elf`
+ - `/abc/lua/?.so`
+ - `/abc/lua/a?d/j/g.elf`
+- 6. New paths are prepended to the original |package.cpath|.
+
+The result will look like this: >
+
+ /foo/bar,/xxx;yyy/baz,/abc ('runtimepath')
+ × ./?.so;/def/ghi/a?d/j/g.elf;/def/?.so (package.cpath)
+ = /foo/bar/lua/?.so;/foo/bar/lua/a?d/j/g.elf;/abc/lua/?.so;/abc/lua/a?d/j/g.elf;./?.so;/def/ghi/a?d/j/g.elf;/def/?.so
Note:
@@ -278,7 +274,7 @@ arguments separated by " " (space) instead of "\t" (tab).
:lua require"lpeg"
:lua -- balanced parenthesis grammar:
:lua bp = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" }
- :luado if bp:match(line) then return "-->\t" .. line end
+ :luado if bp:match(line) then return "=>\t" .. line end
<
*:luafile*
:luafile {file}
@@ -595,12 +591,12 @@ vim.highlight.range({bufnr}, {ns}, {hlgroup}, {start}, {finish}, {opts})
Apply highlight group to range of text.
Parameters: ~
- {bufnr} buffer number
- {ns} namespace for highlights
- {hlgroup} highlight group name
- {start} starting position (tuple {line,col})
- {finish} finish position (tuple {line,col})
- {opts} optional parameters:
+ • {bufnr} buffer number
+ • {ns} namespace for highlights
+ • {hlgroup} highlight group name
+ • {start} starting position (tuple {line,col})
+ • {finish} finish position (tuple {line,col})
+ • {opts} optional parameters:
• `regtype`: type of range (characterwise, linewise,
or blockwise, see |setreg()|), default `'v'`
• `inclusive`: range includes end position,
@@ -653,22 +649,22 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
Examples: >
vim.diff('a\n', 'b\nc\n')
- -->
+ =>
@@ -1 +1,2 @@
-a
+b
+c
vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
- -->
+ =>
{
{1, 1, 1, 2}
}
<
Parameters: ~
- {a} First string to compare
- {b} Second string to compare
- {opts} Optional parameters:
+ • {a} First string to compare
+ • {b} Second string to compare
+ • {opts} Optional parameters:
• `on_hunk` (callback):
Invoked for each hunk in the diff. Return a negative number
to cancel the callback for any remaining hunks.
@@ -734,13 +730,13 @@ vim.spell.check({str}) *vim.spell.check()*
Example: >
vim.spell.check("the quik brown fox")
- -->
+ =>
{
{'quik', 'bad', 4}
}
<
Parameters: ~
- {str} String to spell check.
+ • {str} String to spell check.
Return: ~
List of tuples with three items:
@@ -829,9 +825,9 @@ vim.iconv({str}, {from}, {to}[, {opts}]) *vim.iconv()*
can accept, see ":Man 3 iconv".
Parameters: ~
- {str} (string) Text to convert
- {from} (string) Encoding of {str}
- {to} (string) Target encoding
+ • {str} (string) Text to convert
+ • {from} (string) Encoding of {str}
+ • {to} (string) Target encoding
Returns: ~
Converted string if conversion succeeds, `nil` otherwise.
@@ -849,8 +845,8 @@ vim.defer_fn({fn}, {timeout}) *vim.defer_fn*
safe to call.
Parameters: ~
- {fn} Callback to call once {timeout} expires
- {timeout} Time in ms to wait before calling {fn}
+ • {fn} Callback to call once {timeout} expires
+ • {timeout} Time in ms to wait before calling {fn}
Returns: ~
|vim.loop|.new_timer() object
@@ -863,10 +859,10 @@ vim.wait({time} [, {callback}, {interval}, {fast_only}]) *vim.wait()*
this time.
Parameters: ~
- {time} Number of milliseconds to wait
- {callback} Optional callback. Waits until {callback} returns true
- {interval} (Approximate) number of milliseconds to wait between polls
- {fast_only} If true, only |api-fast| events will be processed.
+ • {time} Number of milliseconds to wait
+ • {callback} Optional callback. Waits until {callback} returns true
+ • {interval} (Approximate) number of milliseconds to wait between polls
+ • {fast_only} If true, only |api-fast| events will be processed.
If called from while in an |api-fast| event, will
automatically be set to `true`.
@@ -1254,7 +1250,7 @@ Option:get()
-- { space = "_", tab = ">~", }
for char, representation in pairs(vim.opt.listchars:get()) do
- print(char, "->", representation)
+ print(char, "=>", representation)
end
<
For values that are lists of flags, a set will be returned with the flags
@@ -1643,10 +1639,10 @@ split({s}, {sep}, {kwargs}) *vim.split()*
Examples: >
- split(":aa::b:", ":") --> {'','aa','','b',''}
- split("axaby", "ab?") --> {'','x','y'}
- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
+ split(":aa::b:", ":") => {'','aa','','b',''}
+ split("axaby", "ab?") => {'','x','y'}
+ split("x*yz*o", "*", {plain=true}) => {'x','yz','o'}
+ split("|x|y|z|", "|", {trimempty=true}) => {'x', 'y', 'z'}
<
@alias split_kwargs {plain: boolean, trimempty: boolean} | boolean | nil
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 4b3a681eb2..f03d608e56 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -100,10 +100,10 @@ end
---
--- Examples:
--- <pre>
---- split(":aa::b:", ":") --> {'','aa','','b',''}
---- split("axaby", "ab?") --> {'','x','y'}
---- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
---- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
+--- split(":aa::b:", ":") => {'','aa','','b',''}
+--- split("axaby", "ab?") => {'','x','y'}
+--- split("x*yz*o", "*", {plain=true}) => {'x','yz','o'}
+--- split("|x|y|z|", "|", {trimempty=true}) => {'x', 'y', 'z'}
--- </pre>
---
---@see |vim.gsplit()|
diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 13601b91f5..06ea1831b0 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -249,6 +249,16 @@ local function getbuflinestr(node, bufnr, offset)
return table.concat(lines, '\n')
end
+-- Gets the whitespace just before `node` from the raw buffer text.
+-- Needed for preformatted `old` lines.
+local function getws(node, bufnr)
+ local line1, c1, line2, _ = node:range()
+ local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1]
+ local text_before = raw:sub(1, c1)
+ local leading_ws = text_before:match('%s+$') or ''
+ return leading_ws
+end
+
local function get_tagname(node, bufnr)
local text = vim.treesitter.get_node_text(node, bufnr)
local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink') and ("'%s'"):format(text) or text
@@ -287,6 +297,16 @@ local function has_ancestor(node, ancestor_name)
return false
end
+-- Gets the first matching child node matching `name`.
+local function first(node, name)
+ for c, _ in node:iter_children() do
+ if c:named() and c:type() == name then
+ return c
+ end
+ end
+ return nil
+end
+
local function validate_link(node, bufnr, fname)
local helppage, tagname = get_tagname(node:child(1), bufnr)
local ignored = false
@@ -354,12 +374,21 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local parent = root:parent() and root:parent():type() or nil
local text = ''
local trimmed
- local function node_text(node)
- return vim.treesitter.get_node_text(node or root, opt.buf)
+ -- Gets leading whitespace of `node`.
+ local function ws(node)
+ node = node or root
+ local ws_ = getws(node, opt.buf)
+ -- XXX: first node of a (line) includes whitespace, even after
+ -- https://github.com/neovim/tree-sitter-vimdoc/pull/31 ?
+ if ws_ == '' then
+ ws_ = vim.treesitter.get_node_text(node, opt.buf):match('^%s+') or ''
+ end
+ return ws_
end
- -- Gets leading whitespace of the current node.
- local function ws()
- return node_text():match('^%s+') or ''
+ local function node_text(node, ws_)
+ node = node or root
+ ws_ = (ws_ == nil or ws_ == true) and getws(node, opt.buf) or ''
+ return string.format('%s%s', ws_, vim.treesitter.get_node_text(node, opt.buf))
end
if root:named_child_count() == 0 or node_name == 'ERROR' then
@@ -390,18 +419,23 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
-- Remove "===" and tags from ToC text.
local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', ''))
+ -- Use the first *tag* node as the heading anchor, if any.
+ local tagnode = first(root, 'tag')
+ local tagname = tagnode and url_encode(node_text(tagnode:child(1), false)) or to_heading_tag(hname)
if node_name == 'h1' or #headings == 0 then
- table.insert(headings, { name = hname, subheadings = {}, })
+ table.insert(headings, { name = hname, subheadings = {}, tag = tagname })
else
- table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, })
+ table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, tag = tagname })
end
local el = node_name == 'h1' and 'h2' or 'h3'
- return ('<a name="%s"></a><%s class="help-heading">%s</%s>\n'):format(to_heading_tag(hname), el, text, el)
+ -- If we are re-using the *tag*, this heading anchor is redundant.
+ local a = tagnode and '' or ('<a name="%s"></a>'):format(tagname)
+ return ('%s<%s class="help-heading">%s</%s>\n'):format(a, el, text, el)
elseif node_name == 'column_heading' or node_name == 'column_name' then
if root:has_error() then
return text
end
- return ('<div class="help-column_heading">%s%s</div>'):format(ws(), trimmed)
+ return ('<div class="help-column_heading">%s</div>'):format(text)
elseif node_name == 'block' then
if is_blank(text) then
return ''
@@ -462,9 +496,9 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
local in_heading = vim.tbl_contains({'h1', 'h2', 'h3'}, parent)
local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag'
- local tagname = node_text(root:child(1))
+ local tagname = node_text(root:child(1), false)
if vim.tbl_count(stats.first_tags) < 2 then
- -- First 2 tags in the doc will be anchored at the main heading.
+ -- Force the first 2 tags in the doc to be anchored at the main heading.
table.insert(stats.first_tags, tagname)
return ''
end
@@ -701,10 +735,10 @@ local function gen_one(fname, to_fname, old, commit)
local n = 0 -- Count of all headings + subheadings.
for _, h1 in ipairs(headings) do n = n + 1 + #h1.subheadings end
for _, h1 in ipairs(headings) do
- toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(to_heading_tag(h1.name), h1.name)
+ toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(h1.tag, h1.name)
if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many.
for _, h2 in ipairs(h1.subheadings) do
- toc = toc .. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(to_heading_tag(h2.name), h2.name)
+ toc = toc .. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(h2.tag, h2.name)
end
end
toc = toc .. '</div>'