feat(gen_help_html.lua): adapt to new parser

- adapt to parser changes from https://github.com/vigoux/tree-sitter-vimdoc/pull/16
- numerous other generator improvements
This commit is contained in:
Justin M. Keyes 2022-09-25 02:20:47 +02:00
parent 7b4c49888a
commit 16336c486e
14 changed files with 600 additions and 412 deletions

View File

@ -83,6 +83,7 @@ and |rpcnotify()|:
let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true})
echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"')
call jobstop(nvim)
<
==============================================================================
API Definitions *api-definitions*
@ -92,7 +93,7 @@ The Nvim C API defines custom types for all function parameters. Some are just
typedefs around C99 standard types, others are Nvim-defined data structures.
Basic types ~
>
API Type C type
------------------------------------------------------------------------
Nil
@ -103,7 +104,7 @@ Basic types ~
Array
Dictionary (msgpack: map)
Object
<
Note: empty Array is accepted as a valid argument for Dictionary parameter.
Special types (msgpack EXT) ~
@ -115,13 +116,13 @@ Special types (msgpack EXT) ~
The EXT object data is the (integer) object handle. The EXT type codes given
in the |api-metadata| `types` key are stable: they will not change and are
thus forward-compatible.
>
EXT Type C type Data
------------------------------------------------------------------------
Buffer enum value kObjectTypeBuffer |bufnr()|
Window enum value kObjectTypeWindow |window-ID|
Tabpage enum value kObjectTypeTabpage internal handle
<
*api-indexing*
Most of the API uses 0-based indices, and ranges are end-exclusive. For the
@ -130,19 +131,19 @@ end of a range, -1 denotes the last line/column.
Exception: the following API functions use "mark-like" indexing (1-based
lines, 0-based columns):
|nvim_get_mark()|
|nvim_buf_get_mark()|
|nvim_buf_set_mark()|
|nvim_win_get_cursor()|
|nvim_win_set_cursor()|
- |nvim_get_mark()|
- |nvim_buf_get_mark()|
- |nvim_buf_set_mark()|
- |nvim_win_get_cursor()|
- |nvim_win_set_cursor()|
Exception: the following API functions use |extmarks| indexing (0-based
indices, end-inclusive):
|nvim_buf_del_extmark()|
|nvim_buf_get_extmark_by_id()|
|nvim_buf_get_extmarks()|
|nvim_buf_set_extmark()|
- |nvim_buf_del_extmark()|
- |nvim_buf_get_extmark_by_id()|
- |nvim_buf_get_extmarks()|
- |nvim_buf_set_extmark()|
*api-fast*
Most API functions are "deferred": they are queued on the main loop and
@ -162,19 +163,19 @@ and return values.
Nvim exposes its API metadata as a Dictionary with these items:
version Nvim version, API level/compatibility
version.api_level API version integer *api-level*
version.api_compatible API is backwards-compatible with this level
version.api_prerelease Declares the API as unstable/unreleased >
(version.api_prerelease && fn.since == version.api_level)
functions API function signatures, containing |api-types| info
describing the return value and parameters.
ui_events |UI| event signatures
ui_options Supported |ui-option|s
{fn}.since API level where function {fn} was introduced
{fn}.deprecated_since API level where function {fn} was deprecated
types Custom handle types defined by Nvim
error_types Possible error types returned by API functions
- version Nvim version, API level/compatibility
- version.api_level API version integer *api-level*
- version.api_compatible API is backwards-compatible with this level
- version.api_prerelease Declares the API as unstable/unreleased
`(version.api_prerelease && fn.since == version.api_level)`
- functions API function signatures, containing |api-types| info
describing the return value and parameters.
- ui_events |UI| event signatures
- ui_options Supported |ui-option|s
- {fn}.since API level where function {fn} was introduced
- {fn}.deprecated_since API level where function {fn} was deprecated
- types Custom handle types defined by Nvim
- error_types Possible error types returned by API functions
About the `functions` map:

View File

@ -151,6 +151,23 @@ DOCUMENTATION *dev-doc*
/// @param dirname The path fragment before `pend`
<
Documentation format ~
For Nvim-owned docs, use the following strict subset of "vimdoc" to ensure
the help doc renders nicely in other formats (such as HTML:
https://neovim.io/doc/user ).
Strict "vimdoc" subset:
- Use lists (like this!) prefixed with "-", "*", or "•", for adjacent lines
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.
- 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
a |help-codeblock| starting with ">".
C docstrings ~
Nvim API documentation lives in the source code, as docstrings (Doxygen

View File

@ -4119,7 +4119,7 @@ This example sorts lines with a specific compare function. >
As a one-liner: >
:call setline(1, sort(getline(1, '$'), function("Strcmp")))
<
scanf() replacement ~
*sscanf*

View File

@ -178,7 +178,7 @@ If a file type that you want to use is not detected yet, there are a few ways
to add it. In any way, it's better not to modify the $VIMRUNTIME/filetype.lua
or $VIMRUNTIME/filetype.vim files. They will be overwritten when installing a
new version of Nvim. The following explains the legacy Vim mechanism (enabled
if |do_legacy_filetype| is set). For Nvim's default mechanism, see
if |g:do_legacy_filetype| is set). For Nvim's default mechanism, see
|vim.filetype.add()|.
A. If you want to overrule all default file type checks.

View File

@ -212,12 +212,6 @@ This is done when viewing the file in Vim, the file itself is not changed. It
is done by going through all help files and obtaining the first line of each
file. The files in $VIMRUNTIME/doc are skipped.
*help-xterm-window*
If you want to have the help in another xterm window, you could use this
command: >
:!xterm -e vim +help &
<
*:helpt* *:helptags*
*E150* *E151* *E152* *E153* *E154* *E670* *E856*
:helpt[ags] [++t] {dir}
@ -372,6 +366,7 @@ To separate sections in a help file, place a series of '=' characters in a
line starting from the first column. The section separator line is highlighted
differently.
*help-codeblock*
To quote a block of ex-commands verbatim, place a greater than (>) character
at the end of the line before the block and a less than (<) character as the
first non-blank on a line following the block. Any line starting in column 1

View File

@ -55,7 +55,6 @@ Lua means "moon" in Portuguese and is pronounced LOO-ah.
==============================================================================
2 THE LANGUAGE *luaref-language*
==============================================================================
This section describes the lexis, the syntax, and the semantics of Lua. In
other words, this section describes which tokens are valid, how they can be
@ -450,21 +449,22 @@ through an arithmetic progression. It has the following syntax:
<
The `block` is repeated for `name` starting at the value of the first `exp`, until
it passes the second `exp` by steps of the third `exp`. More precisely,
a `for` statement like
a `for` statement like >
`for var =` `e1, e2, e3` `do` `block` `end`
for var = e1, e2, e3 do block end
is equivalent to the code:
< is equivalent to the code: >
`do`
`local` `var, limit, step` `= tonumber(e1), tonumber(e2), tonumber(e3)`
`if not (` `var` `and` `limit` `and` `step` `) then error() end`
`while (` `step` `>0 and` `var` `<=` `limit` `)`
`or (` `step` `<=0 and` `var` `>=` `limit` `) do`
`block`
`var` `=` `var` `+` `step`
`end`
`end`
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not ( var and limit and step ) then error() end
while ( step >0 and var <= limit )
or ( step <=0 and var >= limit ) do
block
var = var + step
end
end
<
Note the following:
@ -490,18 +490,18 @@ A `for` statement like
`for` `var1, ..., varn` `in` `explist` `do` `block` `end`
is equivalent to the code:
`do`
`local` `f, s, var` `=` `explist`
`while true do`
`local` `var1, ..., varn` `=` `f(s, var)`
`var` `=` `var1`
`if` `var` `== nil then break end`
`block`
`end`
`end`
is equivalent to the code: >
do
local f, s, var = explist
while true do
local var1, ..., varn = f(s, var)
var = var1
if var == nil then break end
block
end
end
<
Note the following:
- `explist` is evaluated only once. Its results are an iterator function,
@ -1871,25 +1871,25 @@ lua_gc *lua_gc()*
This function performs several tasks, according to the value of the
parameter `what`:
`LUA_GCSTOP` stops the garbage collector.
`LUA_GCRESTART` restarts the garbage collector.
`LUA_GCCOLLECT` performs a full garbage-collection cycle.
`LUA_GCCOUNT` returns the current amount of memory (in Kbytes) in
- `LUA_GCSTOP` stops the garbage collector.
- `LUA_GCRESTART` restarts the garbage collector.
- `LUA_GCCOLLECT` performs a full garbage-collection cycle.
- `LUA_GCCOUNT` returns the current amount of memory (in Kbytes) in
use by Lua.
`LUA_GCCOUNTB` returns the remainder of dividing the current
- `LUA_GCCOUNTB` returns the remainder of dividing the current
amount of bytes of memory in use by Lua by 1024.
`LUA_GCSTEP` performs an incremental step of garbage collection.
- `LUA_GCSTEP` performs an incremental step of garbage collection.
The step "size" is controlled by `data` (larger
values mean more steps) in a non-specified way. If
you want to control the step size you must
experimentally tune the value of `data`. The
function returns 1 if the step finished a
garbage-collection cycle.
`LUA_GCSETPAUSE` sets `data` /100 as the new value for the
- `LUA_GCSETPAUSE` sets `data` /100 as the new value for the
`pause` of the collector (see |luaref-langGC|).
The function returns the previous value of the
pause.
`LUA_GCSETSTEPMUL` sets `data` /100 as the new value for the
- `LUA_GCSETSTEPMUL`sets `data` /100 as the new value for the
`step` `multiplier` of the collector (see
|luaref-langGC|). The function returns the
previous value of the step multiplier.
@ -2717,20 +2717,22 @@ need "inside information" from the interpreter.
lua_Debug *lua_Debug()*
`typedef struct lua_Debug {`
`int event;`
`const char *name; /* (n) */`
`const char *namewhat; /* (n) */`
`const char *what; /* (S) */`
`const char *source; /* (S) */`
`int currentline; /* (l) */`
`int nups; /* (u) number of upvalues */`
`int linedefined; /* (S) */`
`int lastlinedefined; /* (S) */`
`char short_src[LUA_IDSIZE]; /* (S) */`
`/* private part */`
`other fields`
`} lua_Debug;`
>
typedef struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) */
const char *what; /* (S) */
const char *source; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
other fields
} lua_Debug;
<
A structure used to carry different pieces of information about an active
function. `lua_getstack` (see |lua_getstack()|) fills only the private part
@ -2739,28 +2741,28 @@ useful information, call `lua_getinfo` (see |lua_getinfo()|).
The fields of `lua_Debug` have the following meaning:
`source` If the function was defined in a string, then `source` is
- `source` If the function was defined in a string, then `source` is
that string. If the function was defined in a file, then
`source` starts with a `@` followed by the file name.
`short_src` a "printable" version of `source`, to be used in error messages.
`linedefined` the line number where the definition of the function starts.
`lastlinedefined` the line number where the definition of the function ends.
`what` the string `"Lua"` if the function is a Lua function,
- `short_src` a "printable" version of `source`, to be used in error messages.
- `linedefined` the line number where the definition of the function starts.
- `lastlinedefined` the line number where the definition of the function ends.
- `what` the string `"Lua"` if the function is a Lua function,
`"C"` if it is a C function, `"main"` if it is the main
part of a chunk, and `"tail"` if it was a function that
did a tail call. In the latter case, Lua has no other
information about the function.
`currentline` the current line where the given function is executing.
- `currentline` the current line where the given function is executing.
When no line information is available, `currentline` is
set to -1.
`name` a reasonable name for the given function. Because
- `name` a reasonable name for the given function. Because
functions in Lua are first-class values, they do not have
a fixed name: some functions may be the value of multiple
global variables, while others may be stored only in a
table field. The `lua_getinfo` function checks how the
function was called to find a suitable name. If it cannot
find a name, then `name` is set to `NULL`.
`namewhat` explains the `name` field. The value of `namewhat` can be
- `namewhat` explains the `name` field. The value of `namewhat` can be
`"global"`, `"local"`, `"method"`, `"field"`,
`"upvalue"`, or `""` (the empty string), according to how
the function was called. (Lua uses the empty string when

View File

@ -3,7 +3,8 @@
VIM REFERENCE MANUAL by Bram Moolenaar
Quick reference guide
==============================================================================
Quick reference guide
*quickref* *Contents*
tag subject tag subject ~
@ -29,11 +30,11 @@
|Q_to| Text objects |Q_gu| GUI commands
|Q_fo| Folding
------------------------------------------------------------------------------
N is used to indicate an optional count that can be given before the command.
------------------------------------------------------------------------------
*Q_lr* Left-right motions
N is used to indicate an optional count that can be given before the command.
|h| N h left (also: CTRL-H, <BS>, or <Left> key)
|l| N l right (also: <Space> or <Right> key)
|0| 0 to first character in the line (also: <Home> key)
@ -56,6 +57,7 @@ N is used to indicate an optional count that can be given before the command.
|;| N ; repeat the last "f", "F", "t", or "T" N times
|,| N , repeat the last "f", "F", "t", or "T" N times in
opposite direction
------------------------------------------------------------------------------
*Q_ud* Up-down motions
@ -73,6 +75,7 @@ N is used to indicate an optional count that can be given before the command.
given, otherwise it is the |%| command
|gk| N gk up N screen lines (differs from "k" when line wraps)
|gj| N gj down N screen lines (differs from "j" when line wraps)
------------------------------------------------------------------------------
*Q_tm* Text object motions
@ -105,6 +108,7 @@ N is used to indicate an optional count that can be given before the command.
|]#| N ]# N times forward to unclosed "#else" or "#endif"
|[star| N [* N times back to start of comment "/*"
|]star| N ]* N times forward to end of comment "*/"
------------------------------------------------------------------------------
*Q_pa* Pattern searches
@ -168,6 +172,7 @@ N is used to indicate an optional count that can be given before the command.
b[+num] [num] identical to s[+num] above (mnemonic: begin)
b[-num] [num] identical to s[-num] above (mnemonic: begin)
;{search-command} execute {search-command} next
------------------------------------------------------------------------------
*Q_ma* Marks and motions
@ -188,6 +193,7 @@ N is used to indicate an optional count that can be given before the command.
|CTRL-O| N CTRL-O go to Nth older position in jump list
|CTRL-I| N CTRL-I go to Nth newer position in jump list
|:ju| :ju[mps] print the jump list
------------------------------------------------------------------------------
*Q_vm* Various motions
@ -202,6 +208,7 @@ N is used to indicate an optional count that can be given before the command.
|go| N go go to Nth byte in the buffer
|:go| :[range]go[to] [off] go to [off] byte in the buffer
------------------------------------------------------------------------------
*Q_ta* Using tags
@ -229,6 +236,7 @@ N is used to indicate an optional count that can be given before the command.
|:ptjump| :ptj[ump] like ":tjump" but show tag in preview window
|:pclose| :pc[lose] close tag preview window
|CTRL-W_z| CTRL-W z close tag preview window
------------------------------------------------------------------------------
*Q_sc* Scrolling
@ -247,6 +255,7 @@ These only work when 'wrap' is off:
|zl| N zl scroll screen N characters to the left
|zH| N zH scroll screen half a screenwidth to the right
|zL| N zL scroll screen half a screenwidth to the left
------------------------------------------------------------------------------
*Q_in* Inserting text
@ -263,6 +272,7 @@ These only work when 'wrap' is off:
in Visual block mode:
|v_b_I| I insert the same text in front of all the selected lines
|v_b_A| A append the same text after all the selected lines
------------------------------------------------------------------------------
*Q_ai* Insert mode keys
@ -279,6 +289,7 @@ moving around:
|i_<S-Up>| shift-up/down one screenful backward/forward
|i_<End>| <End> cursor after last character in the line
|i_<Home>| <Home> cursor to first character in the line
------------------------------------------------------------------------------
*Q_ss* Special keys in Insert mode
@ -313,6 +324,7 @@ moving around:
|i_0_CTRL-D| 0 CTRL-D delete all indent in the current line
|i_^_CTRL-D| ^ CTRL-D delete all indent in the current line,
restore indent in next line
------------------------------------------------------------------------------
*Q_di* Digraphs
@ -325,12 +337,14 @@ In Insert or Command-line mode:
enter digraph
|i_digraph| {char1} <BS> {char2}
enter digraph if 'digraph' option set
------------------------------------------------------------------------------
*Q_si* Special inserts
|:r| :r [file] insert the contents of [file] below the cursor
|:r!| :r! {command} insert the standard output of {command} below the
cursor
------------------------------------------------------------------------------
*Q_de* Deleting text
@ -346,6 +360,7 @@ In Insert or Command-line mode:
|gJ| N gJ like "J", but without inserting spaces
|v_gJ| {visual}gJ like "{visual}J", but without inserting spaces
|:d| :[range]d [x] delete [range] lines [into register x]
------------------------------------------------------------------------------
*Q_cm* Copying and moving text
@ -363,6 +378,7 @@ In Insert or Command-line mode:
|[p| N [p like P, but adjust indent to current line
|gp| N gp like p, but leave cursor after the new text
|gP| N gP like P, but leave cursor after the new text
------------------------------------------------------------------------------
*Q_ch* Changing text
@ -418,6 +434,7 @@ In Insert or Command-line mode:
left-align the lines in [range] (with [indent])
|:ri| :[range]ri[ght] [width]
right-align the lines in [range]
------------------------------------------------------------------------------
*Q_co* Complex changes
@ -444,6 +461,7 @@ In Insert or Command-line mode:
|:ret| :[range]ret[ab][!] [tabstop]
set 'tabstop' to new value and adjust white space
accordingly
------------------------------------------------------------------------------
*Q_vi* Visual mode
@ -457,6 +475,7 @@ In Insert or Command-line mode:
|v_v| v highlight characters or stop highlighting
|v_V| V highlight linewise or stop highlighting
|v_CTRL-V| CTRL-V highlight blockwise or stop highlighting
------------------------------------------------------------------------------
*Q_to* Text objects (only in Visual mode or after an operator)
@ -509,6 +528,7 @@ In Insert or Command-line mode:
|:sl| :sl[eep] [sec]
don't do anything for [sec] seconds
|gs| N gs goto Sleep for N seconds
------------------------------------------------------------------------------
*Q_km* Key mapping
@ -556,6 +576,7 @@ In Insert or Command-line mode:
like ":mkvimrc", but store current files,
windows, etc. too, to be able to continue
this session later
------------------------------------------------------------------------------
*Q_ab* Abbreviations
@ -570,6 +591,7 @@ In Insert or Command-line mode:
|:abclear| :abc[lear] remove all abbreviations
|:cabclear| :cabc[lear] remove all abbr's for Cmdline mode
|:iabclear| :iabc[lear] remove all abbr's for Insert mode
------------------------------------------------------------------------------
*Q_op* Options
@ -940,18 +962,21 @@ Short explanation of each option: *option-list*
'writeany' 'wa' write to file with no need for "!" override
'writebackup' 'wb' make a backup before overwriting a file
'writedelay' 'wd' delay this many msec for each char (for debug)
------------------------------------------------------------------------------
*Q_ur* Undo/Redo commands
|u| N u undo last N changes
|CTRL-R| N CTRL-R redo last N undone changes
|U| U restore last changed line
------------------------------------------------------------------------------
*Q_et* External commands
|:!| :!{command} execute {command} with a shell
|K| K lookup keyword under the cursor with
'keywordprg' program (default: "man")
------------------------------------------------------------------------------
*Q_qf* Quickfix commands
@ -975,6 +1000,7 @@ Short explanation of each option: *option-list*
error
|:grep| :gr[ep] [args] execute 'grepprg' to find matches and jump to
the first one
------------------------------------------------------------------------------
*Q_vc* Various commands
@ -1000,6 +1026,7 @@ Short explanation of each option: *option-list*
unsaved changes or read-only files
|:browse| :browse {command} open/read/write file, using a
file selection dialog
------------------------------------------------------------------------------
*Q_ce* Command-line editing
@ -1046,6 +1073,7 @@ Context-sensitive completion on the command-line:
to next match
|c_CTRL-P| CTRL-P after 'wildchar' with multiple matches: go
to previous match
------------------------------------------------------------------------------
*Q_ra* Ex ranges
@ -1066,6 +1094,7 @@ Context-sensitive completion on the command-line:
(default: 1)
|:range| -[num] subtract [num] from the preceding line
number (default: 1)
------------------------------------------------------------------------------
*Q_ex* Special Ex characters
@ -1098,6 +1127,7 @@ Context-sensitive completion on the command-line:
|::r| :r root (extension removed)
|::e| :e extension
|::s| :s/{pat}/{repl}/ substitute {pat} with {repl}
------------------------------------------------------------------------------
*Q_st* Starting Vim
@ -1134,6 +1164,7 @@ Context-sensitive completion on the command-line:
|--help| --help show list of arguments and exit
|--version| --version show version info and exit
|--| - read file from stdin
------------------------------------------------------------------------------
*Q_ed* Editing a file
@ -1153,6 +1184,7 @@ Context-sensitive completion on the command-line:
position
|:file| :f[ile] {name} set the current file name to {name}
|:files| :files show alternate file names
------------------------------------------------------------------------------
*Q_fl* Using the argument list |argument-list|
@ -1173,6 +1205,7 @@ Context-sensitive completion on the command-line:
|:Next| :N[ext] :sN[ext] edit previous file
|:first| :fir[st] :sfir[st] edit first file
|:last| :la[st] :sla[st] edit last file
------------------------------------------------------------------------------
*Q_wq* Writing and quitting
@ -1210,6 +1243,7 @@ Context-sensitive completion on the command-line:
|:stop| :st[op][!] suspend Vim or start new shell; if 'aw' option
is set and [!] not given write the buffer
|CTRL-Z| CTRL-Z same as ":stop"
------------------------------------------------------------------------------
*Q_ac* Automatic Commands
@ -1241,6 +1275,7 @@ Context-sensitive completion on the command-line:
with {pat}
|:autocmd| :au! {event} {pat} {cmd} remove all autocommands for {event}
with {pat} and enter new one
------------------------------------------------------------------------------
*Q_wi* Multi-window commands
@ -1286,6 +1321,7 @@ Context-sensitive completion on the command-line:
|CTRL-W_>| CTRL-W > increase current window width
|CTRL-W_bar| CTRL-W | set current window width (default:
widest possible)
------------------------------------------------------------------------------
*Q_bu* Buffer list commands
@ -1307,6 +1343,7 @@ Context-sensitive completion on the command-line:
|:bfirst| :bfirst :sbfirst to first arg/buf
|:blast| :blast :sblast to last arg/buf
|:bmodified| :[N]bmod [N] :[N]sbmod [N] to Nth modified buf
------------------------------------------------------------------------------
*Q_sy* Syntax Highlighting
@ -1333,6 +1370,7 @@ Context-sensitive completion on the command-line:
|:filetype| :filetype plugin indent on
switch on file type detection, with
automatic indenting and settings
------------------------------------------------------------------------------
*Q_gu* GUI commands
@ -1345,6 +1383,7 @@ Context-sensitive completion on the command-line:
add toolbar item, giving {rhs}
|:tmenu| :tmenu {mpath} {text} add tooltip to menu {mpath}
|:unmenu| :unmenu {mpath} remove menu {mpath}
------------------------------------------------------------------------------
*Q_fo* Folding

View File

@ -23,40 +23,37 @@ screen grid with a size of width × height cells. This is typically done by an
embedder at startup (see |ui-startup|), but UIs can also connect to a running
Nvim instance and invoke nvim_ui_attach(). The `options` parameter is a map
with these (optional) keys:
*ui-rgb*
`rgb` Decides the color format.
true: (default) 24-bit RGB colors
false: Terminal colors (8-bit, max 256)
- `rgb` Decides the color format.
- true: (default) 24-bit RGB colors
- false: Terminal colors (8-bit, max 256)
*ui-override*
`override` Decides how UI capabilities are resolved.
true: Enable requested UI capabilities, even
if not supported by all connected UIs
(including |TUI|).
false: (default) Disable UI capabilities not
supported by all connected UIs
(including TUI).
- `override` Decides how UI capabilities are resolved.
- true: Enable requested UI capabilities, even if not
supported by all connected UIs (including |TUI|).
- false: (default) Disable UI capabilities not
supported by all connected UIs (including TUI).
*ui-ext-options*
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
`ext_hlstate` Detailed highlight state. |ui-hlstate|
Sets `ext_linegrid` implicitly.
`ext_linegrid` Line-based grid events. |ui-linegrid|
Deactivates |ui-grid-old| implicitly.
`ext_messages` Externalize messages. |ui-messages|
Sets `ext_linegrid` and `ext_cmdline` implicitly.
`ext_multigrid` Per-window grid events. |ui-multigrid|
Sets `ext_linegrid` implicitly.
`ext_popupmenu` Externalize |popupmenu-completion| and
'wildmenu'. |ui-popupmenu|
`ext_tabline` Externalize the tabline. |ui-tabline|
`ext_termcolors` Use external default colors.
`term_name` Sets the name of the terminal 'term'.
`term_colors` Sets the number of supported colors 't_Co'.
`term_background` Sets the default value of 'background'.
`stdin_fd` Read buffer from `fd` as if it was a stdin pipe
This option can only used by |--embed| ui,
see |ui-startup-stdin|.
- `ext_cmdline` Externalize the cmdline. |ui-cmdline|
- `ext_hlstate` Detailed highlight state. |ui-hlstate|
Sets `ext_linegrid` implicitly.
- `ext_linegrid` Line-based grid events. |ui-linegrid|
Deactivates |ui-grid-old| implicitly.
- `ext_messages` Externalize messages. |ui-messages|
Sets `ext_linegrid` and `ext_cmdline` implicitly.
- `ext_multigrid` Per-window grid events. |ui-multigrid|
Sets `ext_linegrid` implicitly.
- `ext_popupmenu` Externalize |popupmenu-completion| and
'wildmenu'. |ui-popupmenu|
- `ext_tabline` Externalize the tabline. |ui-tabline|
- `ext_termcolors` Use external default colors.
- `term_name` Sets the name of the terminal 'term'.
- `term_colors` Sets the number of supported colors 't_Co'.
- `term_background` Sets the default value of 'background'.
- `stdin_fd` Read buffer from `fd` as if it was a stdin pipe
This option can only used by |--embed| ui,
see |ui-startup-stdin|.
Specifying an unknown option is an error; UIs can check the |api-metadata|
`ui_options` key for supported options.
@ -164,13 +161,13 @@ Global Events *ui-global*
The following UI events are always emitted, and describe global state of
the editor.
["set_title", title]
["set_icon", icon]
["set_title", title] ~
["set_icon", icon] ~
Set the window title, and icon (minimized) window title, respectively.
In windowing systems not distinguishing between the two, "set_icon"
can be ignored.
["mode_info_set", cursor_style_enabled, mode_info]
["mode_info_set", cursor_style_enabled, mode_info] ~
`cursor_style_enabled` is a boolean indicating if the UI should set
the cursor style. `mode_info` is a list of mode property maps. The
current mode is given by the `mode_idx` field of the `mode_change`
@ -197,21 +194,21 @@ the editor.
`hl_id`: Use `attr_id` instead.
`hl_lm`: Use `attr_id_lm` instead.
["option_set", name, value]
["option_set", name, value] ~
UI-related option changed, where `name` is one of:
'arabicshape'
'ambiwidth'
'emoji'
'guifont'
'guifontwide'
'linespace'
'mousefocus'
'mousemoveevent'
'pumblend'
'showtabline'
'termguicolors'
"ext_*" (all |ui-ext-options|)
- 'arabicshape'
- 'ambiwidth'
- 'emoji'
- 'guifont'
- 'guifontwide'
- 'linespace'
- 'mousefocus'
- 'mousemoveevent'
- 'pumblend'
- 'showtabline'
- 'termguicolors'
- "ext_*" (all |ui-ext-options|)
Triggered when the UI first connects to Nvim, and whenever an option
is changed by the user or a plugin.
@ -224,7 +221,7 @@ the editor.
however a UI might still use such options when rendering raw text
sent from Nvim, like for |ui-cmdline|.
["mode_change", mode, mode_idx]
["mode_change", mode, mode_idx] ~
Editor mode changed. The `mode` parameter is a string representing
the current mode. `mode_idx` is an index into the array emitted in
the `mode_info_set` event. UIs should change the cursor style
@ -233,30 +230,30 @@ the editor.
instance more submodes and temporary states might be represented as
separate modes.
["mouse_on"]
["mouse_off"]
["mouse_on"] ~
["mouse_off"] ~
'mouse' was enabled/disabled in the current editor mode. Useful for
a terminal UI, or embedding into an application where Nvim mouse would
conflict with other usages of the mouse. Other UI:s may ignore this event.
["busy_start"]
["busy_stop"]
["busy_start"] ~
["busy_stop"] ~
Indicates to the UI that it must stop rendering the cursor. This event
is misnamed and does not actually have anything to do with busyness.
["suspend"]
["suspend"] ~
|:suspend| command or |CTRL-Z| mapping is used. A terminal client (or
another client where it makes sense) could suspend itself. Other
clients can safely ignore it.
["update_menu"]
["update_menu"] ~
The menu mappings changed.
["bell"]
["visual_bell"]
["bell"] ~
["visual_bell"] ~
Notify the user with an audible or visual bell, respectively.
["flush"]
["flush"] ~
Nvim is done redrawing the screen. For an implementation that renders
to an internal buffer, this is the time to display the redrawn parts
to the user.
@ -279,11 +276,11 @@ be created; to enable per-window grids, activate |ui-multigrid|.
Highlight attribute groups are predefined. UIs should maintain a table to map
numerical highlight ids to the actual attributes.
["grid_resize", grid, width, height]
["grid_resize", grid, width, height] ~
Resize a `grid`. If `grid` wasn't seen by the client before, a new grid is
being created with this size.
["default_colors_set", rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg]
["default_colors_set", rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg] ~
The first three arguments set the default foreground, background and
special colors respectively. `cterm_fg` and `cterm_bg` specifies the
default color codes to use in a 256-color terminal.
@ -300,7 +297,7 @@ numerical highlight ids to the actual attributes.
screen with changed background color itself.
*ui-event-hl_attr_define*
["hl_attr_define", id, rgb_attr, cterm_attr, info]
["hl_attr_define", id, rgb_attr, cterm_attr, info] ~
Add a highlight with `id` to the highlight table, with the
attributes specified by the `rgb_attr` and `cterm_attr` dicts, with the
following (all optional) keys.
@ -346,7 +343,7 @@ numerical highlight ids to the actual attributes.
`info` is an empty array by default, and will be used by the
|ui-hlstate| extension explained below.
["hl_group_set", name, hl_id]
["hl_group_set", name, hl_id] ~
The bulitin highlight group `name` was set to use the attributes `hl_id`
defined by a previous `hl_attr_define` call. This event is not needed
to render the grids which use attribute ids directly, but is useful
@ -355,7 +352,7 @@ numerical highlight ids to the actual attributes.
use the |hl-Pmenu| family of builtin highlights.
*ui-event-grid_line*
["grid_line", grid, row, col_start, cells]
["grid_line", grid, row, col_start, cells] ~
Redraw a continuous part of a `row` on a `grid`, starting at the column
`col_start`. `cells` is an array of arrays each with 1 to 3 items:
`[text(, hl_id, repeat)]` . `text` is the UTF-8 text that should be put in
@ -374,19 +371,19 @@ numerical highlight ids to the actual attributes.
enough to cover the remaining line, will be sent when the rest of the
line should be cleared.
["grid_clear", grid]
["grid_clear", grid] ~
Clear a `grid`.
["grid_destroy", grid]
["grid_destroy", grid] ~
`grid` will not be used anymore and the UI can free any data associated
with it.
["grid_cursor_goto", grid, row, column]
["grid_cursor_goto", grid, row, column] ~
Makes `grid` the current grid and `row, column` the cursor position on this
grid. This event will be sent at most once in a `redraw` batch and
indicates the visible cursor position.
["grid_scroll", grid, top, bot, left, right, rows, cols]
["grid_scroll", grid, top, bot, left, right, rows, cols] ~
Scroll a region of `grid`. This is semantically unrelated to editor
|scrolling|, rather this is an optimized way to say "copy these screen
cells".
@ -439,30 +436,30 @@ Grid Events (cell-based) *ui-grid-old*
This is the legacy representation of the screen grid, emitted if |ui-linegrid|
is not active. New UIs should implement |ui-linegrid| instead.
["resize", width, height]
["resize", width, height] ~
The grid is resized to `width` and `height` cells.
["clear"]
["clear"] ~
Clear the grid.
["eol_clear"]
["eol_clear"] ~
Clear from the cursor position to the end of the current line.
["cursor_goto", row, col]
["cursor_goto", row, col] ~
Move the cursor to position (row, col). Currently, the same cursor is
used to define the position for text insertion and the visible cursor.
However, only the last cursor position, after processing the entire
array in the "redraw" event, is intended to be a visible cursor
position.
["update_fg", color]
["update_bg", color]
["update_sp", color]
["update_fg", color] ~
["update_bg", color] ~
["update_sp", color] ~
Set the default foreground, background and special colors
respectively.
*ui-event-highlight_set*
["highlight_set", attrs]
["highlight_set", attrs] ~
Set the attributes that the next text put on the grid will have.
`attrs` is a dict with the keys below. Any absent key is reset
to its default value. Color defaults are set by the `update_fg` etc
@ -482,18 +479,18 @@ is not active. New UIs should implement |ui-linegrid| instead.
`underdotted`: underdotted text. The dots have `special` color.
`underdashed`: underdashed text. The dashes have `special` color.
["put", text]
["put", text] ~
The (utf-8 encoded) string `text` is put at the cursor position
(and the cursor is advanced), with the highlights as set by the
last `highlight_set` update.
["set_scroll_region", top, bot, left, right]
["set_scroll_region", top, bot, left, right] ~
Define the scroll region used by `scroll` below.
Note: ranges are end-inclusive, which is inconsistent with API
conventions.
["scroll", count]
["scroll", count] ~
Scroll the text in the scroll region. The diagrams below illustrate
what will happen, depending on the scroll direction. "=" is used to
represent the SR(scroll region) boundaries and "-" the moved rectangles.
@ -588,29 +585,29 @@ A window can be hidden and redisplayed without its grid being deallocated.
This can happen multiple times for the same window, for instance when switching
tabs.
["win_pos", grid, win, start_row, start_col, width, height]
["win_pos", grid, win, start_row, start_col, width, height] ~
Set the position and size of the grid in Nvim (i.e. the outer grid
size). If the window was previously hidden, it should now be shown
again.
["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable]
["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable] ~
Display or reconfigure floating window `win`. The window should be
displayed above another grid `anchor_grid` at the specified position
`anchor_row` and `anchor_col`. For the meaning of `anchor` and more
details of positioning, see |nvim_open_win()|.
["win_external_pos", grid, win]
["win_external_pos", grid, win] ~
Display or reconfigure external window `win`. The window should be
displayed as a separate top-level window in the desktop environment,
or something similar.
["win_hide", grid]
["win_hide", grid] ~
Stop displaying the window. The window can be shown again later.
["win_close", grid]
["win_close", grid] ~
Close the window.
["msg_set_pos", grid, row, scrolled, sep_char]
["msg_set_pos", grid, row, scrolled, sep_char] ~
Display messages on `grid`. The grid will be displayed at `row` on the
default grid (grid=1), covering the full column width. `scrolled`
indicates whether the message area has been scrolled to cover other
@ -621,13 +618,13 @@ tabs.
When |ui-messages| is active, no message grid is used, and this event
will not be sent.
["win_viewport", grid, win, topline, botline, curline, curcol]
["win_viewport", grid, win, topline, botline, curline, curcol] ~
Indicates the range of buffer text displayed in the window, as well
as the cursor position in the buffer. All positions are zero-based.
`botline` is set to one more than the line count of the buffer, if
there are filler lines past the end.
["win_extmark", grid, win, ns_id, mark_id, row, col]
["win_extmark", grid, win, ns_id, mark_id, row, col] ~
Updates the position of an extmark which is currently visible in a
window. Only emitted if the mark has the `ui_watched` attribute.
@ -639,7 +636,7 @@ Activated by the `ext_popupmenu` |ui-option|.
This UI extension delegates presentation of the |popupmenu-completion| and
command-line 'wildmenu'.
["popupmenu_show", items, selected, row, col, grid]
["popupmenu_show", items, selected, row, col, grid] ~
Show |popupmenu-completion|. `items` is an array of completion items
to show; each item is an array of the form [word, kind, menu, info] as
defined at |complete-items|, except that `word` is replaced by `abbr`
@ -651,12 +648,12 @@ command-line 'wildmenu'.
set to -1 to indicate the popupmenu should be anchored to the external
cmdline. Then `col` will be a byte position in the cmdline text.
["popupmenu_select", selected]
["popupmenu_select", selected] ~
Select an item in the current popupmenu. `selected` is a zero-based
index into the array of items from the last popupmenu_show event, or
-1 if no item is selected.
["popupmenu_hide"]
["popupmenu_hide"] ~
Hide the popupmenu.
==============================================================================
@ -664,7 +661,7 @@ Tabline Events *ui-tabline*
Activated by the `ext_tabline` |ui-option|.
["tabline_update", curtab, tabs, curbuf, buffers]
["tabline_update", curtab, tabs, curbuf, buffers] ~
Tabline was updated. UIs should present this data in a custom tabline
widget. Note: options `curbuf` + `buffers` were added in API7.
curtab: Current Tabpage
@ -680,7 +677,7 @@ Activated by the `ext_cmdline` |ui-option|.
This UI extension delegates presentation of the |cmdline| (except 'wildmenu').
For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
["cmdline_show", content, pos, firstc, prompt, indent, level]
["cmdline_show", content, pos, firstc, prompt, indent, level] ~
content: List of [attrs, string]
[[{}, "t"], [attrs, "est"], ...]
@ -703,10 +700,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
prompt has level 2. A command line invoked from the |cmdline-window|
has a higher level than than the edited command line.
["cmdline_pos", pos, level]
["cmdline_pos", pos, level] ~
Change the cursor position in the cmdline.
["cmdline_special_char", c, shift, level]
["cmdline_special_char", c, shift, level] ~
Display a special char in the cmdline at the cursor position. This is
typically used to indicate a pending state, e.g. after |c_CTRL-V|. If
`shift` is true the text after the cursor should be shifted, otherwise
@ -714,10 +711,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
Should be hidden at next cmdline_show.
["cmdline_hide"]
["cmdline_hide"] ~
Hide the cmdline.
["cmdline_block_show", lines]
["cmdline_block_show", lines] ~
Show a block of context to the current command line. For example if
the user defines a |:function| interactively: >
:function Foo()
@ -727,10 +724,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
`lines` is a list of lines of highlighted chunks, in the same form as
the "cmdline_show" `contents` parameter.
["cmdline_block_append", line]
["cmdline_block_append", line] ~
Append a line at the end of the currently shown block.
["cmdline_block_hide"]
["cmdline_block_hide"] ~
Hide the block.
==============================================================================
@ -747,7 +744,7 @@ Nvim will not allocate screen space for the cmdline or messages, and
'cmdheight' will be forced zero. Cmdline state is emitted as |ui-cmdline|
events, which the UI must handle.
["msg_show", kind, content, replace_last]
["msg_show", kind, content, replace_last] ~
Display a message to the user.
kind
@ -781,25 +778,25 @@ events, which the UI must handle.
true: Replace the message in the most-recent `msg_show` call,
but any other visible message should still remain.
["msg_clear"]
["msg_clear"] ~
Clear all messages currently displayed by "msg_show". (Messages sent
by other "msg_" events below will not be affected).
["msg_showmode", content]
["msg_showmode", content] ~
Shows 'showmode' and |recording| messages. `content` has the same
format as in "msg_show". This event is sent with empty `content` to
hide the last message.
["msg_showcmd", content]
["msg_showcmd", content] ~
Shows 'showcmd' messages. `content` has the same format as in "msg_show".
This event is sent with empty `content` to hide the last message.
["msg_ruler", content]
["msg_ruler", content] ~
Used to display 'ruler' when there is no space for the ruler in a
statusline. `content` has the same format as in "msg_show". This event is
sent with empty `content` to hide the last message.
["msg_history_show", entries]
["msg_history_show", entries] ~
Sent when |:messages| command is invoked. History is sent as a list of
entries, where each entry is a `[kind, content]` tuple.

View File

@ -907,8 +907,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
return
end
--The active signature. If omitted or the value lies outside the range of
--`signatures` the value defaults to zero or is ignored if `signatures.length
--=== 0`. Whenever possible implementors should make an active decision about
--`signatures` the value defaults to zero or is ignored if `signatures.length == 0`.
--Whenever possible implementors should make an active decision about
--the active signature and shouldn't rely on a default value.
local contents = {}
local active_hl

View File

@ -1,5 +1,7 @@
-- Converts Vim :help files to HTML. Validates |tag| links and document syntax (parser errors).
--
-- NOTE: :helptags checks for duplicate tags, whereas this script checks _links_ (to tags).
--
-- USAGE (GENERATE HTML):
-- 1. Run `make helptags` first; this script depends on vim.fn.taglist().
-- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./build/runtime/doc/', 'target/dir/')"
@ -20,37 +22,19 @@
-- * visit_node() is the core function used by gen() to traverse the document tree and produce HTML.
-- * visit_validate() is the core function used by validate().
-- * Files in `new_layout` will be generated with a "flow" layout instead of preformatted/fixed-width layout.
--
-- parser bugs:
-- * Should NOT be code_block:
-- tab:xy The 'x' is always used, then 'y' as many times as will
-- fit. Thus "tab:>-" displays:
-- >
-- >-
-- >--
-- etc.
--
-- tab:xyz The 'z' is always used, then 'x' is prepended, and
-- then 'y' is used as many times as will fit. Thus
-- "tab:<->" displays:
-- >
-- <>
-- <->
-- <-->
-- etc.
-- * Should NOT be a "headline". Perhaps a "table" (or just "line").
-- expr5 and expr6 *expr5* *expr6*
-- ---------------
-- expr6 + expr6 Number addition, |List| or |Blob| concatenation *expr-+*
-- expr6 - expr6 Number subtraction *expr--*
-- expr6 . expr6 String concatenation *expr-.*
-- expr6 .. expr6 String concatenation *expr-..*
local tagmap = nil
local helpfiles = nil
local invalid_tags = {}
local invalid_links = {}
local invalid_urls = {}
local invalid_spelling = {}
local spell_dict = {
Neovim = 'Nvim',
NeoVim = 'Nvim',
neovim = 'Nvim',
lua = 'Lua',
}
local api = vim.api
local M = {}
-- These files are generated with "flow" layout (non fixed-width, wrapped text paragraphs).
@ -59,16 +43,31 @@ local new_layout = {
['api.txt'] = true,
['channel.txt'] = true,
['develop.txt'] = true,
['luaref.txt'] = true,
['nvim.txt'] = true,
['pi_health.txt'] = true,
['provider.txt'] = true,
['ui.txt'] = true,
}
-- TODO: treesitter gets stuck on these files...
local exclude = {
['filetype.txt'] = true,
['usr_24.txt'] = true,
-- TODO: These known invalid |links| require an update to the relevant docs.
local exclude_invalid = {
["'previewpopup'"] = "quickref.txt",
["'pvp'"] = "quickref.txt",
["'string'"] = "eval.txt",
Query = "treesitter.txt",
["eq?"] = "treesitter.txt",
["lsp-request"] = "lsp.txt",
matchit = "vim_diff.txt",
["matchit.txt"] = "help.txt",
["set!"] = "treesitter.txt",
["v:_null_blob"] = "builtin.txt",
["v:_null_dict"] = "builtin.txt",
["v:_null_list"] = "builtin.txt",
["v:_null_string"] = "builtin.txt",
["vim.lsp.buf_request()"] = "lsp.txt",
["vim.lsp.util.get_progress_messages()"] = "lsp.txt",
["vim.treesitter.start()"] = "treesitter.txt"
}
local function tofile(fname, text)
@ -82,10 +81,6 @@ local function tofile(fname, text)
end
local function html_esc(s)
if s:find('<a class="parse%-error"') then
-- HACK: don't escape HTML that we generated (for a parsing error).
return s
end
return s:gsub(
'&', '&amp;'):gsub(
'<', '&lt;'):gsub(
@ -139,31 +134,35 @@ local function trim_bullet(s)
return s:gsub('^%s*[-*•]%s', '')
end
local function startswith_bullet(s)
return s:find('^%s*[-*•]%s')
end
-- Checks if a given line is a "noise" line that doesn't look good in HTML form.
local function is_noise(line)
return (
line:find('Type .*gO.* to see the table of contents')
-- Title line of traditional :help pages.
-- Example: "NVIM REFERENCE MANUAL by ..."
or line:find('^%s*N?VIM REFERENCE MANUAL')
-- First line of traditional :help pages.
-- Example: "*api.txt* Nvim"
or line:find('%s*%*?[a-zA-Z]+%.txt%*?%s+N?[vV]im%s*$')
-- modeline
-- Example: "vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:"
or line:find('^%s*vi[m]%:.*ft=help')
or line:find('^%s*vi[m]%:.*filetype=help')
)
local function is_noise(line, noise_lines)
if (
-- First line is always noise.
(noise_lines ~= nil and vim.tbl_count(noise_lines) == 0)
or line:find('Type .*gO.* to see the table of contents')
-- Title line of traditional :help pages.
-- Example: "NVIM REFERENCE MANUAL by ..."
or line:find([[^%s*N?VIM[ \t]*REFERENCE[ \t]*MANUAL]])
-- First line of traditional :help pages.
-- Example: "*api.txt* Nvim"
or line:find('%s*%*?[a-zA-Z]+%.txt%*?%s+N?[vV]im%s*$')
-- modeline
-- Example: "vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:"
or line:find('^%s*vi[m]%:.*ft=help')
or line:find('^%s*vi[m]%:.*filetype=help')
or line:find('[*>]local%-additions[*<]')
) then
-- table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0))
table.insert(noise_lines or {}, line)
return true
end
return false
end
-- Creates a github issue URL at vigoux/tree-sitter-vimdoc with prefilled content.
-- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content.
local function get_bug_url_vimdoc(fname, to_fname, sample_text)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
local bug_url = ('https://github.com/vigoux/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
..vim.fs.basename(fname)
..'+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+'
..this_url
@ -237,24 +236,46 @@ 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
local function get_tagname(node, bufnr)
local node_text = vim.treesitter.get_node_text(node, bufnr)
local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink') and ("'%s'"):format(node_text) or node_text
local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt"
local helppage = get_helppage(helpfile) -- "api.html"
return helppage, tag
end
local function get_tagname(node, bufnr, link)
local node_name = (node.named and node:named()) and node:type() or nil
local node_text = vim.treesitter.get_node_text(node, bufnr)
local tag = ((node_name == 'option' and node_text)
or (link and node_text:gsub('^|', ''):gsub('|$', '') or node_text:gsub('^%*', ''):gsub('%*$', '')))
local helpfile = tag and vim.fs.basename(tagmap[tag]) or nil -- "api.txt"
local helppage = get_helppage(helpfile) -- "api.html"
return helppage, tag
-- Returns true if the given invalid tagname is a false positive.
local function ignore_invalid(s)
-- Strings like |~/====| appear in various places and the parser thinks they are links, but they
-- are just table borders.
return not not (s:find('===') or exclude_invalid[s])
end
local function ignore_parse_error(s)
-- Ignore parse errors for unclosed codespan/optionlink/tag.
-- This is common in vimdocs and is treated as plaintext by :help.
return s:find("^[`'|*]")
end
local function has_ancestor(node, ancestor_name)
local p = node
while true do
p = p:parent()
if not p or p:type() == 'help_file' then
break
elseif p:type() == ancestor_name then
return true
end
end
return false
end
local function validate_link(node, bufnr, fname)
local helppage, tagname = get_tagname(node:child(1), bufnr, true)
if not has_ancestor(node, 'column_heading') and not node:has_error() and not tagmap[tagname] and not ignore_invalid(tagname) then
invalid_links[tagname] = vim.fs.basename(fname)
end
return helppage, tagname
end
-- Traverses the tree at `root` and checks that |tag| links point to valid helptags.
@ -262,6 +283,10 @@ local function visit_validate(root, level, lang_tree, opt, stats)
level = level or 0
local node_name = (root.named and root:named()) and root:type() or nil
local toplevel = level < 1
local function node_text(node)
return vim.treesitter.get_node_text(node or root, opt.buf)
end
local text = trim(node_text())
if root:child_count() > 0 then
for node, _ in root:iter_children() do
@ -272,14 +297,26 @@ local function visit_validate(root, level, lang_tree, opt, stats)
end
if node_name == 'ERROR' then
if ignore_parse_error(text) then
return
end
-- Store the raw text to give context to the bug report.
local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]'
table.insert(stats.parse_errors, sample_text)
elseif node_name == 'hotlink' or node_name == 'option' then
local _, tagname = get_tagname(root, opt.buf, true)
if not root:has_error() and not tagmap[tagname] then
invalid_tags[tagname] = vim.fs.basename(opt.fname)
elseif node_name == 'word' or node_name == 'uppercase_name' then
if spell_dict[text] then
if not invalid_spelling[text] then
invalid_spelling[text] = { vim.fs.basename(opt.fname) }
else
table.insert(invalid_spelling[text], vim.fs.basename(opt.fname))
end
end
elseif node_name == 'url' then
if text:find('http%:') then
invalid_urls[text] = vim.fs.basename(opt.fname)
end
elseif node_name == 'taglink' or node_name == 'optionlink' then
local _, _ = validate_link(root, opt.buf, opt.fname)
end
end
@ -296,19 +333,18 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local parent = root:parent() and root:parent():type() or nil
local text = ''
local toplevel = level < 1
local function node_text()
return vim.treesitter.get_node_text(root, opt.buf)
local function node_text(node)
return vim.treesitter.get_node_text(node or root, opt.buf)
end
if root:child_count() == 0 then
if root:child_count() == 0 or node_name == 'ERROR' then
text = node_text()
else
-- Process children and join them with whitespace.
for node, _ in root:iter_children() do
if node:named() then
local r = visit_node(node, level + 1, lang_tree, headings, opt, stats)
local ws = r == '' and '' or ((opt.old and (node:type() == 'word' or not node:named())) and getws(node, opt.buf) or ' ')
text = string.format('%s%s%s', text, ws, r)
text = string.format('%s%s', text, r)
end
end
end
@ -316,82 +352,112 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
if node_name == 'help_file' then -- root node
return text
elseif node_name == 'url' then
return ('<a href="%s">%s</a>'):format(trimmed, trimmed)
elseif node_name == 'word' or node_name == 'uppercase_name' then
if parent == 'headline' then
-- Start a new heading item, or update the current one.
local n = (prev == nil or #headings == 0) and #headings + 1 or #headings
headings[n] = string.format('%s%s', headings[n] and headings[n]..' ' or '', text)
end
return html_esc(text)
elseif node_name == 'headline' then
return ('<a name="%s"></a><h2 class="help-heading">%s</h2>\n'):format(to_heading_tag(headings[#headings]), text)
elseif node_name == 'h1' or node_name == 'h2' or node_name == 'h3' then
if is_noise(text, stats.noise_lines) then
return '' -- Discard common "noise" lines.
end
-- Remove "===" and tags from ToC text.
local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', ''))
if node_name == 'h1' or #headings == 0 then
table.insert(headings, { name = hname, subheadings = {}, })
else
table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, })
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)
elseif node_name == 'column_heading' or node_name == 'column_name' then
return ('<h4>%s</h4>\n'):format(trimmed)
elseif node_name == 'line' then
-- TODO: remove these "sibling inspection" hacks once the parser provides structured info
-- about paragraphs and listitems: https://github.com/vigoux/tree-sitter-vimdoc/issues/12
local next_text = root:next_sibling() and vim.treesitter.get_node_text(root:next_sibling(), opt.buf) or ''
local li = startswith_bullet(text) -- Listitem?
local next_li = startswith_bullet(next_text) -- Next is listitem?
-- Close the paragraph/listitem if the next sibling is not a line.
local close = (next_ ~= 'line' or next_li or is_blank(next_text)) and '</div>\n' or ''
-- HACK: discard common "noise" lines.
if is_noise(text) then
table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0))
return (opt.old or prev ~= 'line') and '' or close
if root:has_error() then
return text
end
return ('<div class="help-column_heading">%s</div>'):format(trimmed)
elseif node_name == 'block' then
if is_blank(text) then
return ''
end
if opt.old then
-- XXX: Treat old docs as preformatted. Until those docs are "fixed" or we get better info
-- from tree-sitter-vimdoc, this avoids broken layout for legacy docs.
return ('<div class="old-help-line">%s</div>\n'):format(text)
-- XXX: Treat old docs as preformatted; random indentation is used for layout there.
return ('<div class="old-help-para">%s</div>\n'):format(text)
end
return string.format('<div class="help-para">\n%s\n</div>\n', text)
elseif node_name == 'line' then
local sib = root:prev_sibling()
local sib_last = sib and sib:named_child(sib:named_child_count() - 1)
local in_li = false
-- XXX: parser bug: (codeblock) without terminating "<" consumes first char of the next (line). Recover it here.
local recovered = (sib_last and sib_last:type() == 'codeblock') and node_text(root:prev_sibling()):sub(-1) or ''
recovered = recovered == '<' and '' or html_esc(recovered)
-- XXX: see if we are currently "in" a listitem.
while sib ~= nil and not in_li do
in_li = (sib:type() == 'line_li')
sib = sib:prev_sibling()
end
if li then
return string.format('<div class="help-item">%s%s', trim_bullet(expandtabs(text)), close)
end
if prev ~= 'line' then -- Start a new paragraph.
return string.format('<div class="help-para">%s%s', expandtabs(text), close)
-- Close the current listitem.
local close = (in_li and next_ ~= 'line') and '</div>' or ''
if is_blank(text) or is_noise(text, stats.noise_lines) then
return close -- Discard common "noise" lines.
end
-- Continue in the current paragraph/listitem.
return string.format('%s%s', expandtabs(text), close)
elseif node_name == 'hotlink' or node_name == 'option' then
local helppage, tagname = get_tagname(root, opt.buf, true)
if not root:has_error() and not tagmap[tagname] then
invalid_tags[tagname] = vim.fs.basename(opt.fname)
local div = (root:child(0) and root:child(0):type() == 'column_heading') or close ~= ''
return string.format('%s%s%s%s', recovered, div and trim(text) or text, div and '' or '\n', close)
elseif node_name == 'line_li' then
-- Close the listitem immediately if the next sibling is not a line.
local close = (next_ ~= 'line') and '</div>' or ''
return string.format('<div class="help-li">%s %s', trim_bullet(text), close)
elseif node_name == 'taglink' or node_name == 'optionlink' then
if root:has_error() then
return text
end
return ('<a href="%s#%s">%s</a>'):format(helppage, url_encode(tagname), html_esc(tagname))
elseif node_name == 'backtick' then
return ('<code>%s</code>'):format(html_esc(text))
local helppage, tagname = validate_link(root, opt.buf, opt.fname)
return (' <a href="%s#%s">%s</a>'):format(helppage, url_encode(tagname), html_esc(tagname))
elseif node_name == 'codespan' then
if root:has_error() then
return text
end
return (' <code>%s</code>'):format(text)
elseif node_name == 'argument' then
return ('<code>{%s}</code>'):format(html_esc(trimmed))
elseif node_name == 'code_block' then
return ('<pre>\n%s</pre>\n'):format(html_esc(trim_indent(trim_gt_lt(text))))
return (' <code>{%s}</code>'):format(trimmed)
elseif node_name == 'codeblock' then
return ('<pre>%s</pre>'):format(html_esc(trim_indent(trim_gt_lt(text))))
elseif node_name == 'tag' then -- anchor
local _, tagname = get_tagname(root, opt.buf, false)
local s = ('<a name="%s"></a><span class="help-tag">%s</span>'):format(url_encode(tagname), trimmed)
if parent == 'headline' and prev ~= 'tag' then
if root:has_error() then
return text
end
local in_heading = (parent == 'h1' or parent == 'h2')
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))
if vim.tbl_count(stats.first_tags) < 2 then
-- First 2 tags in the doc will be anchored at the main heading.
table.insert(stats.first_tags, tagname)
return ''
end
local s = (' <a name="%s"></a><span class="%s">%s</span>'):format(url_encode(tagname), cssclass, trimmed)
if in_heading and prev ~= 'tag' then
-- Start the <span> container for tags in a heading.
-- This makes "justify-content:space-between" right-align the tags.
-- <h2>foo bar<span>tag1 tag2</span></h2>
return string.format('<span class="help-heading-tags">%s', s)
elseif parent == 'headline' and next_ == nil then
elseif in_heading and next_ == nil then
-- End the <span> container for tags in a heading.
return string.format('%s</span>', s)
end
return s
elseif node_name == 'ERROR' then
if ignore_parse_error(trimmed) then
return text
end
-- Store the raw text to give context to the bug report.
local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]'
table.insert(stats.parse_errors, sample_text)
if prev == 'ERROR' then
-- Avoid trashing the text with cascading errors.
return trimmed, ('parse-error:"%s"'):format(node_text())
end
return ('<a class="parse-error" target="_blank" title="Parsing error. Report to tree-sitter-vimdoc..." href="%s">%s</a>'):format(
return ('<a class="parse-error" target="_blank" title="Parse error. Report to tree-sitter-vimdoc..." href="%s">%s</a>'):format(
get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text), trimmed)
else -- Unknown token.
local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]'
@ -406,8 +472,7 @@ local function get_helpfiles(include)
for f, type in vim.fs.dir(dir) do
if (vim.endswith(f, '.txt')
and type == 'file'
and (not include or vim.tbl_contains(include, f))
and (not exclude[f])) then
and (not include or vim.tbl_contains(include, f))) then
local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p')
table.insert(rv, fullpath)
end
@ -430,6 +495,13 @@ local function get_helptags(help_dir)
return m
end
-- Use the help.so parser defined in the build, not whatever happens to be installed on the system.
local function ensure_runtimepath()
if not vim.o.runtimepath:find('build/lib/nvim/') then
vim.cmd[[set runtimepath^=./build/lib/nvim/]]
end
end
-- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents.
--
-- @returns lang_tree, bufnr
@ -437,7 +509,7 @@ local function parse_buf(fname)
local buf
if type(fname) == 'string' then
vim.cmd('split '..vim.fn.fnameescape(fname)) -- Filename.
buf = api.nvim_get_current_buf()
buf = vim.api.nvim_get_current_buf()
else
buf = fname
vim.cmd('sbuffer '..tostring(fname)) -- Buffer number.
@ -451,10 +523,9 @@ end
-- - checks that |tag| links point to valid helptags.
-- - recursively counts parse errors ("ERROR" nodes)
--
-- @returns { invalid_tags: number, parse_errors: number }
-- @returns { invalid_links: number, parse_errors: number }
local function validate_one(fname)
local stats = {
invalid_tags = {},
parse_errors = {},
}
local lang_tree, buf = parse_buf(fname)
@ -463,10 +534,7 @@ local function validate_one(fname)
end
lang_tree:destroy()
vim.cmd.close()
return {
invalid_tags = invalid_tags,
parse_errors = stats.parse_errors,
}
return stats
end
-- Generates HTML from one :help file `fname` and writes the result to `to_fname`.
@ -480,9 +548,10 @@ local function gen_one(fname, to_fname, old, commit)
local stats = {
noise_lines = {},
parse_errors = {},
first_tags = {}, -- Track the first few tags in doc.
}
local lang_tree, buf = parse_buf(fname)
local headings = {} -- Headings (for ToC).
local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3.
local title = to_titlecase(basename_noext(fname))
local html = ([[
@ -555,7 +624,12 @@ local function gen_one(fname, to_fname, old, commit)
</svg>
]]
local main = ([[
local main = ''
for _, tree in ipairs(lang_tree:trees()) do
main = main .. (visit_node(tree:root(), 0, tree, headings, { buf = buf, old = old, fname = fname, to_fname = to_fname }, stats))
end
main = ([[
<header class="container">
<nav class="navbar navbar-expand-lg">
<div>
@ -570,29 +644,37 @@ local function gen_one(fname, to_fname, old, commit)
<div class="container golden-grid help-body">
<div class="col-wide">
<h1>%s</h1>
<a name="%s"></a><a name="%s"></a><h1>%s</h1>
<p>
<i>
Nvim help pages, updated <a href="https://github.com/neovim/neovim/blob/master/scripts/gen_help_html.lua">automatically</a>
from <a href="https://github.com/neovim/neovim/blob/master/runtime/doc/%s">source</a>.
Parsing by <a href="https://github.com/vigoux/tree-sitter-vimdoc">tree-sitter-vimdoc</a>.
Nvim <code>:help</code> pages, <a href="https://github.com/neovim/neovim/blob/master/scripts/gen_help_html.lua">generated</a>
from <a href="https://github.com/neovim/neovim/blob/master/runtime/doc/%s">source</a>
using the <a href="https://github.com/neovim/tree-sitter-vimdoc">tree-sitter-vimdoc</a> parser.
</i>
</p>
]]):format(logo_svg, title, vim.fs.basename(fname))
for _, tree in ipairs(lang_tree:trees()) do
main = main .. (visit_node(tree:root(), 0, tree, headings, { buf = buf, old = old, fname = fname, to_fname = to_fname }, stats))
end
main = main .. '</div>\n'
<hr/>
%s
</div>
]]):format(logo_svg, stats.first_tags[1] or '', stats.first_tags[2] or '', title, vim.fs.basename(fname), main)
local toc = [[
<div class="col-narrow toc">
<div><a href="index.html">Main</a></div>
<div><a href="vimindex.html">Help index</a></div>
<div><a href="vimindex.html">Commands index</a></div>
<div><a href="quickref.html">Quick reference</a></div>
<hr/>
]]
for _, heading in ipairs(headings) do
toc = toc .. ('<div><a href="#%s">%s</a></div>\n'):format(to_heading_tag(heading), heading)
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)
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)
end
end
toc = toc .. '</div>'
end
toc = toc .. '</div>\n'
@ -623,12 +705,21 @@ end
local function gen_css(fname)
local css = [[
:root {
--code-color: #008B8B;
--tag-color: gray;
}
@media (min-width: 40em) {
.toc {
position: fixed;
left: 67%;
}
}
@media (prefers-color-scheme: dark) {
:root {
--code-color: cyan;
}
}
.toc {
/* max-width: 12rem; */
}
@ -640,8 +731,19 @@ local function gen_css(fname)
html {
scroll-behavior: auto;
}
h1, h2, h3, h4 {
body {
font-size: 18px;
line-height: 1.5;
}
h1, h2, h3, h4, h5 {
font-family: sans-serif;
border-bottom: 1px solid gray;
}
h3, h4, h5 {
border-bottom-style: dashed;
}
.help-column_heading {
color: var(--code-color);
}
.help-body {
padding-bottom: 2em;
@ -649,7 +751,8 @@ local function gen_css(fname)
.help-line {
/* font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; */
}
.help-item {
.help-li {
white-space: normal;
display: list-item;
margin-left: 1.5rem; /* padding-left: 1rem; */
}
@ -657,11 +760,13 @@ local function gen_css(fname)
padding-top: 10px;
padding-bottom: 10px;
}
.old-help-line {
.old-help-para {
padding-top: 10px;
padding-bottom: 10px;
/* Tabs are used for alignment in old docs, so we must match Vim's 8-char expectation. */
tab-size: 8;
white-space: pre;
font-size: .875em;
font-size: 16px;
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
}
a.help-tag, a.help-tag:focus, a.help-tag:hover {
@ -669,7 +774,13 @@ local function gen_css(fname)
text-decoration: none;
}
.help-tag {
color: gray;
color: var(--tag-color);
}
/* Tag pseudo-header common in :help docs. */
.help-tag-right {
color: var(--tag-color);
display: block;
text-align: right;
}
h1 .help-tag, h2 .help-tag {
font-size: smaller;
@ -682,7 +793,12 @@ local function gen_css(fname)
}
/* The (right-aligned) "tags" part of a section heading. */
.help-heading-tags {
margin-left: 10px;
margin-right: 10px;
}
.help-toc-h1 {
}
.help-toc-h2 {
margin-left: 1em;
}
.parse-error {
background-color: red;
@ -691,15 +807,19 @@ local function gen_css(fname)
color: black;
background-color: yellow;
}
code {
color: var(--code-color);
font-size: 16px;
}
pre {
/* Tabs are used in code_blocks only for indentation, not alignment, so we can aggressively shrink them. */
/* Tabs are used in codeblocks only for indentation, not alignment, so we can aggressively shrink them. */
tab-size: 2;
white-space: pre;
line-height: 1.1; /* Important for ascii art. */
overflow: visible;
/* font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; */
/* font-size: 14px; */
/* border: 0px; */
/* margin: 0px; */
font-size: 16px;
margin-top: 10px;
}
pre:hover,
.help-heading:hover {
@ -734,12 +854,11 @@ function M._test()
return ok(expected == actual, expected, actual)
end
eq(119, #helpfiles)
ok(vim.tbl_count(tagmap) > 3000, '>3000', vim.tbl_count(tagmap))
ok(vim.endswith(tagmap['vim.diagnostic.set()'], 'diagnostic.txt'), tagmap['vim.diagnostic.set()'], 'diagnostic.txt')
ok(vim.endswith(tagmap['%:s'], 'cmdline.txt'), tagmap['%:s'], 'cmdline.txt')
ok(is_noise([[vim:tw=78:isk=!-~,^*,^\|,^\":ts=8:noet:ft=help:norl:]]))
ok(is_noise([[ VIM REFERENCE MANUAL by Abe Lincoln ]]))
ok(is_noise([[ NVIM REFERENCE MANUAL by Thiago de Arruda ]]))
ok(not is_noise([[vim:tw=78]]))
eq(0, get_indent('a'))
@ -771,6 +890,7 @@ function M.gen(help_dir, to_dir, include, commit)
}
local err_count = 0
ensure_runtimepath()
tagmap = get_helptags(help_dir)
helpfiles = get_helpfiles(include)
@ -788,12 +908,12 @@ function M.gen(help_dir, to_dir, include, commit)
end
print(('generated %d html pages'):format(#helpfiles))
print(('total errors: %d'):format(err_count))
print(('invalid tags:\n%s'):format(vim.inspect(invalid_tags)))
print(('invalid tags:\n%s'):format(vim.inspect(invalid_links)))
return {
helpfiles = helpfiles,
err_count = err_count,
invalid_tags = invalid_tags,
invalid_links = invalid_links,
}
end
@ -810,6 +930,7 @@ function M.validate(help_dir, include)
include={include, 't', true},
}
local err_count = 0
ensure_runtimepath()
tagmap = get_helptags(help_dir)
helpfiles = get_helpfiles(include)
@ -821,9 +942,11 @@ function M.validate(help_dir, include)
end
return {
helpfiles = helpfiles,
helpfiles = #helpfiles,
err_count = err_count,
invalid_tags = invalid_tags,
invalid_links = invalid_links,
invalid_urls = invalid_urls,
invalid_spelling = invalid_spelling,
}
end

View File

@ -354,7 +354,9 @@ describe('startup', function()
local function pack_clear(cmd)
-- add packages after config dir in rtp but before config/after
clear{args={'--cmd', 'set packpath=test/functional/fixtures', '--cmd', 'let paths=split(&rtp, ",")', '--cmd', 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")', '--cmd', cmd}, env={XDG_CONFIG_HOME='test/functional/fixtures/'}}
clear{args={'--cmd', 'set packpath=test/functional/fixtures', '--cmd', 'let paths=split(&rtp, ",")', '--cmd', 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")', '--cmd', cmd}, env={XDG_CONFIG_HOME='test/functional/fixtures/'},
args_rm={'runtimepath'},
}
end

View File

@ -29,6 +29,7 @@ local module = {
}
local start_dir = lfs.currentdir()
local runtime_set = 'set runtimepath^=./build/lib/nvim/'
module.nvim_prog = (
os.getenv('NVIM_PRG')
or global_helpers.test_build_dir .. '/bin/nvim'
@ -40,6 +41,8 @@ module.nvim_set = (
..' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid')
module.nvim_argv = {
module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
-- XXX: find treesitter parsers.
'--cmd', runtime_set,
'--cmd', module.nvim_set,
'--cmd', 'mapclear',
'--cmd', 'mapclear!',
@ -345,14 +348,17 @@ end
-- Removes Nvim startup args from `args` matching items in `args_rm`.
--
-- "-u", "-i", "--cmd" are treated specially: their "values" are also removed.
-- - Special case: "-u", "-i", "--cmd" are treated specially: their "values" are also removed.
-- - Special case: "runtimepath" will remove only { '--cmd', 'set runtimepath^=…', }
--
-- Example:
-- args={'--headless', '-u', 'NONE'}
-- args_rm={'--cmd', '-u'}
-- Result:
-- {'--headless'}
--
-- All cases are removed.
-- All matching cases are removed.
--
-- Example:
-- args={'--cmd', 'foo', '-N', '--cmd', 'bar'}
-- args_rm={'--cmd', '-u'}
@ -373,6 +379,9 @@ local function remove_args(args, args_rm)
last = ''
elseif tbl_contains(args_rm, arg) then
last = arg
elseif arg == runtime_set and tbl_contains(args_rm, 'runtimepath') then
table.remove(new_args) -- Remove the preceding "--cmd".
last = ''
else
table.insert(new_args, arg)
end

View File

@ -12,29 +12,26 @@ describe(':help docs', function()
before_each(clear)
it('validate', function()
-- If this test fails, try these steps (in order):
-- 1. Try to fix/cleanup the :help docs, especially Nvim-owned :help docs.
-- 2. Try to fix the parser: https://github.com/vigoux/tree-sitter-vimdoc
-- 1. Fix/cleanup the :help docs.
-- 2. Fix the parser: https://github.com/neovim/tree-sitter-vimdoc
-- 3. File a parser bug, and adjust the tolerance of this test in the meantime.
local rv = exec_lua([[return require('scripts.gen_help_html').validate('./build/runtime/doc')]])
-- Check that we actually found helpfiles.
ok(rv.helpfiles > 100, '>100 :help files', rv.helpfiles)
-- Check that parse errors did not increase wildly.
-- TODO: yes, there are currently 24k+ parser errors.
-- WIP: https://github.com/vigoux/tree-sitter-vimdoc/pull/16
ok(rv.err_count < 24000, '<24000', rv.err_count)
-- TODO: should be eq(0, …)
ok(exec_lua('return vim.tbl_count(...)', rv.invalid_tags) < 538, '<538',
exec_lua('return vim.inspect(...)', rv.invalid_tags))
-- TODO: Fix all parse errors in :help files.
ok(rv.err_count < 1300, '<1300 parse errors', rv.err_count)
eq({}, rv.invalid_links, exec_lua([[return 'found invalid :help tag links:\n'..vim.inspect(...)]], rv.invalid_links))
end)
it('gen_help_html.lua generates HTML', function()
-- Test:
-- 1. Check that parse errors did not increase wildly. Because we explicitly test only a few
-- :help files, we can be more precise about the tolerances here.
-- 2. exercise gen_help_html.lua, check that it actually works.
-- 3. check that its tree-sitter-vimdoc dependency is working.
-- 1. Test that gen_help_html.lua actually works.
-- 2. Test that parse errors did not increase wildly. Because we explicitly test only a few
-- :help files, we can be precise about the tolerances here.
local tmpdir = exec_lua('return vim.fs.dirname(vim.fn.tempname())')
-- Because gen() is slow (1 min), this test is limited to a few files.
-- Because gen() is slow (~30s), this test is limited to a few files.
local rv = exec_lua([[
local to_dir = ...
return require('scripts.gen_help_html').gen(
@ -46,9 +43,7 @@ describe(':help docs', function()
tmpdir
)
eq(4, #rv.helpfiles)
ok(rv.err_count < 700, '<700', rv.err_count)
-- TODO: should be eq(0, …)
ok(exec_lua('return vim.tbl_count(...)', rv.invalid_tags) <= 32, '<=32',
exec_lua('return vim.inspect(...)', rv.invalid_tags))
ok(rv.err_count < 16, '<16 parse errors', rv.err_count)
eq({}, rv.invalid_links, exec_lua([[return 'found invalid :help tag links:\n'..vim.inspect(...)]], rv.invalid_links))
end)
end)

View File

@ -220,7 +220,9 @@ describe('startup defaults', function()
end)
it("'packpath'", function()
clear()
clear{
args_rm={'runtimepath'},
}
-- Defaults to &runtimepath.
eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
@ -332,17 +334,19 @@ describe('XDG defaults', function()
describe('with too long XDG variables', function()
before_each(function()
clear({env={
XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)),
XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048)
.. env_sep.. root_path .. ('/b'):rep(2048)
.. (env_sep .. root_path .. '/c'):rep(512)),
XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
XDG_RUNTIME_DIR=(root_path .. ('/X'):rep(4096)),
XDG_STATE_HOME=(root_path .. ('/X'):rep(4096)),
XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
.. env_sep .. root_path .. ('/B'):rep(2048)
.. (env_sep .. root_path .. '/C'):rep(512)),
clear({
args_rm={'runtimepath'},
env={
XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)),
XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048)
.. env_sep.. root_path .. ('/b'):rep(2048)
.. (env_sep .. root_path .. '/c'):rep(512)),
XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
XDG_RUNTIME_DIR=(root_path .. ('/X'):rep(4096)),
XDG_STATE_HOME=(root_path .. ('/X'):rep(4096)),
XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
.. env_sep .. root_path .. ('/B'):rep(2048)
.. (env_sep .. root_path .. '/C'):rep(512)),
}})
end)
@ -405,13 +409,15 @@ describe('XDG defaults', function()
describe('with XDG variables that can be expanded', function()
before_each(function()
clear({env={
XDG_CONFIG_HOME='$XDG_DATA_HOME',
XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
XDG_DATA_HOME='$XDG_CONFIG_HOME',
XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR',
XDG_STATE_HOME='$XDG_CONFIG_HOME',
XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
clear({
args_rm={'runtimepath'},
env={
XDG_CONFIG_HOME='$XDG_DATA_HOME',
XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
XDG_DATA_HOME='$XDG_CONFIG_HOME',
XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR',
XDG_STATE_HOME='$XDG_CONFIG_HOME',
XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
}})
end)
@ -478,12 +484,14 @@ describe('XDG defaults', function()
describe('with commas', function()
before_each(function()
clear({env={
XDG_CONFIG_HOME=', , ,',
XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
XDG_DATA_HOME=',=,=,',
XDG_STATE_HOME=',=,=,',
XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
clear({
args_rm={'runtimepath'},
env={
XDG_CONFIG_HOME=', , ,',
XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
XDG_DATA_HOME=',=,=,',
XDG_STATE_HOME=',=,=,',
XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
}})
end)