aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2024-02-15 17:16:04 +0000
committerLewis Russell <me@lewisr.dev>2024-02-27 14:41:17 +0000
commit9beb40a4db5613601fc1a4b828a44e5977eca046 (patch)
tree314096d28ccdf2a2b035091783baa35193887d6a
parent7ad2e3c64562bfb0ea2f7be305e4b0e6d2474d64 (diff)
downloadrneovim-9beb40a4db5613601fc1a4b828a44e5977eca046.tar.gz
rneovim-9beb40a4db5613601fc1a4b828a44e5977eca046.tar.bz2
rneovim-9beb40a4db5613601fc1a4b828a44e5977eca046.zip
feat(docs): replace lua2dox.lua
Problem: The documentation flow (`gen_vimdoc.py`) has several issues: - it's not very versatile - depends on doxygen - doesn't work well with Lua code as it requires an awkward filter script to convert it into pseudo-C. - The intermediate XML files and filters makes it too much like a rube goldberg machine. Solution: Re-implement the flow using Lua, LPEG and treesitter. - `gen_vimdoc.py` is now replaced with `gen_vimdoc.lua` and replicates a portion of the logic. - `lua2dox.lua` is gone! - No more XML files. - Doxygen is now longer used and instead we now use: - LPEG for comment parsing (see `scripts/luacats_grammar.lua` and `scripts/cdoc_grammar.lua`). - LPEG for C parsing (see `scripts/cdoc_parser.lua`) - Lua patterns for Lua parsing (see `scripts/luacats_parser.lua`). - Treesitter for Markdown parsing (see `scripts/text_utils.lua`). - The generated `runtime/doc/*.mpack` files have been removed. - `scripts/gen_eval_files.lua` now instead uses `scripts/cdoc_parser.lua` directly. - Text wrapping is implemented in `scripts/text_utils.lua` and appears to produce more consistent results (the main contributer to the diff of this change).
-rw-r--r--.github/workflows/docs.yml4
-rw-r--r--CONTRIBUTING.md15
-rw-r--r--contrib/flake.nix1
-rw-r--r--contrib/local.mk.example6
-rw-r--r--runtime/doc/api.txt232
-rw-r--r--runtime/doc/diagnostic.txt17
-rw-r--r--runtime/doc/lsp.txt59
-rw-r--r--runtime/doc/lua.txt414
-rw-r--r--runtime/doc/treesitter.txt57
-rw-r--r--runtime/lua/vim/_editor.lua14
-rw-r--r--runtime/lua/vim/_inspector.lua4
-rw-r--r--runtime/lua/vim/_meta/api.lua843
-rw-r--r--runtime/lua/vim/_meta/builtin.lua116
-rw-r--r--runtime/lua/vim/_meta/json.lua2
-rw-r--r--runtime/lua/vim/_meta/lpeg.lua23
-rw-r--r--runtime/lua/vim/_meta/mpack.lua5
-rw-r--r--runtime/lua/vim/_meta/re.lua13
-rw-r--r--runtime/lua/vim/_meta/regex.lua2
-rw-r--r--runtime/lua/vim/_options.lua356
-rw-r--r--runtime/lua/vim/diagnostic.lua125
-rw-r--r--runtime/lua/vim/filetype.lua6
-rw-r--r--runtime/lua/vim/fs.lua2
-rw-r--r--runtime/lua/vim/highlight.lua15
-rw-r--r--runtime/lua/vim/iter.lua8
-rw-r--r--runtime/lua/vim/keymap.lua2
-rw-r--r--runtime/lua/vim/loader.lua13
-rw-r--r--runtime/lua/vim/lsp.lua190
-rw-r--r--runtime/lua/vim/lsp/buf.lua35
-rw-r--r--runtime/lua/vim/lsp/codelens.lua2
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua4
-rw-r--r--runtime/lua/vim/lsp/handlers.lua5
-rw-r--r--runtime/lua/vim/lsp/log.lua2
-rw-r--r--runtime/lua/vim/lsp/rpc.lua2
-rw-r--r--runtime/lua/vim/lsp/sync.lua4
-rw-r--r--runtime/lua/vim/lsp/util.lua8
-rw-r--r--runtime/lua/vim/shared.lua92
-rw-r--r--runtime/lua/vim/snippet.lua2
-rw-r--r--runtime/lua/vim/treesitter.lua2
-rw-r--r--runtime/lua/vim/treesitter/_query_linter.lua2
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua1
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua4
-rw-r--r--runtime/lua/vim/treesitter/query.lua4
-rw-r--r--runtime/lua/vim/uri.lua3
-rw-r--r--runtime/lua/vim/version.lua9
-rw-r--r--scripts/cdoc_grammar.lua87
-rw-r--r--scripts/cdoc_parser.lua223
-rwxr-xr-xscripts/gen_eval_files.lua100
-rwxr-xr-xscripts/gen_vimdoc.lua787
-rwxr-xr-xscripts/gen_vimdoc.py1766
-rw-r--r--scripts/lua2dox.lua544
-rw-r--r--scripts/luacats_grammar.lua218
-rw-r--r--scripts/luacats_parser.lua521
-rw-r--r--scripts/text_utils.lua239
-rw-r--r--src/nvim/CMakeLists.txt24
-rw-r--r--src/nvim/api/autocmd.c12
-rw-r--r--src/nvim/api/buffer.c10
-rw-r--r--src/nvim/api/command.c2
-rw-r--r--src/nvim/api/deprecated.c8
-rw-r--r--src/nvim/api/extmark.c1
-rw-r--r--src/nvim/api/options.c24
-rw-r--r--src/nvim/api/ui.c4
-rw-r--r--src/nvim/api/vim.c25
-rw-r--r--src/nvim/api/vimscript.c6
-rw-r--r--src/nvim/api/win_config.c36
-rw-r--r--src/nvim/api/window.c1
-rw-r--r--src/nvim/generators/c_grammar.lua70
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua14
-rw-r--r--src/nvim/generators/gen_api_ui_events.lua4
-rw-r--r--src/nvim/generators/luacats_grammar.lua136
-rw-r--r--test/functional/script/luacats_grammar_spec.lua (renamed from test/functional/luacats_grammar_spec.lua)4
-rw-r--r--test/functional/script/text_utils_spec.lua39
71 files changed, 3741 insertions, 3889 deletions
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 83e7c77dc9..c91f2945fb 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -20,10 +20,6 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- - name: Install dependencies
- run: |
- sudo apt-get install -y doxygen python3-msgpack
-
- name: Generate docs
run: |
make doc
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d0e463866b..2f5c2cce5a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -272,11 +272,16 @@ make lintdoc
```
If you need to modify or debug the documentation flow, these are the main files:
-- `./scripts/gen_vimdoc.py`:
- Main doc generator. Drives doxygen to generate xml files, and scrapes those
- xml files to render vimdoc files.
-- `./scripts/lua2dox.lua`:
- Used by `gen_vimdoc.py` to transform Lua files into a format compatible with doxygen.
+- `./scripts/gen_vimdoc.lua`:
+ Main doc generator. Parses C and Lua files to render vimdoc files.
+- `./scripts/luacats_parser.lua`:
+ Documentation parser for Lua files.
+- `./scripts/cdoc_parser.lua`:
+ Documentation parser for C files.
+- `./scripts/luacats_grammar.lua`:
+ Lpeg grammar for LuaCATS
+- `./scripts/cdoc_grammar.lua`:
+ Lpeg grammar for C doc comments
- `./scripts/gen_eval_files.lua`:
Generates documentation and Lua type files from metadata files:
```
diff --git a/contrib/flake.nix b/contrib/flake.nix
index 51c2014d6c..6355f3a68a 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -140,7 +140,6 @@
include-what-you-use # for scripts/check-includes.py
jq # jq for scripts/vim-patch.sh -r
shellcheck # for `make shlint`
- doxygen # for script/gen_vimdoc.py
];
nativeBuildInputs = with pkgs;
diff --git a/contrib/local.mk.example b/contrib/local.mk.example
index bda2c1b4dc..4e8a510f2d 100644
--- a/contrib/local.mk.example
+++ b/contrib/local.mk.example
@@ -55,9 +55,3 @@
# DEPS_CMAKE_FLAGS += -DUSE_BUNDLED=OFF
# .DEFAULT_GOAL := nvim
-#
-# Run doxygen over the source code.
-# Output will be in build/doxygen
-#
-# doxygen:
-# doxygen src/Doxyfile
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index e994644be9..1b00777532 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -579,7 +579,7 @@ created for extmark changes.
==============================================================================
Global Functions *api-global*
-nvim__get_runtime({pat}, {all}, {*opts}) *nvim__get_runtime()*
+nvim__get_runtime({pat}, {all}, {opts}) *nvim__get_runtime()*
Find files in runtime directories
Attributes: ~
@@ -700,7 +700,7 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()*
• {chan} id of the channel
• {data} data to write. 8-bit clean: can contain NUL bytes.
-nvim_complete_set({index}, {*opts}) *nvim_complete_set()*
+nvim_complete_set({index}, {opts}) *nvim_complete_set()*
Set info for the completion candidate index. if the info was shown in a
window, then the window and buffer ids are returned for further
customization. If the text was not shown, an empty dict is returned.
@@ -766,7 +766,7 @@ nvim_del_var({name}) *nvim_del_var()*
Parameters: ~
• {name} Variable name
-nvim_echo({chunks}, {history}, {*opts}) *nvim_echo()*
+nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
Echo a message.
Parameters: ~
@@ -797,7 +797,7 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
See also: ~
• nvim_err_write()
-nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
+nvim_eval_statusline({str}, {opts}) *nvim_eval_statusline()*
Evaluates statusline string.
Attributes: ~
@@ -878,13 +878,13 @@ nvim_get_api_info() *nvim_get_api_info()*
Returns a 2-tuple (Array), where item 0 is the current channel id and item
1 is the |api-metadata| map (Dictionary).
- Return: ~
- 2-tuple [{channel-id}, {api-metadata}]
-
Attributes: ~
|api-fast|
|RPC| only
+ Return: ~
+ 2-tuple [{channel-id}, {api-metadata}]
+
nvim_get_chan_info({chan}) *nvim_get_chan_info()*
Gets information about a channel.
@@ -900,12 +900,10 @@ nvim_get_chan_info({chan}) *nvim_get_chan_info()*
• "stderr" stderr of this Nvim instance
• "socket" TCP/IP socket or named pipe
• "job" Job with communication over its stdio.
-
• "mode" How data received on the channel is interpreted.
• "bytes" Send and receive raw bytes.
• "terminal" |terminal| instance interprets ASCII sequences.
• "rpc" |RPC| communication on the channel is active.
-
• "pty" (optional) Name of pseudoterminal. On a POSIX system this is a
device path like "/dev/pts/1". If the name is unknown, the key will
still be present if a pty is used (e.g. for conpty on Windows).
@@ -937,7 +935,7 @@ nvim_get_color_map() *nvim_get_color_map()*
Return: ~
Map of color names and RGB values.
-nvim_get_context({*opts}) *nvim_get_context()*
+nvim_get_context({opts}) *nvim_get_context()*
Gets a map of the current editor state.
Parameters: ~
@@ -972,7 +970,7 @@ nvim_get_current_win() *nvim_get_current_win()*
Return: ~
Window handle
-nvim_get_hl({ns_id}, {*opts}) *nvim_get_hl()*
+nvim_get_hl({ns_id}, {opts}) *nvim_get_hl()*
Gets all or specific highlight groups in a namespace.
Note: ~
@@ -1001,7 +999,7 @@ nvim_get_hl_id_by_name({name}) *nvim_get_hl_id_by_name()*
similar to |hlID()|, but allocates a new ID if not present.
-nvim_get_hl_ns({*opts}) *nvim_get_hl_ns()*
+nvim_get_hl_ns({opts}) *nvim_get_hl_ns()*
Gets the active highlight namespace.
Parameters: ~
@@ -1024,7 +1022,7 @@ nvim_get_keymap({mode}) *nvim_get_keymap()*
Array of |maparg()|-like dictionaries describing mappings. The
"buffer" key is always zero.
-nvim_get_mark({name}, {*opts}) *nvim_get_mark()*
+nvim_get_mark({name}, {opts}) *nvim_get_mark()*
Returns a `(row, col, buffer, buffername)` tuple representing the position
of the uppercase/file named mark. "End of line" column position is
returned as |v:maxcol| (big number). See |mark-motions|.
@@ -1050,12 +1048,12 @@ nvim_get_mode() *nvim_get_mode()*
Gets the current mode. |mode()| "blocking" is true if Nvim is waiting for
input.
- Return: ~
- Dictionary { "mode": String, "blocking": Boolean }
-
Attributes: ~
|api-fast|
+ Return: ~
+ Dictionary { "mode": String, "blocking": Boolean }
+
nvim_get_proc({pid}) *nvim_get_proc()*
Gets info describing process `pid`.
@@ -1222,7 +1220,7 @@ nvim_notify({msg}, {log_level}, {opts}) *nvim_notify()*
• {log_level} The log level
• {opts} Reserved for future use.
-nvim_open_term({buffer}, {*opts}) *nvim_open_term()*
+nvim_open_term({buffer}, {opts}) *nvim_open_term()*
Open a terminal instance in a buffer
By default (and currently the only option) the terminal will not be
@@ -1280,14 +1278,13 @@ nvim_paste({data}, {crlf}, {phase}) *nvim_paste()*
• {data} Multiline input. May be binary (containing NUL bytes).
• {crlf} Also break lines at CR and CRLF.
• {phase} -1: paste in a single call (i.e. without streaming). To
- "stream" a paste, call `nvim_paste` sequentially
- with these `phase` values:
+ "stream" a paste, call `nvim_paste` sequentially with these
+ `phase` values:
• 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once)
Return: ~
-
• true: Client may continue pasting.
• false: Client must cancel the paste.
@@ -1326,7 +1323,7 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special})
• cpoptions
*nvim_select_popupmenu_item()*
-nvim_select_popupmenu_item({item}, {insert}, {finish}, {*opts})
+nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts})
Selects an item in the completion popup menu.
If neither |ins-completion| nor |cmdline-completion| popup menu is active
@@ -1450,20 +1447,20 @@ nvim_set_current_win({window}) *nvim_set_current_win()*
Parameters: ~
• {window} Window handle
-nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()*
+nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
Sets a highlight group.
Note: ~
- • Unlike the `:highlight` command which can update a highlight group, this
- function completely replaces the definition. For example:
+ • Unlike the `:highlight` command which can update a highlight group,
+ this function completely replaces the definition. For example:
`nvim_set_hl(0, 'Visual', {})` will clear the highlight group
'Visual'.
- • The fg and bg keys also accept the string values `"fg"` or `"bg"` which
- act as aliases to the corresponding foreground and background values
- of the Normal group. If the Normal group has not been defined, using
- these values results in an error.
- • If `link` is used in combination with other attributes; only the `link`
- will take effect (see |:hi-link|).
+ • The fg and bg keys also accept the string values `"fg"` or `"bg"`
+ which act as aliases to the corresponding foreground and background
+ values of the Normal group. If the Normal group has not been defined,
+ using these values results in an error.
+ • If `link` is used in combination with other attributes; only the
+ `link` will take effect (see |:hi-link|).
Parameters: ~
• {ns_id} Namespace id for this highlight |nvim_create_namespace()|.
@@ -1520,7 +1517,7 @@ nvim_set_hl_ns_fast({ns_id}) *nvim_set_hl_ns_fast()*
Parameters: ~
• {ns_id} the namespace to activate
-nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
+nvim_set_keymap({mode}, {lhs}, {rhs}, {opts}) *nvim_set_keymap()*
Sets a global |mapping| for the given mode.
To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
@@ -1537,8 +1534,8 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
<
Parameters: ~
- • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …) or
- "!" for |:map!|, or empty string for |:map|. "ia", "ca" or
+ • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …)
+ or "!" for |:map!|, or empty string for |:map|. "ia", "ca" or
"!a" for abbreviation in Insert mode, Cmdline mode, or both,
respectively
• {lhs} Left-hand-side |{lhs}| of the mapping.
@@ -1651,7 +1648,7 @@ nvim_eval({expr}) *nvim_eval()*
Return: ~
Evaluation result or expanded object
-nvim_exec2({src}, {*opts}) *nvim_exec2()*
+nvim_exec2({src}, {opts}) *nvim_exec2()*
Executes Vimscript (multiline block of Ex commands), like anonymous
|:source|.
@@ -1704,18 +1701,16 @@ nvim_parse_expression({expr}, {flags}, {highlight})
region [start_col, end_col)).
Return: ~
-
• AST: top-level dictionary with these keys:
• "error": Dictionary with error, present only if parser saw some
error. Contains the following keys:
• "message": String, error message in printf format, translated.
Must contain exactly one "%.*s".
• "arg": String, error message argument.
-
• "len": Amount of bytes successfully parsed. With flags equal to ""
- that should be equal to the length of expr string. (“Successfully
- parsed” here means “participated in AST creation”, not “till the
- first error”.)
+ that should be equal to the length of expr string. ("Successfully
+ parsed" here means "participated in AST creation", not "till the
+ first error".)
• "ast": AST, either nil or a dictionary with these keys:
• "type": node type, one of the value names from ExprASTNodeType
stringified without "kExprNode" prefix.
@@ -1730,7 +1725,6 @@ nvim_parse_expression({expr}, {flags}, {highlight})
is zero, one or two children, key will not be present if node
has no children. Maximum number of children may be found in
node_maxchildren array.
-
• Local values (present only for certain nodes):
• "scope": a single Integer, specifies scope for "Option" and
"PlainIdentifier" nodes. For "Option" it is one of ExprOptScope
@@ -1760,11 +1754,11 @@ nvim_parse_expression({expr}, {flags}, {highlight})
Command Functions *api-command*
*nvim_buf_create_user_command()*
-nvim_buf_create_user_command({buffer}, {name}, {command}, {*opts})
+nvim_buf_create_user_command({buffer}, {name}, {command}, {opts})
Creates a buffer-local command |user-commands|.
Parameters: ~
- • {buffer} Buffer handle, or 0 for current buffer.
+ • {buffer} Buffer handle, or 0 for current buffer.
See also: ~
• nvim_create_user_command
@@ -1780,7 +1774,7 @@ nvim_buf_del_user_command({buffer}, {name})
• {buffer} Buffer handle, or 0 for current buffer.
• {name} Name of the command to delete.
-nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
+nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()*
Gets a map of buffer-local |user-commands|.
Parameters: ~
@@ -1790,7 +1784,7 @@ nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
Return: ~
Map of maps describing commands.
-nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
+nvim_cmd({cmd}, {opts}) *nvim_cmd()*
Executes an Ex command.
Unlike |nvim_command()| this command takes a structured Dictionary instead
@@ -1825,7 +1819,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
• |nvim_command()|
*nvim_create_user_command()*
-nvim_create_user_command({name}, {command}, {*opts})
+nvim_create_user_command({name}, {command}, {opts})
Creates a global |user-commands| command.
For Lua usage see |lua-guide-commands-create|.
@@ -1885,7 +1879,7 @@ nvim_del_user_command({name}) *nvim_del_user_command()*
Parameters: ~
• {name} Name of the command to delete.
-nvim_get_commands({*opts}) *nvim_get_commands()*
+nvim_get_commands({opts}) *nvim_get_commands()*
Gets a map of global (non-buffer-local) Ex commands.
Currently only |user-commands| are supported, not builtin Ex commands.
@@ -1899,7 +1893,7 @@ nvim_get_commands({*opts}) *nvim_get_commands()*
See also: ~
• |nvim_get_all_options_info()|
-nvim_parse_cmd({str}, {*opts}) *nvim_parse_cmd()*
+nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
Parse command line.
Doesn't check the validity of command arguments.
@@ -1937,13 +1931,11 @@ nvim_parse_cmd({str}, {*opts}) *nvim_parse_cmd()*
• bar: (boolean) The "|" character is treated as a command separator
and the double quote character (") is treated as the start of a
comment.
-
• mods: (dictionary) |:command-modifiers|.
• filter: (dictionary) |:filter|.
• pattern: (string) Filter pattern. Empty string if there is no
filter.
• force: (boolean) Whether filter is inverted or not.
-
• silent: (boolean) |:silent|.
• emsg_silent: (boolean) |:silent!|.
• unsilent: (boolean) |:unsilent|.
@@ -1986,7 +1978,7 @@ nvim_get_all_options_info() *nvim_get_all_options_info()*
See also: ~
• |nvim_get_commands()|
-nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
+nvim_get_option_info2({name}, {opts}) *nvim_get_option_info2()*
Gets the option information for one option from arbitrary buffer or window
Resulting dictionary has keys:
@@ -2020,7 +2012,7 @@ nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
Return: ~
Option Information
-nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
+nvim_get_option_value({name}, {opts}) *nvim_get_option_value()*
Gets the value of an option. The behavior of this function matches that of
|:set|: the local value of an option is returned if it exists; otherwise,
the global value is returned. Local values always correspond to the
@@ -2043,7 +2035,7 @@ nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
Option value
*nvim_set_option_value()*
-nvim_set_option_value({name}, {value}, {*opts})
+nvim_set_option_value({name}, {value}, {opts})
Sets the value of an option. The behavior of this function matches that of
|:set|: for global-local options, both the global and local value are set
unless otherwise specified with {scope}.
@@ -2069,16 +2061,16 @@ For more information on buffers, see |buffers|.
Unloaded Buffers: ~
Buffers may be unloaded by the |:bunload| command or the buffer's
-|'bufhidden'| option. When a buffer is unloaded its file contents are
-freed from memory and vim cannot operate on the buffer lines until it is
-reloaded (usually by opening the buffer again in a new window). API
-methods such as |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be
-affected.
+|'bufhidden'| option. When a buffer is unloaded its file contents are freed
+from memory and vim cannot operate on the buffer lines until it is reloaded
+(usually by opening the buffer again in a new window). API methods such as
+|nvim_buf_get_lines()| and |nvim_buf_line_count()| will be affected.
You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
whether a buffer is loaded.
-nvim_buf_attach({buffer}, {send_buffer}, {*opts}) *nvim_buf_attach()*
+
+nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activates buffer-update events on a channel, or as Lua callbacks.
Example (Lua): capture buffer updates in a global `events` variable (use
@@ -2100,8 +2092,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {*opts}) *nvim_buf_attach()*
callbacks.
• {opts} Optional parameters.
• on_lines: Lua callback invoked on change. Return a
- truthy value (not `false` or `nil`)
- to detach. Args:
+ truthy value (not `false` or `nil`) to detach. Args:
• the string "lines"
• buffer handle
• b:changedtick
@@ -2111,12 +2102,10 @@ nvim_buf_attach({buffer}, {send_buffer}, {*opts}) *nvim_buf_attach()*
• byte count of previous contents
• deleted_codepoints (if `utf_sizes` is true)
• deleted_codeunits (if `utf_sizes` is true)
-
• on_bytes: Lua callback invoked on change. This
callback receives more granular information about the
change compared to on_lines. Return a truthy value
- (not `false` or `nil`) to
- detach. Args:
+ (not `false` or `nil`) to detach. Args:
• the string "bytes"
• buffer handle
• b:changedtick
@@ -2134,22 +2123,18 @@ nvim_buf_attach({buffer}, {send_buffer}, {*opts}) *nvim_buf_attach()*
• new end column of the changed text (if new end row
= 0, offset from start column)
• new end byte length of the changed text
-
• on_changedtick: Lua callback invoked on changedtick
increment without text change. Args:
• the string "changedtick"
• buffer handle
• b:changedtick
-
• on_detach: Lua callback invoked on detach. Args:
• the string "detach"
• buffer handle
-
• on_reload: Lua callback invoked on reload. The entire
buffer content should be considered changed. Args:
• the string "reload"
• buffer handle
-
• utf_sizes: include UTF-32 and UTF-16 size of the
replaced region, as args to `on_lines`.
• preview: also attach to command preview (i.e.
@@ -2221,7 +2206,7 @@ nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()*
• {buffer} Buffer handle, or 0 for current buffer
• {name} Variable name
-nvim_buf_delete({buffer}, {*opts}) *nvim_buf_delete()*
+nvim_buf_delete({buffer}, {opts}) *nvim_buf_delete()*
Deletes the buffer. See |:bwipeout|
Attributes: ~
@@ -2263,8 +2248,8 @@ nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()*
Gets a list of buffer-local |mapping| definitions.
Parameters: ~
- • {mode} Mode short-name ("n", "i", "v", ...)
• {buffer} Buffer handle, or 0 for current buffer
+ • {mode} Mode short-name ("n", "i", "v", ...)
Return: ~
Array of |maparg()|-like dictionaries describing mappings. The
@@ -2338,7 +2323,7 @@ nvim_buf_get_offset({buffer}, {index}) *nvim_buf_get_offset()*
*nvim_buf_get_text()*
nvim_buf_get_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
- {*opts})
+ {opts})
Gets a range from the buffer.
This differs from |nvim_buf_get_lines()| in that it allows retrieving only
@@ -2403,7 +2388,7 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Line count, or 0 for unloaded buffer. |api-buffer|
*nvim_buf_set_keymap()*
-nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts})
+nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {opts})
Sets a buffer-local |mapping| for the given mode.
Parameters: ~
@@ -2440,7 +2425,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
• |nvim_buf_set_text()|
*nvim_buf_set_mark()*
-nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {*opts})
+nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts})
Sets a named mark in the given buffer, all marks are allowed
file/uppercase, visual, last change, etc. See |mark-motions|.
@@ -2581,7 +2566,7 @@ nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()*
true if the extmark was found, else false
*nvim_buf_get_extmark_by_id()*
-nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {*opts})
+nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
Gets the position (0-indexed) of an |extmark|.
Parameters: ~
@@ -2597,7 +2582,7 @@ nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {*opts})
0-indexed (row, col) tuple or empty list () if extmark id was absent
*nvim_buf_get_extmarks()*
-nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
+nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
Gets |extmarks| in "traversal order" from a |charwise| region defined by
buffer positions (inclusive, 0-indexed |api-indexing|).
@@ -2657,7 +2642,7 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
List of [extmark_id, row, col] tuples in "traversal order".
*nvim_buf_set_extmark()*
-nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
+nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
Creates or updates an |extmark|.
By default a new extmark is created when no id is passed in, but it is
@@ -2703,7 +2688,6 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
• "right_align": display right aligned in the window.
• "inline": display at the specified column, and shift the
buffer text to the right as needed.
-
• virt_text_win_col : position the virtual text at a fixed
window column (starting from the first text column of the
screen line) instead of "virt_text_pos".
@@ -2715,14 +2699,12 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
wrapped lines.
• hl_mode : control how highlights are combined with the
highlights of the text. Currently only affects virt_text
- highlights, but might affect `hl_group` in
- later versions.
+ highlights, but might affect `hl_group` in later versions.
• "replace": only show the virt_text color. This is the
default.
• "combine": combine with background text color.
• "blend": blend with background text color. Not supported
for "inline" virt_text.
-
• virt_lines : virtual lines to add next to this mark This
should be an array over lines, where each line in turn is
an array over [text, highlight] tuples. In general, buffer
@@ -2815,7 +2797,7 @@ nvim_get_namespaces() *nvim_get_namespaces()*
dict that maps from names to namespace ids.
*nvim_set_decoration_provider()*
-nvim_set_decoration_provider({ns_id}, {*opts})
+nvim_set_decoration_provider({ns_id}, {opts})
Set or change decoration provider for a |namespace|
This is a very general purpose interface for having Lua callbacks being
@@ -3066,7 +3048,7 @@ nvim_win_set_hl_ns({window}, {ns_id}) *nvim_win_set_hl_ns()*
This takes precedence over the 'winhighlight' option.
Parameters: ~
- • {ns_id} the namespace to use
+ • {ns_id} the namespace to use
nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()*
Sets a window-scoped (w:) variable
@@ -3084,7 +3066,7 @@ nvim_win_set_width({window}, {width}) *nvim_win_set_width()*
• {window} Window handle, or 0 for current window
• {width} Width as a count of columns
-nvim_win_text_height({window}, {*opts}) *nvim_win_text_height()*
+nvim_win_text_height({window}, {opts}) *nvim_win_text_height()*
Computes the number of screen lines occupied by a range of text in a given
window. Works for off-screen text and takes folds into account.
@@ -3120,9 +3102,9 @@ nvim_win_text_height({window}, {*opts}) *nvim_win_text_height()*
==============================================================================
-Win_Config Functions *api-win_config*
+Win_config Functions *api-win_config*
-nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
+nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Opens a new split window, or a floating window if `relative` is specified,
or an external window (managed by the UI) if `external` is specified.
@@ -3188,7 +3170,6 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
window.
• "cursor" Cursor position in current window.
• "mouse" Mouse position
-
• win: |window-ID| window to split, or relative window when
creating a float (relative="win").
• anchor: Decides which corner of the float to place at
@@ -3197,17 +3178,15 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
• "NE" northeast
• "SW" southwest
• "SE" southeast
-
• width: Window width (in character cells). Minimum of 1.
• height: Window height (in character cells). Minimum of 1.
• bufpos: Places float relative to buffer text (only when
relative="win"). Takes a tuple of zero-indexed [line,
- column]. `row` and `col` if given are
- applied relative to this position, else they default to:
+ column]. `row` and `col` if given are applied relative to
+ this position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or "NE"
• `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
like a tooltip near the buffer text).
-
• row: Row position in units of "screen cell height", may be
fractional.
• col: Column position in units of "screen cell width", may
@@ -3228,7 +3207,6 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
wildoptions+=pum) The default value for floats are 50.
In general, values below 100 are recommended, unless
there is a good reason to overshadow builtin elements.
-
• style: (optional) Configure the appearance of the window.
Currently only supports one value:
• "minimal" Nvim will display the window with many UI
@@ -3241,14 +3219,13 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
empty. The end-of-buffer region is hidden by setting
`eob` flag of 'fillchars' to a space char, and clearing
the |hl-EndOfBuffer| region in 'winhighlight'.
-
• border: Style of (optional) window border. This can either
be a string or an array. The string values are
• "none": No border (default).
• "single": A single line box.
• "double": A double line box.
- • "rounded": Like "single", but with rounded corners ("╭"
- etc.).
+ • "rounded": Like "single", but with rounded corners
+ ("╭" etc.).
• "solid": Adds padding by a single whitespace cell.
• "shadow": A drop shadow effect by blending with the
background.
@@ -3256,19 +3233,26 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
any divisor of eight. The array will specify the eight
chars building up the border in a clockwise fashion
starting with the top-left corner. As an example, the
- double box style could be specified as [ "╔", "═" ,"╗",
- "║", "╝", "═", "╚", "║" ]. If the number of chars are
- less than eight, they will be repeated. Thus an ASCII
- border could be specified as [ "/", "-", "\\", "|" ], or
- all chars the same as [ "x" ]. An empty string can be
- used to turn off a specific border, for instance, [ "",
- "", "", ">", "", "", "", "<" ] will only make vertical
- borders but not horizontal ones. By default,
- `FloatBorder` highlight is used, which links to
- `WinSeparator` when not defined. It could also be
- specified by character: [ ["+", "MyCorner"], ["x",
- "MyBorder"] ].
-
+ double box style could be specified as: >
+ [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
+<
+ If the number of chars are less than eight, they will be
+ repeated. Thus an ASCII border could be specified as >
+ [ "/", "-", \"\\\\\", "|" ],
+<
+ or all chars the same as >
+ [ "x" ].
+<
+ An empty string can be used to turn off a specific border,
+ for instance, >
+ [ "", "", "", ">", "", "", "", "<" ]
+<
+ will only make vertical borders but not horizontal ones.
+ By default, `FloatBorder` highlight is used, which links
+ to `WinSeparator` when not defined. It could also be
+ specified by character: >
+ [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+<
• title: Title (optional) in window border, string or list.
List should consist of `[text, highlight]` tuples. If
string, the default highlight group is `FloatTitle`.
@@ -3306,7 +3290,7 @@ nvim_win_get_config({window}) *nvim_win_get_config()*
Return: ~
Map defining the window configuration, see |nvim_open_win()|
-nvim_win_set_config({window}, {*config}) *nvim_win_set_config()*
+nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
Configures window layout. Currently only for floating and external windows
(including changing a split window to those layouts).
@@ -3397,7 +3381,7 @@ nvim_tabpage_set_win({tabpage}, {win}) *nvim_tabpage_set_win()*
==============================================================================
Autocmd Functions *api-autocmd*
-nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()*
+nvim_clear_autocmds({opts}) *nvim_clear_autocmds()*
Clears all autocommands selected by {opts}. To delete autocmds see
|nvim_del_autocmd()|.
@@ -3407,25 +3391,21 @@ nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()*
• event: "pat1"
• event: { "pat1" }
• event: { "pat1", "pat2", "pat3" }
-
• pattern: (string|table)
• pattern or patterns to match exactly.
• For example, if you have `*.py` as that pattern for the
autocmd, you must pass `*.py` exactly to clear it.
`test.py` will not match the pattern.
-
• defaults to clearing all patterns.
• NOTE: Cannot be used with {buffer}
-
• buffer: (bufnr)
• clear only |autocmd-buflocal| autocommands.
• NOTE: Cannot be used with {pattern}
-
• group: (string|int) The augroup name or id.
• NOTE: If not passed, will only delete autocmds not in any
group.
-nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
+nvim_create_augroup({name}, {opts}) *nvim_create_augroup()*
Create or get an autocommand group |autocmd-groups|.
To get an existing group id, do: >lua
@@ -3446,9 +3426,10 @@ nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
See also: ~
• |autocmd-groups|
-nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
- Creates an |autocommand| event handler, defined by `callback` (Lua function
- or Vimscript function name string) or `command` (Ex command string).
+nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()*
+ Creates an |autocommand| event handler, defined by `callback` (Lua
+ function or Vimscript function name string) or `command` (Ex command
+ string).
Example using Lua callback: >lua
vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
@@ -3487,8 +3468,8 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• callback (function|string) optional: Lua function (or
Vimscript function name, if string) called when the
event(s) is triggered. Lua callback can return a truthy
- value (not `false` or `nil`) to delete the
- autocommand. Receives a table argument with these keys:
+ value (not `false` or `nil`) to delete the autocommand.
+ Receives a table argument with these keys:
• id: (number) autocommand id
• event: (string) name of the triggered event
|autocmd-events|
@@ -3498,7 +3479,6 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• file: (string) expanded value of |<afile>|
• data: (any) arbitrary data passed from
|nvim_exec_autocmds()|
-
• command (string) optional: Vim command to execute on event.
Cannot be used with {callback}
• once (boolean) optional: defaults to false. Run the
@@ -3548,7 +3528,7 @@ nvim_del_autocmd({id}) *nvim_del_autocmd()*
Parameters: ~
• {id} Integer Autocommand id returned by |nvim_create_autocmd()|
-nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
+nvim_exec_autocmds({event}, {opts}) *nvim_exec_autocmds()*
Execute all autocommands for {event} that match the corresponding {opts}
|autocmd-execute|.
@@ -3569,7 +3549,7 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
See also: ~
• |:doautocmd|
-nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
+nvim_get_autocmds({opts}) *nvim_get_autocmds()*
Get all autocommands that match the corresponding {opts}.
These examples will get autocommands matching ALL the given criteria: >lua
@@ -3683,13 +3663,12 @@ nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()*
• {height} Popupmenu height, must be greater than zero.
nvim_ui_set_focus({gained}) *nvim_ui_set_focus()*
- Tells the nvim server if focus was gained or lost by the GUI.
+ Tells the nvim server if focus was gained or lost by the GUI
Attributes: ~
|RPC| only
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
- TODO: Documentation
Attributes: ~
|RPC| only
@@ -3698,7 +3677,6 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
Tells Nvim when a terminal event has occurred
The following terminal events are supported:
-
• "termresponse": The terminal sent an OSC or DCS response sequence to
Nvim. The payload is the received response. Sets |v:termresponse| and
fires |TermResponse|.
@@ -3707,11 +3685,10 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
|RPC| only
Parameters: ~
- • {event} Event name
- • {payload} Event payload
+ • {event} Event name
+ • {value} Event payload
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
- TODO: Documentation
Attributes: ~
|RPC| only
@@ -3731,4 +3708,5 @@ nvim_ui_try_resize_grid({grid}, {width}, {height})
• {width} The new requested width.
• {height} The new requested height.
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index bee0445e4e..dbfa0148af 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -397,7 +397,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
diagnostics. Options:
• severity: Only underline diagnostics matching the
given severity |diagnostic-severity|
-
• virtual_text: (default true) Use virtual text for
diagnostics. If multiple diagnostics are set for a
namespace, one prefix per diagnostic + the last
@@ -430,7 +429,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
• format: (function) A function that takes a diagnostic
as input and returns a string. The return value is
the text used to display the diagnostic. Example: >lua
-
function(diagnostic)
if diagnostic.severity == vim.diagnostic.severity.ERROR then
return string.format("E: %s", diagnostic.message)
@@ -438,7 +436,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
return diagnostic.message
end
<
-
• signs: (default true) Use signs for diagnostics
|diagnostic-signs|. Options:
• severity: Only show signs for diagnostics matching
@@ -452,7 +449,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
default is to use "E", "W", "I", and "H" for errors,
warnings, information, and hints, respectively.
Example: >lua
-
vim.diagnostic.config({
signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
})
@@ -463,7 +459,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
• linehl: (table) A table mapping |diagnostic-severity|
to the highlight group used for the whole line the
sign is placed in.
-
• float: Options for floating windows. See
|vim.diagnostic.open_float()|.
• update_in_insert: (default false) Update diagnostics in
@@ -542,8 +537,8 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Return: ~
(`vim.Diagnostic[]`) table A list of diagnostic items
- |diagnostic-structure|. Keys `bufnr` , `end_lnum` , `end_col` , and `severity` are
- guaranteed to be present.
+ |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and
+ `severity` are guaranteed to be present.
get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata.
@@ -685,7 +680,7 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
(`vim.Diagnostic?`) |diagnostic-structure| or `nil` if {pat} fails to
match {str}.
-open_float({opts}, {...}) *vim.diagnostic.open_float()*
+open_float({opts}) *vim.diagnostic.open_float()*
Show diagnostics in a floating window.
Parameters: ~
@@ -738,8 +733,9 @@ open_float({opts}, {...}) *vim.diagnostic.open_float()*
diagnostic instead of prepending it. Overrides the setting
from |vim.diagnostic.config()|.
- Return: ~
- (`integer?, integer?`) ({float_bufnr}, {win_id})
+ Return (multiple): ~
+ (`integer?`) float_bufnr
+ (`integer?`) win_id
reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
Remove all diagnostics from the given namespace.
@@ -823,4 +819,5 @@ toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Return: ~
(`table[]`) of quickfix list items |setqflist-what|
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index a94de629b2..c14c0e5b9c 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -712,10 +712,9 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
(`string?`) err On timeout, cancel, or error, `err` is a string
describing the failure reason, and `result` is nil.
-client() *vim.lsp.client*
+client *vim.lsp.client*
LSP client object. You can get an active client object via
|vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
-
• Methods:
• request(method, params, [handler], bufnr) Sends a request to the
server. This is a thin wrapper around {client.rpc.request} with some
@@ -750,7 +749,6 @@ client() *vim.lsp.client*
given method. Always returns true for unknown off-spec methods. [opts]
is a optional `{bufnr?: integer}` table. Some language server
capabilities can be file specific.
-
• Members
• {id} (number): The id allocated to the client.
• {name} (string): If a name is specified on creation, that will be
@@ -916,7 +914,6 @@ start({config}, {opts}) *vim.lsp.start()*
See |vim.lsp.start_client()| for all available options. The most important
are:
-
• `name` arbitrary name for the LSP client. Should be unique per language
server.
• `cmd` command string[] or function, described at
@@ -975,8 +972,7 @@ start_client({config}) *vim.lsp.start_client()*
• cmd_env: (table) Environment flags to pass to the LSP on
spawn. Must be specified using a table. Non-string values
are coerced to string. Example: >
-
- { PORT = 8080; HOST = "0.0.0.0"; }
+ { PORT = 8080; HOST = "0.0.0.0"; }
<
• detached: (boolean, default true) Daemonize the server
process so that it runs in a separate process group from
@@ -994,7 +990,6 @@ start_client({config}) *vim.lsp.start_client()*
make_client_capabilities() and modify its result.
• Note: To send an empty dictionary use
|vim.empty_dict()|, else it will be encoded as an array.
-
• handlers: Map of language server method names to
|lsp-handler|
• settings: Map with language server specific settings.
@@ -1041,7 +1036,6 @@ start_client({config}) *vim.lsp.start_client()*
• signal: number describing the signal used to terminate
(if any)
• client_id: client handle
-
• on_attach: Callback (client, bufnr) invoked when client
attaches to a buffer.
• trace: ("off" | "messages" | "verbose" | nil) passed
@@ -1059,7 +1053,6 @@ start_client({config}) *vim.lsp.start_client()*
sending the "shutdown" request before sending kill -15.
If set to false, nvim exits immediately after sending
the "shutdown" request to the server.
-
• root_dir: (string) Directory where the LSP server will
base its workspaceFolders, rootUri, and rootPath on
initialization.
@@ -1124,6 +1117,9 @@ add_workspace_folder({workspace_folder})
Add the folder at path to the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|.
+ Parameters: ~
+ • {workspace_folder} (`string?`)
+
clear_references() *vim.lsp.buf.clear_references()*
Removes document highlights from current buffer.
@@ -1133,8 +1129,8 @@ code_action({options}) *vim.lsp.buf.code_action()*
Parameters: ~
• {options} (`table?`) Optional table which holds the following
optional fields:
- • context: (table|nil) Corresponds to `CodeActionContext` of
- the LSP specification:
+ • context: (table|nil) Corresponds to `CodeActionContext`
+ of the LSP specification:
• diagnostics (table|nil): LSP `Diagnostic[]`. Inferred
from the current position if not provided.
• only (table|nil): List of LSP `CodeActionKind`s used to
@@ -1142,7 +1138,6 @@ code_action({options}) *vim.lsp.buf.code_action()*
values like `refactor` or `quickfix`.
• triggerKind (number|nil): The reason why code actions
were requested.
-
• filter: (function|nil) Predicate taking an `CodeAction`
and returning a boolean.
• apply: (boolean|nil) When set to `true`, and there is
@@ -1235,7 +1230,8 @@ format({options}) *vim.lsp.buf.format()*
optional fields:
• formatting_options (table|nil): Can be used to specify
FormattingOptions. Some unspecified options will be
- automatically derived from the current Nvim options. See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
+ automatically derived from the current Nvim options. See
+ https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
• timeout_ms (integer|nil, default 1000): Time in
milliseconds to block for formatting requests. No effect
if async=true
@@ -1245,7 +1241,6 @@ format({options}) *vim.lsp.buf.format()*
• filter (function|nil): Predicate used to filter clients.
Receives a client as argument and must return a boolean.
Clients matching the predicate are included. Example: >lua
-
-- Never request typescript-language-server for formatting
vim.lsp.buf.format {
filter = function(client) return client.name ~= "tsserver" end
@@ -1308,6 +1303,9 @@ remove_workspace_folder({workspace_folder})
Remove the folder at path from the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|.
+ Parameters: ~
+ • {workspace_folder} (`string?`)
+
rename({new_name}, {options}) *vim.lsp.buf.rename()*
Renames all references to the symbol under the cursor.
@@ -1454,12 +1452,13 @@ get({bufnr}) *vim.lsp.codelens.get()*
Return: ~
(`lsp.CodeLens[]`)
- *vim.lsp.codelens.on_codelens()*
-on_codelens({err}, {result}, {ctx}, {_})
+on_codelens({err}, {result}, {ctx}) *vim.lsp.codelens.on_codelens()*
|lsp-handler| for the method `textDocument/codeLens`
Parameters: ~
- • {ctx} (`lsp.HandlerContext`)
+ • {err} (`lsp.ResponseError?`)
+ • {result} (`lsp.CodeLens[]`)
+ • {ctx} (`lsp.HandlerContext`)
refresh({opts}) *vim.lsp.codelens.refresh()*
Refresh the lenses.
@@ -1499,7 +1498,7 @@ enable({bufnr}, {enable}) *vim.lsp.inlay_hint.enable()*
<
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
• {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
@@ -1523,7 +1522,7 @@ get({filter}) *vim.lsp.inlay_hint.get()*
<
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
• {filter} (`vim.lsp.inlay_hint.get.filter?`) Optional filters
@@ -1539,8 +1538,9 @@ get({filter}) *vim.lsp.inlay_hint.get()*
• inlay_hint (lsp.InlayHint)
is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()*
+
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
• {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
@@ -1653,6 +1653,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
<
Parameters: ~
+ • {result} (`lsp.Hover`)
• {ctx} (`lsp.HandlerContext`)
• {config} (`table`) Configuration table.
• border: (default=nil)
@@ -1674,7 +1675,7 @@ signature_help({_}, {result}, {ctx}, {config})
<
Parameters: ~
- • {result} (`table`) Response from the language server
+ • {result} (`lsp.SignatureHelp`) Response from the language server
• {ctx} (`lsp.HandlerContext`) Client context
• {config} (`table`) Configuration table.
• border: (default=nil)
@@ -1695,6 +1696,7 @@ apply_text_document_edit({text_document_edit}, {index}, {offset_encoding})
• {text_document_edit} (`table`) a `TextDocumentEdit` object
• {index} (`integer`) Optional index of the edit, if from
a list of edits (or nil, if not from a list)
+ • {offset_encoding} (`string?`)
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
@@ -1719,6 +1721,9 @@ apply_workspace_edit({workspace_edit}, {offset_encoding})
• {workspace_edit} (`table`) `WorkspaceEdit`
• {offset_encoding} (`string`) utf-8|utf-16|utf-32 (required)
+ See also: ~
+ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
+
buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer.
@@ -1994,6 +1999,7 @@ preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
Parameters: ~
• {location} (`table`) a single `Location` or `LocationLink`
+ • {opts} (`table`)
Return (multiple): ~
(`integer?`) buffer id of float window
@@ -2038,6 +2044,7 @@ stylize_markdown({bufnr}, {contents}, {opts})
`open_floating_preview` instead
Parameters: ~
+ • {bufnr} (`integer`)
• {contents} (`table`) of lines to show in window
• {opts} (`table`) with optional fields
• height of floating window
@@ -2055,6 +2062,7 @@ symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()*
Parameters: ~
• {symbols} (`table`) DocumentSymbol[] or SymbolInformation[]
+ • {bufnr} (`integer`)
==============================================================================
@@ -2092,7 +2100,7 @@ should_log({level}) *vim.lsp.log.should_log()*
• {level} (`integer`) log level
Return: ~
- (bool) true if would log, false if not
+ (`bool`) true if would log, false if not
==============================================================================
@@ -2110,7 +2118,8 @@ connect({host}, {port}) *vim.lsp.rpc.connect()*
• {port} (`integer`) port to connect to
Return: ~
- (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
+ (`fun(dispatchers: vim.lsp.rpc.Dispatchers):
+ vim.lsp.rpc.PublicClient`)
*vim.lsp.rpc.domain_socket_connect()*
domain_socket_connect({pipe_path})
@@ -2126,7 +2135,8 @@ domain_socket_connect({pipe_path})
of the named pipe (Windows) to connect to
Return: ~
- (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
+ (`fun(dispatchers: vim.lsp.rpc.Dispatchers):
+ vim.lsp.rpc.PublicClient`)
format_rpc_error({err}) *vim.lsp.rpc.format_rpc_error()*
Constructs an error message from an LSP error object.
@@ -2241,4 +2251,5 @@ resolve_capabilities({server_capabilities})
Return: ~
(`lsp.ServerCapabilities?`) Normalized table of capabilities
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 94b37ad7c6..f56d7f778a 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -582,25 +582,21 @@ A subset of the `vim.*` API is available in threads. This includes:
==============================================================================
VIM.HIGHLIGHT *vim.highlight*
-
Nvim includes a function for highlighting a selection on yank.
To enable it, add the following to your `init.vim`: >vim
au TextYankPost * silent! lua vim.highlight.on_yank()
-
<
-You can customize the highlight group and the duration of the highlight
-via: >vim
+You can customize the highlight group and the duration of the highlight via: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=150}
-
<
If you want to exclude visual selections from highlighting on yank, use: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
-
<
+
vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
Highlight the yanked text
@@ -678,12 +674,10 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
• `count_a` (integer): Hunk size in {a}.
• `start_b` (integer): Start line of hunk in {b}.
• `count_b` (integer): Hunk size in {b}.
-
• `result_type` (string): Form of the returned diff:
• "unified": (default) String in unified format.
• "indices": Array of hunk locations. Note: This option is
ignored if `on_hunk` is used.
-
• `linematch` (boolean|integer): Run linematch on the
resulting hunks from xdiff. When integer, only hunks upto
this size in lines are run through linematch. Requires
@@ -694,7 +688,6 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
possible diff
• "patience" patience diff algorithm
• "histogram" histogram diff algorithm
-
• `ctxlen` (integer): Context length
• `interhunkctxlen` (integer): Inter hunk context length
• `ignore_whitespace` (boolean): Ignore whitespace
@@ -716,30 +709,38 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
==============================================================================
VIM.MPACK *vim.mpack*
-
This module provides encoding and decoding of Lua objects to and from
msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
+
vim.mpack.decode({str}) *vim.mpack.decode()*
Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
Parameters: ~
• {str} (`string`)
+ Return: ~
+ (`any`)
+
vim.mpack.encode({obj}) *vim.mpack.encode()*
Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
+ Parameters: ~
+ • {obj} (`any`)
+
+ Return: ~
+ (`string`)
+
==============================================================================
VIM.JSON *vim.json*
-
This module provides encoding and decoding of Lua objects to and from
JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
+
vim.json.decode({str}, {opts}) *vim.json.decode()*
Decodes (or "unpacks") the JSON-encoded {str} to a Lua object.
-
• Decodes JSON "null" as |vim.NIL| (controllable by {opts}, see below).
• Decodes empty object as |vim.empty_dict()|.
• Decodes empty array as `{}` (empty Lua table).
@@ -829,24 +830,24 @@ vim.spell.check({str}) *vim.spell.check()*
VIM *vim.builtin*
-vim.api.{func}({...}) *vim.api*
+vim.api.{func}({...}) *vim.api*
Invokes Nvim |API| function {func} with arguments {...}.
Example: call the "nvim_get_current_line()" API function: >lua
print(tostring(vim.api.nvim_get_current_line()))
-vim.NIL *vim.NIL*
+vim.NIL *vim.NIL*
Special value representing NIL in |RPC| and |v:null| in Vimscript
conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
table representing a Dictionary or Array, because it is treated as
missing: `{"foo", nil}` is the same as `{"foo"}`.
-vim.type_idx *vim.type_idx*
+vim.type_idx *vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the values from
|vim.types| allows typing the empty table (it is unclear whether empty Lua
table represents empty list or empty array) and forcing integral numbers
to be |Float|. See |lua-special-tbl| for more details.
-vim.val_idx *vim.val_idx*
+vim.val_idx *vim.val_idx*
Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >lua
{
@@ -855,7 +856,7 @@ vim.val_idx *vim.val_id
}
< See also |vim.type_idx| and |lua-special-tbl|.
-vim.types *vim.types*
+vim.types *vim.types*
Table with possible values for |vim.type_idx|. Contains two sets of
key-value pairs: first maps possible values for |vim.type_idx| to
human-readable strings, second maps human-readable type names to values
@@ -884,6 +885,8 @@ Log levels are one of the values defined in `vim.log.levels`:
vim.log.levels.WARN
vim.log.levels.OFF
+
+
vim.empty_dict() *vim.empty_dict()*
Creates a special empty table (marked with a metatable), which Nvim
converts to an empty dictionary when translating Lua values to Vimscript
@@ -1137,8 +1140,9 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
• {fast_only} (`boolean?`) If true, only |api-fast| events will be
processed.
- Return: ~
- (`boolean, -1|-2?`)
+ Return (multiple): ~
+ (`boolean`)
+ (`-1|-2?`)
• If {callback} returns `true` during the {time}: `true, nil`
• If {callback} never returns `true` during the {time}: `false, -1`
• If {callback} is interrupted during the {time}: `false, -2`
@@ -1148,18 +1152,15 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
==============================================================================
LUA-VIMSCRIPT BRIDGE *lua-vimscript*
-
Nvim Lua provides an interface or "bridge" to Vimscript variables and
functions, and editor commands and options.
Objects passed over this bridge are COPIED (marshalled): there are no
-"references". |lua-guide-variables| For example, using `vim.fn.remove()`
-on a Lua list copies the list object to Vimscript and does NOT modify the
-Lua list: >lua
+"references". |lua-guide-variables| For example, using `vim.fn.remove()` on a
+Lua list copies the list object to Vimscript and does NOT modify the Lua list: >lua
local list = { 1, 2, 3 }
vim.fn.remove(list, 0)
vim.print(list) --> "{ 1, 2, 3 }"
-
<
vim.call({func}, {...}) *vim.call()*
@@ -1240,7 +1241,7 @@ vim.v *vim.v*
|v:| variables.
Invalid or unset key returns `nil`.
-` ` *lua-options*
+ *lua-options*
*lua-vim-options*
*lua-vim-set*
*lua-vim-setlocal*
@@ -1263,9 +1264,10 @@ window-scoped options. Note that this must NOT be confused with
|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
global value of a |global-local| option, see |:setglobal|.
-` ` *vim.opt_local*
- *vim.opt_global*
- *vim.opt*
+ *vim.opt_local*
+ *vim.opt_global*
+ *vim.opt*
+
A special interface |vim.opt| exists for conveniently interacting with list-
and map-style option from Lua: It allows accessing them as Lua tables and
@@ -1326,6 +1328,7 @@ In any of the above examples, to replicate the behavior |:setlocal|, use
`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
`vim.opt_global`.
+
Option:append({value}) *vim.opt:append()*
Append a value to string-style options. See |:set+=|
@@ -1478,7 +1481,7 @@ vim.wo *vim.wo*
==============================================================================
Lua module: vim *lua-vim*
-vim.cmd *vim.cmd()*
+vim.cmd({command}) *vim.cmd()*
Executes Vim script commands.
Note that `vim.cmd` can be indexed with a command name to return a
@@ -1552,7 +1555,7 @@ vim.deprecate({name}, {alternative}, {version}, {plugin}, {backtrace})
Return: ~
(`string?`) Deprecated message, or nil if no message was shown.
-vim.inspect *vim.inspect()*
+vim.inspect() *vim.inspect()*
Gets a human-readable representation of the given object.
Return: ~
@@ -1580,12 +1583,15 @@ vim.keycode({str}) *vim.keycode()*
See also: ~
• |nvim_replace_termcodes()|
-vim.lua_omnifunc({find_start}, {_}) *vim.lua_omnifunc()*
+vim.lua_omnifunc({find_start}) *vim.lua_omnifunc()*
Omnifunc for completing Lua values from the runtime Lua interpreter,
similar to the builtin completion for the `:lua` command.
Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer.
+ Parameters: ~
+ • {find_start} (`1|0`)
+
vim.notify({msg}, {level}, {opts}) *vim.notify()*
Displays a notification to the user.
@@ -1655,8 +1661,8 @@ vim.paste({lines}, {phase}) *vim.paste()*
• {lines} (`string[]`) |readfile()|-style list of lines to paste.
|channel-lines|
• {phase} (`-1|1|2|3`) -1: "non-streaming" paste: the call contains all
- lines. If paste is "streamed", `phase` indicates
- the stream state:
+ lines. If paste is "streamed", `phase` indicates the stream
+ state:
• 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once)
@@ -1674,6 +1680,9 @@ vim.print({...}) *vim.print()*
local hl_normal = vim.print(vim.api.nvim_get_hl(0, { name = 'Normal' }))
<
+ Parameters: ~
+ • {...} (`any`)
+
Return: ~
(`any`) given arguments.
@@ -1799,7 +1808,6 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
• signal: (integer)
• stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed
-
• kill (fun(signal: integer|string))
• write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to
close the stream.
@@ -1858,11 +1866,32 @@ vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
+Ringbuf:clear() *Ringbuf:clear()*
+ Clear all items
+
+Ringbuf:peek() *Ringbuf:peek()*
+ Returns the first unread item without removing it
+
+ Return: ~
+ (`any?`)
+
+Ringbuf:pop() *Ringbuf:pop()*
+ Removes and returns the first unread item
+
+ Return: ~
+ (`any?`)
+
+Ringbuf:push({item}) *Ringbuf:push()*
+ Adds an item, overriding the oldest item if the buffer is full.
+
+ Parameters: ~
+ • {item} (`any`)
+
vim.deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality
- Tables are compared recursively unless they both provide the `eq` metamethod.
- All other types are compared using the equality `==` operator.
+ Tables are compared recursively unless they both provide the `eq`
+ metamethod. All other types are compared using the equality `==` operator.
Parameters: ~
• {a} (`any`) First value
@@ -1999,12 +2028,12 @@ vim.list_slice({list}, {start}, {finish}) *vim.list_slice()*
(inclusive)
Parameters: ~
- • {list} (`list`) Table
+ • {list} (`any[]`) Table
• {start} (`integer?`) Start range of slice
• {finish} (`integer?`) End range of slice
Return: ~
- (`list`) Copy of table sliced from start to finish (inclusive)
+ (`any[]`) Copy of table sliced from start to finish (inclusive)
vim.pesc({s}) *vim.pesc()*
Escapes magic chars in |lua-patterns|.
@@ -2037,7 +2066,6 @@ vim.ringbuf({size}) *vim.ringbuf()*
<
Returns a Ringbuf instance with the following methods:
-
• |Ringbuf:push()|
• |Ringbuf:pop()|
• |Ringbuf:peek()|
@@ -2049,27 +2077,6 @@ vim.ringbuf({size}) *vim.ringbuf()*
Return: ~
(`table`)
-vim.Ringbuf:clear() *Ringbuf:clear()*
- Clear all items.
-
-vim.Ringbuf:peek() *Ringbuf:peek()*
- Returns the first unread item without removing it
-
- Return: ~
- (`any?`)
-
-vim.Ringbuf:pop() *Ringbuf:pop()*
- Removes and returns the first unread item
-
- Return: ~
- (`any?`)
-
-vim.Ringbuf:push({item}) *Ringbuf:push()*
- Adds an item, overriding the oldest item if the buffer is full.
-
- Parameters: ~
- • {item} (`any`)
-
vim.spairs({t}) *vim.spairs()*
Enumerates key-value pairs of a table, ordered by key.
@@ -2080,7 +2087,8 @@ vim.spairs({t}) *vim.spairs()*
(`function`) |for-in| iterator over sorted keys and their values
See also: ~
- • Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • Based on
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.split({s}, {sep}, {opts}) *vim.split()*
Splits a string at each instance of a separator and returns the result as
@@ -2171,8 +2179,8 @@ vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
Merges recursively two or more tables.
Parameters: ~
- • {behavior} (`string`) Decides what to do if a key is found in more
- than one map:
+ • {behavior} (`"error"|"keep"|"force"`) (string) Decides what to do if
+ a key is found in more than one map:
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
@@ -2209,7 +2217,7 @@ vim.tbl_filter({func}, {t}) *vim.tbl_filter()*
• {t} (`table`) Table
Return: ~
- (`table`) Table of filtered values
+ (`any[]`) Table of filtered values
vim.tbl_flatten({t}) *vim.tbl_flatten()*
Creates a copy of a list-like table such that any nested tables are
@@ -2222,7 +2230,8 @@ vim.tbl_flatten({t}) *vim.tbl_flatten()*
(`table`) Flattened copy of the given list-like table
See also: ~
- • From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • From
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_get({o}, {...}) *vim.tbl_get()*
Index into a table (first argument) via string keys passed as subsequent
@@ -2298,10 +2307,11 @@ vim.tbl_keys({t}) *vim.tbl_keys()*
• {t} (`table`) Table
Return: ~
- (`list`) List of keys
+ (`any[]`) List of keys
See also: ~
- • From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • From
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table.
@@ -2321,7 +2331,7 @@ vim.tbl_values({t}) *vim.tbl_values()*
• {t} (`table`) Table
Return: ~
- (`list`) List of values
+ (`any[]`) List of values
vim.trim({s}) *vim.trim()*
Trim whitespace (Lua pattern "%s") from both sides of a string.
@@ -2378,7 +2388,6 @@ vim.validate({opt}) *vim.validate()*
"string", "s", "number", "n", "boolean", "b", "function",
"f", "nil", "thread", "userdata") or list of them.
• optional: (optional) boolean, if true, `nil` is valid
-
2. (arg_value, fn, msg)
• arg_value: argument value
• fn: any function accepting one argument, returns true if
@@ -2422,7 +2431,7 @@ vim.loader.find({modname}, {opts}) *vim.loader.find()*
first one (defaults to `false`)
Return: ~
- (`list`) A list of results with the following properties:
+ (`table`) A list of results with the following properties:
• modpath: (string) the path to the module
• modname: (string) the name of the module
• stat: (table|nil) the fs_stat of the module path. Won't be returned
@@ -2632,9 +2641,9 @@ vim.filetype.add({filetypes}) *vim.filetype.add()*
['/etc/foo/config'] = 'toml',
},
pattern = {
- ['.*&zwj;/etc/foo/.*'] = 'fooscript',
+ ['.*/etc/foo/.*'] = 'fooscript',
-- Using an optional priority
- ['.*&zwj;/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
+ ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
-- A pattern containing an environment variable
['${XDG_CONFIG_HOME}/foo/git'] = 'git',
['README.(%a+)$'] = function(path, bufnr, ext)
@@ -2756,9 +2765,11 @@ vim.keymap.del({modes}, {lhs}, {opts}) *vim.keymap.del()*
<
Parameters: ~
- • {opts} (`table?`) A table of optional arguments:
- • "buffer": (integer|boolean) Remove a mapping from the given
- buffer. When `0` or `true`, use the current buffer.
+ • {modes} (`string|string[]`)
+ • {lhs} (`string`)
+ • {opts} (`table?`) A table of optional arguments:
+ • "buffer": (integer|boolean) Remove a mapping from the given
+ buffer. When `0` or `true`, use the current buffer.
See also: ~
• |vim.keymap.set()|
@@ -2789,7 +2800,6 @@ vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
• Same as |nvim_set_keymap()| {opts}, except:
• "replace_keycodes" defaults to `true` if "expr" is `true`.
• "noremap": inverse of "remap" (see below).
-
• Also accepts:
• "buffer": (integer|boolean) Creates buffer-local mapping,
`0` or `true` for current buffer.
@@ -2971,7 +2981,8 @@ Lua module: vim.glob *vim.glob*
vim.glob.to_lpeg({pattern}) *vim.glob.to_lpeg()*
Parses a raw glob into an |lua-lpeg| pattern.
- This uses glob semantics from LSP 3.17.0: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
+ This uses glob semantics from LSP 3.17.0:
+ https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
Glob patterns can have the following syntax:
• `*` to match one or more characters in a path segment
@@ -3008,6 +3019,35 @@ The LPeg library for parsing expression grammars is included as `vim.lpeg`
In addition, its regex-like interface is available as |vim.re|
(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+
+
+Pattern:match({subject}, {init}) *Pattern:match()*
+ Matches the given `pattern` against the `subject` string. If the match
+ succeeds, returns the index in the subject of the first character after
+ the match, or the captured values (if the pattern captured any value). An
+ optional numeric argument `init` makes the match start at that position in
+ the subject string. As usual in Lua libraries, a negative value counts
+ from the end. Unlike typical pattern-matching functions, `match` works
+ only in anchored mode; that is, it tries to match the pattern with a
+ prefix of the given subject string (at position `init`), not with an
+ arbitrary substring of the subject. So, if we want to find a pattern
+ anywhere in a string, we must either write a loop in Lua or write a
+ pattern that matches anywhere.
+
+ Example: >lua
+ local pattern = lpeg.R("az") ^ 1 * -1
+ assert(pattern:match("hello") == 6)
+ assert(lpeg.match(pattern, "hello") == 6)
+ assert(pattern:match("1 hello") == nil)
+<
+
+ Parameters: ~
+ • {subject} (`string`)
+ • {init} (`integer?`)
+
+ Return: ~
+ (`integer|vim.lpeg.Capture?`)
+
vim.lpeg.B({pattern}) *vim.lpeg.B()*
Returns a pattern that matches only if the input string at the current
position is preceded by `patt`. Pattern `patt` must match only strings
@@ -3047,7 +3087,8 @@ vim.lpeg.C({patt}) *vim.lpeg.C()*
vim.lpeg.Carg({n}) *vim.lpeg.Carg()*
Creates an argument capture. This pattern matches the empty string and
- produces the value given as the nth extra argument given in the call to `lpeg.match` .
+ produces the value given as the nth extra argument given in the call to
+ `lpeg.match`.
Parameters: ~
• {n} (`integer`)
@@ -3192,11 +3233,40 @@ vim.lpeg.Ct({patt}) *vim.lpeg.Ct()*
the group name as its key. The captured value is only the table.
Parameters: ~
- • {patt} (vim.lpeg.Pattern |' `) @return (` vim.lpeg.Capture`)
+ • {patt} (`vim.lpeg.Pattern|''`)
-vim.lpeg.lpeg *vim.lpeg()*
- LPeg is a new pattern-matching library for Lua, based on Parsing Expression
- Grammars (PEGs).
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.locale({tab}) *vim.lpeg.locale()*
+ Returns a table with patterns for matching some character classes
+ according to the current locale. The table has fields named `alnum`,
+ `alpha`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`,
+ `upper`, and `xdigit`, each one containing a correspondent pattern. Each
+ pattern matches any single character that belongs to its class. If called
+ with an argument `table`, then it creates those fields inside the given
+ table and returns that table.
+
+ Example: >lua
+ lpeg.locale(lpeg)
+ local space = lpeg.space^0
+ local name = lpeg.C(lpeg.alpha^1) * space
+ local sep = lpeg.S(",;") * space
+ local pair = lpeg.Cg(name * "=" * space * name) * sep^-1
+ local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset)
+ local t = list:match("a=b, c = hi; next = pi")
+ assert(t.a == 'b')
+ assert(t.c == 'hi')
+ assert(t.next == 'pi')
+ local locale = lpeg.locale()
+ assert(type(locale.digit) == 'userdata')
+<
+
+ Parameters: ~
+ • {tab} (`table?`)
+
+ Return: ~
+ (`vim.lpeg.Locale`)
vim.lpeg.match({pattern}, {subject}, {init}) *vim.lpeg.match()*
Matches the given `pattern` against the `subject` string. If the match
@@ -3252,33 +3322,6 @@ vim.lpeg.P({value}) *vim.lpeg.P()*
Return: ~
(`vim.lpeg.Pattern`)
-vim.lpeg.Pattern:match({subject}, {init}) *Pattern:match()*
- Matches the given `pattern` against the `subject` string. If the match
- succeeds, returns the index in the subject of the first character after
- the match, or the captured values (if the pattern captured any value). An
- optional numeric argument `init` makes the match start at that position in
- the subject string. As usual in Lua libraries, a negative value counts
- from the end. Unlike typical pattern-matching functions, `match` works
- only in anchored mode; that is, it tries to match the pattern with a
- prefix of the given subject string (at position `init`), not with an
- arbitrary substring of the subject. So, if we want to find a pattern
- anywhere in a string, we must either write a loop in Lua or write a
- pattern that matches anywhere.
-
- Example: >lua
- local pattern = lpeg.R("az") ^ 1 * -1
- assert(pattern:match("hello") == 6)
- assert(lpeg.match(pattern, "hello") == 6)
- assert(pattern:match("1 hello") == nil)
-<
-
- Parameters: ~
- • {subject} (`string`)
- • {init} (`integer?`)
-
- Return: ~
- (`integer|vim.lpeg.Capture?`)
-
vim.lpeg.R({...}) *vim.lpeg.R()*
Returns a pattern that matches any single character belonging to one of
the given ranges. Each `range` is a string `xy` of length 2, representing
@@ -3300,10 +3343,10 @@ vim.lpeg.R({...}) *vim.lpeg.R()*
vim.lpeg.S({string}) *vim.lpeg.S()*
Returns a pattern that matches any single character that appears in the
given string (the `S` stands for Set). As an example, the pattern
- `lpeg.S("+-*&zwj;/")` matches any arithmetic operator. Note that, if `s`
- is a character (that is, a string of length 1), then `lpeg.P(s)` is
- equivalent to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also
- that both `lpeg.S("")` and `lpeg.R()` are patterns that always fail.
+ `lpeg.S("+-*/")` matches any arithmetic operator. Note that, if `s` is a
+ character (that is, a string of length 1), then `lpeg.P(s)` is equivalent
+ to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also that both
+ `lpeg.S("")` and `lpeg.R()` are patterns that always fail.
Parameters: ~
• {string} (`string`)
@@ -3327,6 +3370,9 @@ vim.lpeg.type({value}) *vim.lpeg.type()*
Returns the string `"pattern"` if the given value is a pattern, otherwise
`nil`.
+ Parameters: ~
+ • {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
+
Return: ~
(`"pattern"?`)
@@ -3357,13 +3403,13 @@ vim.lpeg.version() *vim.lpeg.version()*
==============================================================================
VIM.RE *vim.re*
-
-The `vim.re` module provides a conventional regex-like syntax for pattern usage
-within LPeg |vim.lpeg|.
+The `vim.re` module provides a conventional regex-like syntax for pattern
+usage within LPeg |vim.lpeg|.
See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
documentation including regex syntax and more concrete examples.
+
vim.re.compile({string}, {defs}) *vim.re.compile()*
Compiles the given {string} and returns an equivalent LPeg pattern. The
given string may define either an expression or a grammar. The optional
@@ -3421,28 +3467,19 @@ vim.re.match({subject}, {pattern}, {init}) *vim.re.match()*
See also: ~
• vim.lpeg.match()
+vim.re.updatelocale() *vim.re.updatelocale()*
+ Updates the pre-defined character classes to the current locale.
+
==============================================================================
VIM.REGEX *vim.regex*
+Vim regexes can be used directly from Lua. Currently they only allow matching
+within a single line.
-Vim regexes can be used directly from Lua. Currently they only allow
-matching within a single line.
-
-
-vim.regex({re}) *vim.regex()*
- Parse the Vim regex {re} and return a regex object. Regexes are "magic"
- and case-sensitive by default, regardless of 'magic' and 'ignorecase'.
- They can be controlled with flags, see |/magic| and |/ignorecase|.
-
- Parameters: ~
- • {re} (`string`)
-
- Return: ~
- (`vim.regex`)
*regex:match_line()*
-vim.regex:match_line({bufnr}, {line_idx}, {start}, {end_})
+regex:match_line({bufnr}, {line_idx}, {start}, {end_})
Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and {end}
are supplied, match only this byte index range. Otherwise see
|regex:match_str()|. If {start} is used, then the returned byte indices
@@ -3454,16 +3491,28 @@ vim.regex:match_line({bufnr}, {line_idx}, {start}, {end_})
• {start} (`integer?`)
• {end_} (`integer?`)
-vim.regex:match_str({str}) *regex:match_str()*
+regex:match_str({str}) *regex:match_str()*
Match the string against the regex. If the string should match the regex
- precisely, surround the regex with `^` and `$` . If there was a match, the
+ precisely, surround the regex with `^` and `$`. If there was a match, the
byte indices for the beginning and end of the match are returned. When
- there is no match, `nil` is returned. Because any integer is "truthy", `regex:match_str()` can
- be directly used as a condition in an if-statement.
+ there is no match, `nil` is returned. Because any integer is "truthy",
+ `regex:match_str()` can be directly used as a condition in an
+ if-statement.
Parameters: ~
• {str} (`string`)
+vim.regex({re}) *vim.regex()*
+ Parse the Vim regex {re} and return a regex object. Regexes are "magic"
+ and case-sensitive by default, regardless of 'magic' and 'ignorecase'.
+ They can be controlled with flags, see |/magic| and |/ignorecase|.
+
+ Parameters: ~
+ • {re} (`string`)
+
+ Return: ~
+ (`vim.regex`)
+
==============================================================================
Lua module: vim.secure *vim.secure*
@@ -3508,29 +3557,23 @@ vim.secure.trust({opts}) *vim.secure.trust()*
==============================================================================
Lua module: vim.version *vim.version*
-
-The `vim.version` module provides functions for comparing versions and
-ranges conforming to the
-
-https://semver.org
-
-spec. Plugins, and plugin managers, can use this to check available tools
-and dependencies on the current system.
+The `vim.version` module provides functions for comparing versions and ranges
+conforming to the https://semver.org spec. Plugins, and plugin managers, can
+use this to check available tools and dependencies on the current system.
Example: >lua
local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
if vim.version.gt(v, {3, 2, 0}) then
-- ...
end
-
<
*vim.version()* returns the version of the current Nvim process.
-VERSION RANGE SPEC *version-range*
+VERSION RANGE SPEC *version-range*
-A version "range spec" defines a semantic version range which can be
-tested against a version, using |vim.version.range()|.
+A version "range spec" defines a semantic version range which can be tested
+against a version, using |vim.version.range()|.
Supported range specs are shown in the following table. Note: suffixed
versions (1.2.3-rc1) are not matched. >
@@ -3561,9 +3604,9 @@ versions (1.2.3-rc1) are not matched. >
Partial left: missing pieces treated as 0 (1.2 => 1.2.0).
1.2 - 2.3.0 is 1.2.0 - 2.3.0
-
<
+
vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parses and compares two version objects (the result of
|vim.version.parse()|, or specified literally as a `{major, minor, patch}`
@@ -3586,14 +3629,14 @@ vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parameters: ~
• {v1} (`Version|number[]|string`) Version object.
- • {v2} (`Version|number[]|string`) Version to compare with `v1` .
+ • {v2} (`Version|number[]|string`) Version to compare with `v1`.
Return: ~
(`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
vim.version.eq({v1}, {v2}) *vim.version.eq()*
- Returns `true` if the given versions are equal. See |vim.version.cmp()| for
- usage.
+ Returns `true` if the given versions are equal. See |vim.version.cmp()|
+ for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
@@ -3603,7 +3646,7 @@ vim.version.eq({v1}, {v2}) *vim.version.eq()*
(`boolean`)
vim.version.ge({v1}, {v2}) *vim.version.ge()*
- Returns `true` if `v1 >= v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
@@ -3613,7 +3656,7 @@ vim.version.ge({v1}, {v2}) *vim.version.ge()*
(`boolean`)
vim.version.gt({v1}, {v2}) *vim.version.gt()*
- Returns `true` if `v1 > v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
@@ -3632,7 +3675,7 @@ vim.version.last({versions}) *vim.version.last()*
(`Version?`)
vim.version.le({v1}, {v2}) *vim.version.le()*
- Returns `true` if `v1 <= v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
@@ -3642,7 +3685,7 @@ vim.version.le({v1}, {v2}) *vim.version.le()*
(`boolean`)
vim.version.lt({v1}, {v2}) *vim.version.lt()*
- Returns `true` if `v1 < v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
Parameters: ~
• {v1} (`Version|number[]|string`)
@@ -3671,7 +3714,7 @@ vim.version.parse({version}, {opts}) *vim.version.parse()*
invalid.
See also: ~
- • # https://semver.org/spec/v2.0.0.html
+ • https://semver.org/spec/v2.0.0.html
vim.version.range({spec}) *vim.version.range()*
Parses a semver |version-range| "spec" and returns a range object: >
@@ -3702,35 +3745,30 @@ vim.version.range({spec}) *vim.version.range()*
• {spec} (`string`) Version range "spec"
See also: ~
- • # https://github.com/npm/node-semver#ranges
+ • https://github.com/npm/node-semver#ranges
==============================================================================
Lua module: vim.iter *vim.iter*
-
*vim.iter()* is an interface for |iterable|s: it wraps a table or function
argument into an *Iter* object with methods (such as |Iter:filter()| and
-|Iter:map()|) that transform the underlying source data. These methods can
-be chained to create iterator "pipelines": the output of each pipeline
-stage is input to the next stage. The first stage depends on the type
-passed to `vim.iter()`:
-
+|Iter:map()|) that transform the underlying source data. These methods can be
+chained to create iterator "pipelines": the output of each pipeline stage is
+input to the next stage. The first stage depends on the type passed to
+`vim.iter()`:
• List tables (arrays, |lua-list|) yield only the value of each element.
• Use |Iter:enumerate()| to also pass the index to the next stage.
• Or initialize with ipairs(): `vim.iter(ipairs(…))`.
-
-• Non-list tables (|lua-dict|) yield both the key and value of each
- element.
-• Function |iterator|s yield all values returned by the underlying
- function.
+• Non-list tables (|lua-dict|) yield both the key and value of each element.
+• Function |iterator|s yield all values returned by the underlying function.
• Tables with a |__call()| metamethod are treated as function iterators.
-The iterator pipeline terminates when the underlying |iterable| is
-exhausted (for function iterators this means it returned nil).
+The iterator pipeline terminates when the underlying |iterable| is exhausted
+(for function iterators this means it returned nil).
-Note: `vim.iter()` scans table input to decide if it is a list or a dict;
-to avoid this cost you can wrap the table with an iterator e.g.
+Note: `vim.iter()` scans table input to decide if it is a list or a dict; to
+avoid this cost you can wrap the table with an iterator e.g.
`vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator|
operations such as |Iter:rev()|).
@@ -3771,13 +3809,13 @@ Examples: >lua
rb:push("b")
vim.iter(rb):totable()
-- { "a", "b" }
-
<
In addition to the |vim.iter()| function, the |vim.iter| module provides
convenience functions like |vim.iter.filter()| and |vim.iter.totable()|.
-filter({f}, {src}, {...}) *vim.iter.filter()*
+
+filter({f}, {src}) *vim.iter.filter()*
Filters a table or other |iterable|. >lua
-- Equivalent to:
vim.iter(src):filter(f):totable()
@@ -3839,11 +3877,11 @@ Iter:enumerate() *Iter:enumerate()*
Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next()
- -- 1 'a'
+ -- 1 'a'
it:next()
- -- 2 'b'
+ -- 2 'b'
it:next()
- -- 3 'c'
+ -- 3 'c'
<
Return: ~
@@ -3884,6 +3922,9 @@ Iter:find({f}) *Iter:find()*
-- 12
<
+ Parameters: ~
+ • {f} (`any`)
+
Return: ~
(`any`)
@@ -3926,7 +3967,7 @@ Iter:fold({init}, {f}) *Iter:fold()*
Parameters: ~
• {init} (`any`) Initial value of the accumulator.
- • {f} (`fun(acc:any, ...):any`) Accumulation function.
+ • {f} (`fun(acc:A, ...):A`) Accumulation function.
Return: ~
(`any`)
@@ -4105,11 +4146,14 @@ Iter:rfind({f}) *Iter:rfind()*
Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1)
- -- 5 1
+ -- 5 1
it:rfind(1)
- -- 1 1
+ -- 1 1
<
+ Parameters: ~
+ • {f} (`any`)
+
Return: ~
(`any`)
@@ -4205,7 +4249,7 @@ Iter:totable() *Iter:totable()*
Return: ~
(`table`)
-map({f}, {src}, {...}) *vim.iter.map()*
+map({f}, {src}) *vim.iter.map()*
Maps a table or other |iterable|. >lua
-- Equivalent to:
vim.iter(src):map(f):totable()
@@ -4223,7 +4267,7 @@ map({f}, {src}, {...}) *vim.iter.map()*
See also: ~
• |Iter:map()|
-totable({f}, {...}) *vim.iter.totable()*
+totable({f}) *vim.iter.totable()*
Collects an |iterable| into a table. >lua
-- Equivalent to:
vim.iter(f):totable()
@@ -4249,8 +4293,9 @@ vim.snippet.exit() *vim.snippet.exit()*
Exits the current snippet.
vim.snippet.expand({input}) *vim.snippet.expand()*
- Expands the given snippet text. Refer to https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax for
- the specification of valid input.
+ Expands the given snippet text. Refer to
+ https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax
+ for the specification of valid input.
Tabstops are highlighted with hl-SnippetTabstop.
@@ -4317,4 +4362,5 @@ vim.text.hexencode({str}) *vim.text.hexencode()*
Return: ~
(`string`) Hex encoded string
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 8a3770bf27..09c086b7f7 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -933,6 +933,7 @@ get_filetypes({lang}) *vim.treesitter.language.get_filetypes()*
(`string[]`) filetypes
get_lang({filetype}) *vim.treesitter.language.get_lang()*
+
Parameters: ~
• {filetype} (`string`)
@@ -1056,14 +1057,13 @@ lint({buf}, {opts}) *vim.treesitter.query.lint()*
Use |treesitter-parsers| in runtimepath to check the query file in {buf}
for errors:
-
• verify that used nodes are valid identifiers in the grammar.
• verify that predicates and directives are valid.
• verify that top-level s-expressions are valid.
The found diagnostics are reported using |diagnostic-api|. By default, the
parser used for verification is determined by the containing folder of the
- query file, e.g., if the path ends in `/lua/highlights.scm` , the parser
+ query file, e.g., if the path ends in `/lua/highlights.scm`, the parser
for the `lua` language will be used.
Parameters: ~
@@ -1093,6 +1093,10 @@ omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()*
vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
<
+ Parameters: ~
+ • {findstart} (`0|1`)
+ • {base} (`string`)
+
parse({lang}, {query}) *vim.treesitter.query.parse()*
Parse {query} as a string. (If the query is in a file, the caller should
read the contents into a string before calling).
@@ -1218,42 +1222,36 @@ set({lang}, {query_name}, {text}) *vim.treesitter.query.set()*
==============================================================================
Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree*
+A *LanguageTree* contains a tree of parsers: the root treesitter parser for
+{lang} and any "injected" language parsers, which themselves may inject other
+languages, recursively. For example a Lua buffer containing some Vimscript
+commands needs multiple parsers to fully understand its contents.
-A *LanguageTree* contains a tree of parsers: the root treesitter parser
-for {lang} and any "injected" language parsers, which themselves may
-inject other languages, recursively. For example a Lua buffer containing
-some Vimscript commands needs multiple parsers to fully understand its
-contents.
-
-To create a LanguageTree (parser object) for a given buffer and language,
-use: >lua
+To create a LanguageTree (parser object) for a given buffer and language, use: >lua
local parser = vim.treesitter.get_parser(bufnr, lang)
-
<
-(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'.
-Note: currently the parser is retained for the lifetime of a buffer but
-this may change; a plugin should keep a reference to the parser object if
-it wants incremental updates.
+(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. Note:
+currently the parser is retained for the lifetime of a buffer but this may
+change; a plugin should keep a reference to the parser object if it wants
+incremental updates.
Whenever you need to access the current syntax tree, parse the buffer: >lua
local tree = parser:parse({ start_row, end_row })
-
<
-This returns a table of immutable |treesitter-tree| objects representing
-the current state of the buffer. When the plugin wants to access the state
-after a (possible) edit it must call `parse()` again. If the buffer wasn't
-edited, the same tree will be returned again without extra work. If the
-buffer was parsed before, incremental parsing will be done of the changed
-parts.
+This returns a table of immutable |treesitter-tree| objects representing the
+current state of the buffer. When the plugin wants to access the state after a
+(possible) edit it must call `parse()` again. If the buffer wasn't edited, the
+same tree will be returned again without extra work. If the buffer was parsed
+before, incremental parsing will be done of the changed parts.
+
+Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback,
+you must call |vim.treesitter.get_parser()| before you register your callback.
+But preferably parsing shouldn't be done directly in the change callback
+anyway as they will be very frequent. Rather a plugin that does any kind of
+analysis on a tree should use a timer to throttle too frequent updates.
-Note: To use the parser directly inside a |nvim_buf_attach()| Lua
-callback, you must call |vim.treesitter.get_parser()| before you register
-your callback. But preferably parsing shouldn't be done directly in the
-change callback anyway as they will be very frequent. Rather a plugin that
-does any kind of analysis on a tree should use a timer to throttle too
-frequent updates.
LanguageTree:children() *LanguageTree:children()*
Returns a map of language to child tree.
@@ -1284,7 +1282,7 @@ LanguageTree:for_each_tree({fn}) *LanguageTree:for_each_tree()*
• {fn} (`fun(tree: TSTree, ltree: LanguageTree)`)
LanguageTree:included_regions() *LanguageTree:included_regions()*
- Gets the set of included regions managed by this LanguageTree . This can be
+ Gets the set of included regions managed by this LanguageTree. This can be
different from the regions set by injection query, because a partial
|LanguageTree:parse()| drops the regions outside the requested range.
@@ -1405,4 +1403,5 @@ LanguageTree:trees() *LanguageTree:trees()*
Return: ~
(`table<integer, TSTree>`)
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index c5a6e65e86..4e39abb2be 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -127,10 +127,10 @@ vim.log = {
--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
--- be called in |api-fast|.
--- - SystemCompleted is an object with the fields:
---- - code: (integer)
---- - signal: (integer)
---- - stdout: (string), nil if stdout argument is passed
---- - stderr: (string), nil if stderr argument is passed
+--- - code: (integer)
+--- - signal: (integer)
+--- - stdout: (string), nil if stdout argument is passed
+--- - stderr: (string), nil if stderr argument is passed
--- - kill (fun(signal: integer|string))
--- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream.
--- - is_closing (fun(): boolean)
@@ -706,8 +706,8 @@ end
--- Generates a list of possible completions for the string.
--- String has the pattern.
---
---- 1. Can we get it to just return things in the global namespace with that name prefix
---- 2. Can we get it to return things from global namespace even with `print(` in front.
+--- 1. Can we get it to just return things in the global namespace with that name prefix
+--- 2. Can we get it to return things from global namespace even with `print(` in front.
---
--- @param pat string
function vim._expand_pat(pat, env)
@@ -885,6 +885,7 @@ do
--- similar to the builtin completion for the `:lua` command.
---
--- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer.
+ --- @param find_start 1|0
function vim.lua_omnifunc(find_start, _)
if find_start == 1 then
local line = vim.api.nvim_get_current_line()
@@ -914,6 +915,7 @@ end
---
--- @see |vim.inspect()|
--- @see |:=|
+--- @param ... any
--- @return any # given arguments.
function vim.print(...)
if vim.in_fast_event() then
diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua
index 3f7b9d2c23..9a073c32c4 100644
--- a/runtime/lua/vim/_inspector.lua
+++ b/runtime/lua/vim/_inspector.lua
@@ -17,7 +17,7 @@ local defaults = {
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table|nil) a table with key-value pairs to filter the items
+---@param filter? InspectorFilter (table) a table with key-value pairs to filter the items
--- - syntax (boolean): include syntax based highlight groups (defaults to true)
--- - treesitter (boolean): include treesitter based highlight groups (defaults to true)
--- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
@@ -139,7 +139,7 @@ end
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table|nil) see |vim.inspect_pos()|
+---@param filter? InspectorFilter (table) see |vim.inspect_pos()|
function vim.show_pos(bufnr, row, col, filter)
local items = vim.inspect_pos(bufnr, row, col, filter)
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index aee866f324..d2f624fd97 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -38,6 +38,7 @@ function vim.api.nvim__get_runtime(pat, all, opts) end
--- @private
--- Returns object given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -47,6 +48,7 @@ function vim.api.nvim__id(obj) end
--- @private
--- Returns array given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -56,6 +58,7 @@ function vim.api.nvim__id_array(arr) end
--- @private
--- Returns dictionary given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -65,6 +68,7 @@ function vim.api.nvim__id_dictionary(dct) end
--- @private
--- Returns floating-point value given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -108,17 +112,20 @@ function vim.api.nvim__stats() end
function vim.api.nvim__unpack(str) end
--- Adds a highlight to buffer.
+---
--- Useful for plugins that dynamically generate highlights to a buffer (like
--- a semantic highlighter or linter). The function adds a single highlight to
--- a buffer. Unlike `matchaddpos()` highlights follow changes to line
--- numbering (as lines are inserted/removed above the highlighted line), like
--- signs and marks do.
+---
--- Namespaces are used for batch deletion/updating of a set of highlights. To
--- create a namespace, use `nvim_create_namespace()` which returns a
--- namespace id. Pass it in to this function as `ns_id` to add highlights to
--- the namespace. All highlights in the same namespace can then be cleared
--- with single call to `nvim_buf_clear_namespace()`. If the highlight never
--- will be deleted by an API call, pass `ns_id = -1`.
+---
--- As a shorthand, `ns_id = 0` can be used to create a new namespace for the
--- highlight, the allocated id is then returned. If `hl_group` is the empty
--- string no highlight is added, but a new `ns_id` is still returned. This is
@@ -131,11 +138,12 @@ function vim.api.nvim__unpack(str) end
--- @param line integer Line to highlight (zero-indexed)
--- @param col_start integer Start of (byte-indexed) column range to highlight
--- @param col_end integer End of (byte-indexed) column range to highlight, or -1 to
---- highlight to end of line
+--- highlight to end of line
--- @return integer
function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) end
--- Activates buffer-update events on a channel, or as Lua callbacks.
+---
--- Example (Lua): capture buffer updates in a global `events` variable (use
--- "vim.print(events)" to see its contents):
---
@@ -148,6 +156,7 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start
--- })
--- ```
---
+---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param send_buffer boolean True if the initial notification should contain the
--- whole buffer: first notification will be
@@ -155,77 +164,70 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start
--- will be `nvim_buf_changedtick_event`. Not for Lua
--- callbacks.
--- @param opts vim.api.keyset.buf_attach Optional parameters.
---- • on_lines: Lua callback invoked on change. Return a
---- truthy value (not `false` or `nil`)
---- to detach. Args:
---- • the string "lines"
---- • buffer handle
---- • b:changedtick
---- • first line that changed (zero-indexed)
---- • last line that was changed
---- • last line in the updated range
---- • byte count of previous contents
---- • deleted_codepoints (if `utf_sizes` is true)
---- • deleted_codeunits (if `utf_sizes` is true)
----
---- • on_bytes: Lua callback invoked on change. This
---- callback receives more granular information about the
---- change compared to on_lines. Return a truthy value
---- (not `false` or `nil`) to
---- detach. Args:
---- • the string "bytes"
---- • buffer handle
---- • b:changedtick
---- • start row of the changed text (zero-indexed)
---- • start column of the changed text
---- • byte offset of the changed text (from the start of
---- the buffer)
---- • old end row of the changed text (offset from start
---- row)
---- • old end column of the changed text (if old end row
---- = 0, offset from start column)
---- • old end byte length of the changed text
---- • new end row of the changed text (offset from start
---- row)
---- • new end column of the changed text (if new end row
---- = 0, offset from start column)
---- • new end byte length of the changed text
----
---- • on_changedtick: Lua callback invoked on changedtick
---- increment without text change. Args:
---- • the string "changedtick"
---- • buffer handle
---- • b:changedtick
----
---- • on_detach: Lua callback invoked on detach. Args:
---- • the string "detach"
---- • buffer handle
----
---- • on_reload: Lua callback invoked on reload. The entire
---- buffer content should be considered changed. Args:
---- • the string "reload"
---- • buffer handle
----
---- • utf_sizes: include UTF-32 and UTF-16 size of the
---- replaced region, as args to `on_lines`.
---- • preview: also attach to command preview (i.e.
---- 'inccommand') events.
+--- • on_lines: Lua callback invoked on change. Return a truthy
+--- value (not `false` or `nil`) to detach. Args:
+--- • the string "lines"
+--- • buffer handle
+--- • b:changedtick
+--- • first line that changed (zero-indexed)
+--- • last line that was changed
+--- • last line in the updated range
+--- • byte count of previous contents
+--- • deleted_codepoints (if `utf_sizes` is true)
+--- • deleted_codeunits (if `utf_sizes` is true)
+--- • on_bytes: Lua callback invoked on change. This callback
+--- receives more granular information about the change compared
+--- to on_lines. Return a truthy value (not `false` or `nil`) to
+--- detach. Args:
+--- • the string "bytes"
+--- • buffer handle
+--- • b:changedtick
+--- • start row of the changed text (zero-indexed)
+--- • start column of the changed text
+--- • byte offset of the changed text (from the start of the
+--- buffer)
+--- • old end row of the changed text (offset from start row)
+--- • old end column of the changed text (if old end row = 0,
+--- offset from start column)
+--- • old end byte length of the changed text
+--- • new end row of the changed text (offset from start row)
+--- • new end column of the changed text (if new end row = 0,
+--- offset from start column)
+--- • new end byte length of the changed text
+--- • on_changedtick: Lua callback invoked on changedtick
+--- increment without text change. Args:
+--- • the string "changedtick"
+--- • buffer handle
+--- • b:changedtick
+--- • on_detach: Lua callback invoked on detach. Args:
+--- • the string "detach"
+--- • buffer handle
+--- • on_reload: Lua callback invoked on reload. The entire buffer
+--- content should be considered changed. Args:
+--- • the string "reload"
+--- • buffer handle
+--- • utf_sizes: include UTF-32 and UTF-16 size of the replaced
+--- region, as args to `on_lines`.
+--- • preview: also attach to command preview (i.e. 'inccommand')
+--- events.
--- @return boolean
function vim.api.nvim_buf_attach(buffer, send_buffer, opts) end
--- call a function with buffer as temporary current buffer
+---
--- This temporarily switches current buffer to "buffer". If the current
--- window already shows "buffer", the window is not switched If a window
--- inside the current tabpage (including a float) already shows the buffer
--- One of these windows will be set as current window temporarily. Otherwise
--- a temporary scratch window (called the "autocmd window" for historical
--- reasons) will be used.
+---
--- This is useful e.g. to call Vimscript functions that only work with the
--- current buffer/window currently, like `termopen()`.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param fun function Function to call inside the buffer (currently Lua callable
---- only)
+--- only)
--- @return any
function vim.api.nvim_buf_call(buffer, fun) end
@@ -238,14 +240,15 @@ function vim.api.nvim_buf_clear_highlight(buffer, ns_id, line_start, line_end) e
--- Clears `namespace`d objects (highlights, `extmarks`, virtual text) from a
--- region.
+---
--- Lines are 0-indexed. `api-indexing` To clear the namespace in the entire
--- buffer, specify line_start=0 and line_end=-1.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param ns_id integer Namespace to clear, or -1 to clear all namespaces.
--- @param line_start integer Start of range of lines to clear
---- @param line_end integer End of range of lines to clear (exclusive) or -1 to
---- clear to end of buffer.
+--- @param line_end integer End of range of lines to clear (exclusive) or -1 to clear
+--- to end of buffer.
function vim.api.nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) end
--- Creates a buffer-local command `user-commands`.
@@ -279,6 +282,7 @@ function vim.api.nvim_buf_del_keymap(buffer, mode, lhs) end
function vim.api.nvim_buf_del_mark(buffer, name) end
--- Delete a buffer-local user-defined command.
+---
--- Only commands created with `:command-buffer` or
--- `nvim_buf_create_user_command()` can be deleted with this function.
---
@@ -296,8 +300,8 @@ function vim.api.nvim_buf_del_var(buffer, name) end
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param opts vim.api.keyset.buf_delete Optional parameters. Keys:
---- • force: Force deletion and ignore unsaved changes.
---- • unload: Unloaded only, do not delete. See `:bunload`
+--- • force: Force deletion and ignore unsaved changes.
+--- • unload: Unloaded only, do not delete. See `:bunload`
function vim.api.nvim_buf_delete(buffer, opts) end
--- Gets a changed tick of a buffer
@@ -319,14 +323,15 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end
--- @param ns_id integer Namespace id from `nvim_create_namespace()`
--- @param id integer Extmark id
--- @param opts vim.api.keyset.get_extmark Optional parameters. Keys:
---- • details: Whether to include the details dict
---- • hl_name: Whether to include highlight group name instead
---- of id, true if omitted
+--- • details: Whether to include the details dict
+--- • hl_name: Whether to include highlight group name instead of
+--- id, true if omitted
--- @return vim.api.keyset.get_extmark_item
function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
--- Gets `extmarks` in "traversal order" from a `charwise` region defined by
--- buffer positions (inclusive, 0-indexed `api-indexing`).
+---
--- Region can be given as (row,col) tuples, or valid extmark ids (whose
--- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
--- respectively, thus the following are equivalent:
@@ -338,12 +343,15 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
---
--- If `end` is less than `start`, traversal works backwards. (Useful with
--- `limit`, to get the first marks prior to a given position.)
+---
--- Note: when using extmark ranges (marks with a end_row/end_col position)
--- the `overlap` option might be useful. Otherwise only the start position of
--- an extmark will be considered.
+---
--- Note: legacy signs placed through the `:sign` commands are implemented as
--- extmarks and will show up here. Their details array will contain a
--- `sign_name` field.
+---
--- Example:
---
--- ```lua
@@ -361,23 +369,23 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
--- vim.print(ms)
--- ```
---
+---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param ns_id integer Namespace id from `nvim_create_namespace()` or -1 for all
---- namespaces
+--- namespaces
--- @param start any Start of range: a 0-indexed (row, col) or valid extmark id
---- (whose position defines the bound). `api-indexing`
+--- (whose position defines the bound). `api-indexing`
--- @param end_ any End of range (inclusive): a 0-indexed (row, col) or valid
---- extmark id (whose position defines the bound).
---- `api-indexing`
+--- extmark id (whose position defines the bound). `api-indexing`
--- @param opts vim.api.keyset.get_extmarks Optional parameters. Keys:
---- • limit: Maximum number of marks to return
---- • details: Whether to include the details dict
---- • hl_name: Whether to include highlight group name instead
---- of id, true if omitted
---- • overlap: Also include marks which overlap the range, even
---- if their start position is less than `start`
---- • type: Filter marks by type: "highlight", "sign",
---- "virt_text" and "virt_lines"
+--- • limit: Maximum number of marks to return
+--- • details: Whether to include the details dict
+--- • hl_name: Whether to include highlight group name instead of
+--- id, true if omitted
+--- • overlap: Also include marks which overlap the range, even if
+--- their start position is less than `start`
+--- • type: Filter marks by type: "highlight", "sign", "virt_text"
+--- and "virt_lines"
--- @return vim.api.keyset.get_extmark_item[]
function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end
@@ -389,9 +397,11 @@ function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end
function vim.api.nvim_buf_get_keymap(buffer, mode) end
--- Gets a line-range from the buffer.
+---
--- Indexing is zero-based, end-exclusive. Negative indices are interpreted as
--- length+1+index: -1 refers to the index past the end. So to get the last
--- element use start=-2 and end=-1.
+---
--- Out-of-bounds indices are clamped to the nearest valid value, unless
--- `strict_indexing` is set.
---
@@ -405,6 +415,7 @@ function vim.api.nvim_buf_get_lines(buffer, start, end_, strict_indexing) end
--- Returns a `(row,col)` tuple representing the position of the named mark.
--- "End of line" column position is returned as `v:maxcol` (big number). See
--- `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -424,10 +435,12 @@ function vim.api.nvim_buf_get_name(buffer) end
function vim.api.nvim_buf_get_number(buffer) end
--- Returns the byte offset of a line (0-indexed). `api-indexing`
+---
--- Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte.
--- 'fileformat' and 'fileencoding' are ignored. The line index just after the
--- last line gives the total byte-count of the buffer. A final EOL byte is
--- counted if it would be written, see 'eol'.
+---
--- Unlike `line2byte()`, throws error for out-of-bounds indexing. Returns -1
--- for unloaded buffer.
---
@@ -443,10 +456,13 @@ function vim.api.nvim_buf_get_offset(buffer, index) end
function vim.api.nvim_buf_get_option(buffer, name) end
--- Gets a range from the buffer.
+---
--- This differs from `nvim_buf_get_lines()` in that it allows retrieving only
--- portions of a line.
+---
--- Indexing is zero-based. Row indices are end-inclusive, and column indices
--- are end-exclusive.
+---
--- Prefer `nvim_buf_get_lines()` when retrieving entire lines.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -485,13 +501,16 @@ function vim.api.nvim_buf_is_valid(buffer) end
function vim.api.nvim_buf_line_count(buffer) end
--- Creates or updates an `extmark`.
+---
--- By default a new extmark is created when no id is passed in, but it is
--- also possible to create a new mark by passing in a previously unused id or
--- move an existing mark by passing in its id. The caller must then keep
--- track of existing and unused ids itself. (Useful over RPC, to avoid
--- waiting for the return value.)
+---
--- Using the optional arguments, it is possible to use this to highlight a
--- range of text, and also to associate virtual text to the mark.
+---
--- If present, the position defined by `end_col` and `end_row` should be
--- after the start position in order for the extmark to cover a range. An
--- earlier end position is not an error, but then it behaves like an empty
@@ -502,114 +521,110 @@ function vim.api.nvim_buf_line_count(buffer) end
--- @param line integer Line where to place the mark, 0-based. `api-indexing`
--- @param col integer Column where to place the mark, 0-based. `api-indexing`
--- @param opts vim.api.keyset.set_extmark Optional parameters.
---- • id : id of the extmark to edit.
---- • end_row : ending line of the mark, 0-based inclusive.
---- • end_col : ending col of the mark, 0-based exclusive.
---- • hl_group : name of the highlight group used to highlight
---- this mark.
---- • hl_eol : when true, for a multiline highlight covering the
---- EOL of a line, continue the highlight for the rest of the
---- screen line (just like for diff and cursorline highlight).
---- • virt_text : virtual text to link to this mark. A list of
---- [text, highlight] tuples, each representing a text chunk
---- with specified highlight. `highlight` element can either
---- be a single highlight group, or an array of multiple
---- highlight groups that will be stacked (highest priority
---- last). A highlight group can be supplied either as a
---- string or as an integer, the latter which can be obtained
---- using `nvim_get_hl_id_by_name()`.
---- • virt_text_pos : position of virtual text. Possible values:
---- • "eol": right after eol character (default).
---- • "overlay": display over the specified column, without
---- shifting the underlying text.
---- • "right_align": display right aligned in the window.
---- • "inline": display at the specified column, and shift the
---- buffer text to the right as needed.
----
---- • virt_text_win_col : position the virtual text at a fixed
---- window column (starting from the first text column of the
---- screen line) instead of "virt_text_pos".
---- • virt_text_hide : hide the virtual text when the background
---- text is selected or hidden because of scrolling with
---- 'nowrap' or 'smoothscroll'. Currently only affects
---- "overlay" virt_text.
---- • virt_text_repeat_linebreak : repeat the virtual text on
---- wrapped lines.
---- • hl_mode : control how highlights are combined with the
---- highlights of the text. Currently only affects virt_text
---- highlights, but might affect `hl_group` in
---- later versions.
---- • "replace": only show the virt_text color. This is the
---- default.
---- • "combine": combine with background text color.
---- • "blend": blend with background text color. Not supported
---- for "inline" virt_text.
----
---- • virt_lines : virtual lines to add next to this mark This
---- should be an array over lines, where each line in turn is
---- an array over [text, highlight] tuples. In general, buffer
---- and window options do not affect the display of the text.
---- In particular 'wrap' and 'linebreak' options do not take
---- effect, so the number of extra screen lines will always
---- match the size of the array. However the 'tabstop' buffer
---- option is still used for hard tabs. By default lines are
---- placed below the buffer line containing the mark.
---- • virt_lines_above: place virtual lines above instead.
---- • virt_lines_leftcol: Place extmarks in the leftmost column
---- of the window, bypassing sign and number columns.
---- • ephemeral : for use with `nvim_set_decoration_provider()`
---- callbacks. The mark will only be used for the current
---- redraw cycle, and not be permantently stored in the
---- buffer.
---- • right_gravity : boolean that indicates the direction the
---- extmark will be shifted in when new text is inserted (true
---- for right, false for left). Defaults to true.
---- • end_right_gravity : boolean that indicates the direction
---- the extmark end position (if it exists) will be shifted in
---- when new text is inserted (true for right, false for
---- left). Defaults to false.
---- • undo_restore : Restore the exact position of the mark if
---- text around the mark was deleted and then restored by
---- undo. Defaults to true.
---- • invalidate : boolean that indicates whether to hide the
---- extmark if the entirety of its range is deleted. For
---- hidden marks, an "invalid" key is added to the "details"
---- array of `nvim_buf_get_extmarks()` and family. If
---- "undo_restore" is false, the extmark is deleted instead.
---- • priority: a priority value for the highlight group, sign
---- attribute or virtual text. For virtual text, item with
---- highest priority is drawn last. For example treesitter
---- highlighting uses a value of 100.
---- • strict: boolean that indicates extmark should not be
---- placed if the line or column value is past the end of the
---- buffer or end of the line respectively. Defaults to true.
---- • sign_text: string of length 1-2 used to display in the
---- sign column.
---- • sign_hl_group: name of the highlight group used to
---- highlight the sign column text.
---- • number_hl_group: name of the highlight group used to
---- highlight the number column.
---- • line_hl_group: name of the highlight group used to
---- highlight the whole line.
---- • cursorline_hl_group: name of the highlight group used to
---- highlight the sign column text when the cursor is on the
---- same line as the mark and 'cursorline' is enabled.
---- • conceal: string which should be either empty or a single
---- character. Enable concealing similar to `:syn-conceal`.
---- When a character is supplied it is used as `:syn-cchar`.
---- "hl_group" is used as highlight for the cchar if provided,
---- otherwise it defaults to `hl-Conceal`.
---- • spell: boolean indicating that spell checking should be
---- performed within this extmark
---- • ui_watched: boolean that indicates the mark should be
---- drawn by a UI. When set, the UI will receive win_extmark
---- events. Note: the mark is positioned by virt_text
---- attributes. Can be used together with virt_text.
---- • url: A URL to associate with this extmark. In the TUI, the
---- OSC 8 control sequence is used to generate a clickable
---- hyperlink to this URL.
---- • scoped: boolean that indicates that the extmark should
---- only be displayed in the namespace scope. (experimental)
+--- • id : id of the extmark to edit.
+--- • end_row : ending line of the mark, 0-based inclusive.
+--- • end_col : ending col of the mark, 0-based exclusive.
+--- • hl_group : name of the highlight group used to highlight
+--- this mark.
+--- • hl_eol : when true, for a multiline highlight covering the
+--- EOL of a line, continue the highlight for the rest of the
+--- screen line (just like for diff and cursorline highlight).
+--- • virt_text : virtual text to link to this mark. A list of
+--- [text, highlight] tuples, each representing a text chunk
+--- with specified highlight. `highlight` element can either be
+--- a single highlight group, or an array of multiple highlight
+--- groups that will be stacked (highest priority last). A
+--- highlight group can be supplied either as a string or as an
+--- integer, the latter which can be obtained using
+--- `nvim_get_hl_id_by_name()`.
+--- • virt_text_pos : position of virtual text. Possible values:
+--- • "eol": right after eol character (default).
+--- • "overlay": display over the specified column, without
+--- shifting the underlying text.
+--- • "right_align": display right aligned in the window.
+--- • "inline": display at the specified column, and shift the
+--- buffer text to the right as needed.
+--- • virt_text_win_col : position the virtual text at a fixed
+--- window column (starting from the first text column of the
+--- screen line) instead of "virt_text_pos".
+--- • virt_text_hide : hide the virtual text when the background
+--- text is selected or hidden because of scrolling with
+--- 'nowrap' or 'smoothscroll'. Currently only affects "overlay"
+--- virt_text.
+--- • virt_text_repeat_linebreak : repeat the virtual text on
+--- wrapped lines.
+--- • hl_mode : control how highlights are combined with the
+--- highlights of the text. Currently only affects virt_text
+--- highlights, but might affect `hl_group` in later versions.
+--- • "replace": only show the virt_text color. This is the
+--- default.
+--- • "combine": combine with background text color.
+--- • "blend": blend with background text color. Not supported
+--- for "inline" virt_text.
+--- • virt_lines : virtual lines to add next to this mark This
+--- should be an array over lines, where each line in turn is an
+--- array over [text, highlight] tuples. In general, buffer and
+--- window options do not affect the display of the text. In
+--- particular 'wrap' and 'linebreak' options do not take
+--- effect, so the number of extra screen lines will always
+--- match the size of the array. However the 'tabstop' buffer
+--- option is still used for hard tabs. By default lines are
+--- placed below the buffer line containing the mark.
+--- • virt_lines_above: place virtual lines above instead.
+--- • virt_lines_leftcol: Place extmarks in the leftmost column of
+--- the window, bypassing sign and number columns.
+--- • ephemeral : for use with `nvim_set_decoration_provider()`
+--- callbacks. The mark will only be used for the current redraw
+--- cycle, and not be permantently stored in the buffer.
+--- • right_gravity : boolean that indicates the direction the
+--- extmark will be shifted in when new text is inserted (true
+--- for right, false for left). Defaults to true.
+--- • end_right_gravity : boolean that indicates the direction the
+--- extmark end position (if it exists) will be shifted in when
+--- new text is inserted (true for right, false for left).
+--- Defaults to false.
+--- • undo_restore : Restore the exact position of the mark if
+--- text around the mark was deleted and then restored by undo.
+--- Defaults to true.
+--- • invalidate : boolean that indicates whether to hide the
+--- extmark if the entirety of its range is deleted. For hidden
+--- marks, an "invalid" key is added to the "details" array of
+--- `nvim_buf_get_extmarks()` and family. If "undo_restore" is
+--- false, the extmark is deleted instead.
+--- • priority: a priority value for the highlight group, sign
+--- attribute or virtual text. For virtual text, item with
+--- highest priority is drawn last. For example treesitter
+--- highlighting uses a value of 100.
+--- • strict: boolean that indicates extmark should not be placed
+--- if the line or column value is past the end of the buffer or
+--- end of the line respectively. Defaults to true.
+--- • sign_text: string of length 1-2 used to display in the sign
+--- column.
+--- • sign_hl_group: name of the highlight group used to highlight
+--- the sign column text.
+--- • number_hl_group: name of the highlight group used to
+--- highlight the number column.
+--- • line_hl_group: name of the highlight group used to highlight
+--- the whole line.
+--- • cursorline_hl_group: name of the highlight group used to
+--- highlight the sign column text when the cursor is on the
+--- same line as the mark and 'cursorline' is enabled.
+--- • conceal: string which should be either empty or a single
+--- character. Enable concealing similar to `:syn-conceal`. When
+--- a character is supplied it is used as `:syn-cchar`.
+--- "hl_group" is used as highlight for the cchar if provided,
+--- otherwise it defaults to `hl-Conceal`.
+--- • spell: boolean indicating that spell checking should be
+--- performed within this extmark
+--- • ui_watched: boolean that indicates the mark should be drawn
+--- by a UI. When set, the UI will receive win_extmark events.
+--- Note: the mark is positioned by virt_text attributes. Can be
+--- used together with virt_text.
+--- • url: A URL to associate with this extmark. In the TUI, the
+--- OSC 8 control sequence is used to generate a clickable
+--- hyperlink to this URL.
+--- • scoped: boolean that indicates that the extmark should only
+--- be displayed in the namespace scope. (experimental)
--- @return integer
function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end
@@ -623,11 +638,14 @@ function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end
function vim.api.nvim_buf_set_keymap(buffer, mode, lhs, rhs, opts) end
--- Sets (replaces) a line-range in the buffer.
+---
--- Indexing is zero-based, end-exclusive. Negative indices are interpreted as
--- length+1+index: -1 refers to the index past the end. So to change or
--- delete the last element use start=-2 and end=-1.
+---
--- To insert lines at a given index, set `start` and `end` to the same index.
--- To delete a range of lines, set `replacement` to an empty array.
+---
--- Out-of-bounds indices are clamped to the nearest valid value, unless
--- `strict_indexing` is set.
---
@@ -640,6 +658,7 @@ function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replac
--- Sets a named mark in the given buffer, all marks are allowed
--- file/uppercase, visual, last change, etc. See `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param buffer integer Buffer to set the mark on
@@ -663,16 +682,21 @@ function vim.api.nvim_buf_set_name(buffer, name) end
function vim.api.nvim_buf_set_option(buffer, name, value) end
--- Sets (replaces) a range in the buffer
+---
--- This is recommended over `nvim_buf_set_lines()` when only modifying parts
--- of a line, as extmarks will be preserved on non-modified parts of the
--- touched lines.
+---
--- Indexing is zero-based. Row indices are end-inclusive, and column indices
--- are end-exclusive.
+---
--- To insert text at a given `(row, column)` location, use `start_row =
--- end_row = row` and `start_col = end_col = col`. To delete the text in a
--- range, use `replacement = {}`.
+---
--- Prefer `nvim_buf_set_lines()` if you are only adding or deleting entire
--- lines.
+---
--- Prefer `nvim_put()` if you want to insert text at the cursor position.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -700,6 +724,7 @@ function vim.api.nvim_buf_set_var(buffer, name, value) end
function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) end
--- Calls a Vimscript `Dictionary-function` with the given arguments.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param dict any Dictionary, or String evaluating to a Vimscript `self` dict
@@ -709,6 +734,7 @@ function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) e
function vim.api.nvim_call_dict_function(dict, fn, args) end
--- Calls a Vimscript function with the given arguments.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param fn string Function to call
@@ -720,6 +746,7 @@ function vim.api.nvim_call_function(fn, args) end
--- process. For the stdio channel `channel-stdio`, it writes to Nvim's
--- stdout. For an internal terminal instance (`nvim_open_term()`) it writes
--- directly to terminal output. See `channel-bytes` for more information.
+---
--- This function writes raw data, not RPC messages. If the channel was
--- created with `rpc=true` then the channel expects RPC messages, use
--- `vim.rpcnotify()` and `vim.rpcrequest()` instead.
@@ -736,42 +763,41 @@ function vim.api.nvim_chan_send(chan, data) end
--- • event: "pat1"
--- • event: { "pat1" }
--- • event: { "pat1", "pat2", "pat3" }
----
--- • pattern: (string|table)
--- • pattern or patterns to match exactly.
--- • For example, if you have `*.py` as that pattern for the
--- autocmd, you must pass `*.py` exactly to clear it.
--- `test.py` will not match the pattern.
----
--- • defaults to clearing all patterns.
--- • NOTE: Cannot be used with {buffer}
----
--- • buffer: (bufnr)
--- • clear only `autocmd-buflocal` autocommands.
--- • NOTE: Cannot be used with {pattern}
----
--- • group: (string|int) The augroup name or id.
--- • NOTE: If not passed, will only delete autocmds not in any
--- group.
function vim.api.nvim_clear_autocmds(opts) end
--- Executes an Ex command.
+---
--- Unlike `nvim_command()` this command takes a structured Dictionary instead
--- of a String. This allows for easier construction and manipulation of an Ex
--- command. This also allows for things such as having spaces inside a
--- command argument, expanding filenames in a command that otherwise doesn't
--- expand filenames, etc. Command arguments may also be Number, Boolean or
--- String.
+---
--- The first argument may also be used instead of count for commands that
--- support it in order to make their usage simpler with `vim.cmd()`. For
--- example, instead of `vim.cmd.bdelete{ count = 2 }`, you may do
--- `vim.cmd.bdelete(2)`.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param cmd vim.api.keyset.cmd Command to execute. Must be a Dictionary that can contain the
---- same values as the return value of `nvim_parse_cmd()` except
---- "addr", "nargs" and "nextcmd" which are ignored if provided.
---- All values except for "cmd" are optional.
+--- same values as the return value of `nvim_parse_cmd()` except
+--- "addr", "nargs" and "nextcmd" which are ignored if provided.
+--- All values except for "cmd" are optional.
--- @param opts vim.api.keyset.cmd_opts Optional parameters.
--- • output: (boolean, default false) Whether to return command
--- output.
@@ -779,7 +805,9 @@ function vim.api.nvim_clear_autocmds(opts) end
function vim.api.nvim_cmd(cmd, opts) end
--- Executes an Ex command.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
+---
--- Prefer using `nvim_cmd()` or `nvim_exec2()` over this. To evaluate
--- multiple lines of Vim script or an Ex command directly, use
--- `nvim_exec2()`. To construct an Ex command using a structured format and
@@ -800,11 +828,12 @@ function vim.api.nvim_command_output(command) end
---
--- @param index integer the completion candidate index
--- @param opts vim.api.keyset.complete_set Optional parameters.
---- • info: (string) info text.
+--- • info: (string) info text.
--- @return table<string,any>
function vim.api.nvim_complete_set(index, opts) end
--- Create or get an autocommand group `autocmd-groups`.
+---
--- To get an existing group id, do:
---
--- ```lua
@@ -813,6 +842,7 @@ function vim.api.nvim_complete_set(index, opts) end
--- })
--- ```
---
+---
--- @param name string String: The name of the group
--- @param opts vim.api.keyset.create_augroup Dictionary Parameters
--- • clear (bool) optional: defaults to true. Clear existing
@@ -820,8 +850,10 @@ function vim.api.nvim_complete_set(index, opts) end
--- @return integer
function vim.api.nvim_create_augroup(name, opts) end
---- Creates an `autocommand` event handler, defined by `callback` (Lua function
---- or Vimscript function name string) or `command` (Ex command string).
+--- Creates an `autocommand` event handler, defined by `callback` (Lua
+--- function or Vimscript function name string) or `command` (Ex command
+--- string).
+---
--- Example using Lua callback:
---
--- ```lua
@@ -849,39 +881,39 @@ function vim.api.nvim_create_augroup(name, opts) end
--- pattern = vim.fn.expand("~") .. "/some/path/*.py"
--- ```
---
+---
--- @param event any (string|array) Event(s) that will trigger the handler
--- (`callback` or `command`).
--- @param opts vim.api.keyset.create_autocmd Options dict:
---- • group (string|integer) optional: autocommand group name or
---- id to match against.
---- • pattern (string|array) optional: pattern(s) to match
---- literally `autocmd-pattern`.
---- • buffer (integer) optional: buffer number for buffer-local
---- autocommands `autocmd-buflocal`. Cannot be used with
---- {pattern}.
---- • desc (string) optional: description (for documentation and
---- troubleshooting).
---- • callback (function|string) optional: Lua function (or
---- Vimscript function name, if string) called when the
---- event(s) is triggered. Lua callback can return a truthy
---- value (not `false` or `nil`) to delete the
---- autocommand. Receives a table argument with these keys:
---- • id: (number) autocommand id
---- • event: (string) name of the triggered event
---- `autocmd-events`
---- • group: (number|nil) autocommand group id, if any
---- • match: (string) expanded value of `<amatch>`
---- • buf: (number) expanded value of `<abuf>`
---- • file: (string) expanded value of `<afile>`
---- • data: (any) arbitrary data passed from
---- `nvim_exec_autocmds()`
----
---- • command (string) optional: Vim command to execute on event.
---- Cannot be used with {callback}
---- • once (boolean) optional: defaults to false. Run the
---- autocommand only once `autocmd-once`.
---- • nested (boolean) optional: defaults to false. Run nested
---- autocommands `autocmd-nested`.
+--- • group (string|integer) optional: autocommand group name or
+--- id to match against.
+--- • pattern (string|array) optional: pattern(s) to match
+--- literally `autocmd-pattern`.
+--- • buffer (integer) optional: buffer number for buffer-local
+--- autocommands `autocmd-buflocal`. Cannot be used with
+--- {pattern}.
+--- • desc (string) optional: description (for documentation and
+--- troubleshooting).
+--- • callback (function|string) optional: Lua function (or
+--- Vimscript function name, if string) called when the event(s)
+--- is triggered. Lua callback can return a truthy value (not
+--- `false` or `nil`) to delete the autocommand. Receives a
+--- table argument with these keys:
+--- • id: (number) autocommand id
+--- • event: (string) name of the triggered event
+--- `autocmd-events`
+--- • group: (number|nil) autocommand group id, if any
+--- • match: (string) expanded value of `<amatch>`
+--- • buf: (number) expanded value of `<abuf>`
+--- • file: (string) expanded value of `<afile>`
+--- • data: (any) arbitrary data passed from
+--- `nvim_exec_autocmds()`
+--- • command (string) optional: Vim command to execute on event.
+--- Cannot be used with {callback}
+--- • once (boolean) optional: defaults to false. Run the
+--- autocommand only once `autocmd-once`.
+--- • nested (boolean) optional: defaults to false. Run nested
+--- autocommands `autocmd-nested`.
--- @return integer
function vim.api.nvim_create_autocmd(event, opts) end
@@ -894,9 +926,11 @@ function vim.api.nvim_create_autocmd(event, opts) end
--- @return integer
function vim.api.nvim_create_buf(listed, scratch) end
---- Creates a new namespace or gets an existing one. *namespace*
+--- Creates a new namespace or gets an existing one. *namespace*
+---
--- Namespaces are used for buffer highlights and virtual text, see
--- `nvim_buf_add_highlight()` and `nvim_buf_set_extmark()`.
+---
--- Namespaces can be named or anonymous. If `name` matches an existing
--- namespace, the associated id is returned. If `name` is an empty string a
--- new, anonymous namespace is created.
@@ -906,7 +940,9 @@ function vim.api.nvim_create_buf(listed, scratch) end
function vim.api.nvim_create_namespace(name) end
--- Creates a global `user-commands` command.
+---
--- For Lua usage see `lua-guide-commands-create`.
+---
--- Example:
---
--- ```vim
@@ -915,8 +951,9 @@ function vim.api.nvim_create_namespace(name) end
--- Hello world!
--- ```
---
+---
--- @param name string Name of the new user command. Must begin with an uppercase
---- letter.
+--- letter.
--- @param command any Replacement command to execute when this user command is
--- executed. When called from Lua, the command can also be a
--- Lua function. The function is called with a single table
@@ -943,23 +980,24 @@ function vim.api.nvim_create_namespace(name) end
--- Has the same structure as the "mods" key of
--- `nvim_parse_cmd()`.
--- @param opts vim.api.keyset.user_command Optional `command-attributes`.
---- • Set boolean attributes such as `:command-bang` or
---- `:command-bar` to true (but not `:command-buffer`, use
---- `nvim_buf_create_user_command()` instead).
---- • "complete" `:command-complete` also accepts a Lua
---- function which works like
---- `:command-completion-customlist`.
---- • Other parameters:
---- • desc: (string) Used for listing the command when a Lua
---- function is used for {command}.
---- • force: (boolean, default true) Override any previous
---- definition.
---- • preview: (function) Preview callback for 'inccommand'
---- `:command-preview`
+--- • Set boolean attributes such as `:command-bang` or
+--- `:command-bar` to true (but not `:command-buffer`, use
+--- `nvim_buf_create_user_command()` instead).
+--- • "complete" `:command-complete` also accepts a Lua function
+--- which works like `:command-completion-customlist`.
+--- • Other parameters:
+--- • desc: (string) Used for listing the command when a Lua
+--- function is used for {command}.
+--- • force: (boolean, default true) Override any previous
+--- definition.
+--- • preview: (function) Preview callback for 'inccommand'
+--- `:command-preview`
function vim.api.nvim_create_user_command(name, command, opts) end
--- Delete an autocommand group by id.
+---
--- To get a group id one can use `nvim_get_autocmds()`.
+---
--- NOTE: behavior differs from `:augroup-delete`. When deleting a group,
--- autocommands contained in this group will also be deleted and cleared.
--- This group will no longer exist.
@@ -968,6 +1006,7 @@ function vim.api.nvim_create_user_command(name, command, opts) end
function vim.api.nvim_del_augroup_by_id(id) end
--- Delete an autocommand group by name.
+---
--- NOTE: behavior differs from `:augroup-delete`. When deleting a group,
--- autocommands contained in this group will also be deleted and cleared.
--- This group will no longer exist.
@@ -985,6 +1024,7 @@ function vim.api.nvim_del_autocmd(id) end
function vim.api.nvim_del_current_line() end
--- Unmaps a global `mapping` for the given mode.
+---
--- To unmap a buffer-local mapping, use `nvim_buf_del_keymap()`.
---
--- @param mode string
@@ -1010,14 +1050,14 @@ function vim.api.nvim_del_var(name) end
--- Echo a message.
---
--- @param chunks any[] A list of [text, hl_group] arrays, each representing a text
---- chunk with specified highlight. `hl_group` element can be
---- omitted for no highlight.
+--- chunk with specified highlight. `hl_group` element can be
+--- omitted for no highlight.
--- @param history boolean if true, add to `message-history`.
--- @param opts vim.api.keyset.echo_opts Optional parameters.
---- • verbose: Message was printed as a result of 'verbose'
---- option if Nvim was invoked with -V3log_file, the message
---- will be redirected to the log_file and suppressed from
---- direct output.
+--- • verbose: Message was printed as a result of 'verbose' option
+--- if Nvim was invoked with -V3log_file, the message will be
+--- redirected to the log_file and suppressed from direct
+--- output.
function vim.api.nvim_echo(chunks, history, opts) end
--- Writes a message to the Vim error buffer. Does not append "\n", the
@@ -1034,6 +1074,7 @@ function vim.api.nvim_err_writeln(str) end
--- Evaluates a Vimscript `expression`. Dictionaries and Lists are recursively
--- expanded.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param expr string Vimscript expression string
@@ -1068,8 +1109,10 @@ function vim.api.nvim_exec(src, output) end
--- Executes Vimscript (multiline block of Ex commands), like anonymous
--- `:source`.
+---
--- Unlike `nvim_command()` this function supports heredocs, script-scope
--- (s:), etc.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param src string Vimscript code
@@ -1084,24 +1127,27 @@ function vim.api.nvim_exec2(src, opts) end
---
--- @param event any (String|Array) The event or events to execute
--- @param opts vim.api.keyset.exec_autocmds Dictionary of autocommand options:
---- • group (string|integer) optional: the autocommand group name
---- or id to match against. `autocmd-groups`.
---- • pattern (string|array) optional: defaults to "*"
---- `autocmd-pattern`. Cannot be used with {buffer}.
---- • buffer (integer) optional: buffer number
---- `autocmd-buflocal`. Cannot be used with {pattern}.
---- • modeline (bool) optional: defaults to true. Process the
---- modeline after the autocommands `<nomodeline>`.
---- • data (any): arbitrary data to send to the autocommand
---- callback. See `nvim_create_autocmd()` for details.
+--- • group (string|integer) optional: the autocommand group name
+--- or id to match against. `autocmd-groups`.
+--- • pattern (string|array) optional: defaults to "*"
+--- `autocmd-pattern`. Cannot be used with {buffer}.
+--- • buffer (integer) optional: buffer number `autocmd-buflocal`.
+--- Cannot be used with {pattern}.
+--- • modeline (bool) optional: defaults to true. Process the
+--- modeline after the autocommands `<nomodeline>`.
+--- • data (any): arbitrary data to send to the autocommand
+--- callback. See `nvim_create_autocmd()` for details.
function vim.api.nvim_exec_autocmds(event, opts) end
--- Sends input-keys to Nvim, subject to various quirks controlled by `mode`
--- flags. This is a blocking call, unlike `nvim_input()`.
+---
--- On execution error: does not fail, but updates v:errmsg.
+---
--- To input sequences like <C-o> use `nvim_replace_termcodes()` (typically
--- with escape_ks=false) to replace `keycodes`, then pass the result to
--- nvim_feedkeys().
+---
--- Example:
---
--- ```vim
@@ -1109,6 +1155,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end
--- :call nvim_feedkeys(key, 'n', v:false)
--- ```
---
+---
--- @param keys string to be typed
--- @param mode string behavior flags, see `feedkeys()`
--- @param escape_ks boolean If true, escape K_SPECIAL bytes in `keys`. This should be
@@ -1117,6 +1164,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end
function vim.api.nvim_feedkeys(keys, mode, escape_ks) end
--- Gets the option information for all options.
+---
--- The dictionary has the full option names as keys and option metadata
--- dictionaries as detailed at `nvim_get_option_info2()`.
---
@@ -1124,6 +1172,7 @@ function vim.api.nvim_feedkeys(keys, mode, escape_ks) end
function vim.api.nvim_get_all_options_info() end
--- Get all autocommands that match the corresponding {opts}.
+---
--- These examples will get autocommands matching ALL the given criteria:
---
--- ```lua
@@ -1164,6 +1213,7 @@ function vim.api.nvim_get_chan_info(chan) end
--- Returns the 24-bit RGB value of a `nvim_get_color_map()` color name or
--- "#rrggbb" hexadecimal string.
+---
--- Example:
---
--- ```vim
@@ -1171,11 +1221,13 @@ function vim.api.nvim_get_chan_info(chan) end
--- :echo nvim_get_color_by_name("#cbcbcb")
--- ```
---
+---
--- @param name string Color name or "#rrggbb" string
--- @return integer
function vim.api.nvim_get_color_by_name(name) end
--- Returns a map of color names and RGB values.
+---
--- Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values
--- (e.g. 65535).
---
@@ -1183,6 +1235,7 @@ function vim.api.nvim_get_color_by_name(name) end
function vim.api.nvim_get_color_map() end
--- Gets a map of global (non-buffer-local) Ex commands.
+---
--- Currently only `user-commands` are supported, not builtin Ex commands.
---
--- @param opts vim.api.keyset.get_commands Optional parameters. Currently only supports {"builtin":false}
@@ -1223,12 +1276,12 @@ function vim.api.nvim_get_current_win() end
--- `nvim_get_namespaces()`. Use 0 to get global highlight groups
--- `:highlight`.
--- @param opts vim.api.keyset.get_highlight Options dict:
---- • name: (string) Get a highlight definition by name.
---- • id: (integer) Get a highlight definition by id.
---- • link: (boolean, default true) Show linked group name
---- instead of effective definition `:hi-link`.
---- • create: (boolean, default true) When highlight group
---- doesn't exist create it.
+--- • name: (string) Get a highlight definition by name.
+--- • id: (integer) Get a highlight definition by id.
+--- • link: (boolean, default true) Show linked group name instead
+--- of effective definition `:hi-link`.
+--- • create: (boolean, default true) When highlight group doesn't
+--- exist create it.
--- @return vim.api.keyset.hl_info
function vim.api.nvim_get_hl(ns_id, opts) end
@@ -1245,6 +1298,7 @@ function vim.api.nvim_get_hl_by_id(hl_id, rgb) end
function vim.api.nvim_get_hl_by_name(name, rgb) end
--- Gets a highlight group by name
+---
--- similar to `hlID()`, but allocates a new ID if not present.
---
--- @param name string
@@ -1270,6 +1324,7 @@ function vim.api.nvim_get_keymap(mode) end
--- Returns a `(row, col, buffer, buffername)` tuple representing the position
--- of the uppercase/file named mark. "End of line" column position is
--- returned as `v:maxcol` (big number). See `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param name string Mark name
@@ -1299,6 +1354,7 @@ function vim.api.nvim_get_option(name) end
function vim.api.nvim_get_option_info(name) end
--- Gets the option information for one option from arbitrary buffer or window
+---
--- Resulting dictionary has keys:
--- • name: Name of the option (like 'filetype')
--- • shortname: Shortened name of the option (like 'ft')
@@ -1360,10 +1416,12 @@ function vim.api.nvim_get_proc(pid) end
function vim.api.nvim_get_proc_children(pid) end
--- Find files in runtime directories
+---
--- "name" can contain wildcards. For example
--- nvim_get_runtime_file("colors/*.vim", true) will return all color scheme
--- files. Always use forward slashes (/) in the search pattern for
--- subdirectories regardless of platform.
+---
--- It is not an error to not find any files. An empty array is returned then.
---
--- @param name string pattern of files to search for
@@ -1386,6 +1444,7 @@ function vim.api.nvim_get_vvar(name) end
--- Queues raw user-input. Unlike `nvim_feedkeys()`, this uses a low-level
--- input buffer and the call is non-blocking (input is processed
--- asynchronously by the eventloop).
+---
--- On execution error: does not fail, but updates v:errmsg.
---
--- @param keys string to be typed
@@ -1393,14 +1452,15 @@ function vim.api.nvim_get_vvar(name) end
function vim.api.nvim_input(keys) end
--- Send mouse event from GUI.
+---
--- Non-blocking: does not wait on any result, but queues the event to be
--- processed soon by the event loop.
---
--- @param button string Mouse button: one of "left", "right", "middle", "wheel",
---- "move", "x1", "x2".
---- @param action string For ordinary buttons, one of "press", "drag", "release".
---- For the wheel, one of "up", "down", "left", "right".
---- Ignored for "move".
+--- "move", "x1", "x2".
+--- @param action string For ordinary buttons, one of "press", "drag", "release". For
+--- the wheel, one of "up", "down", "left", "right". Ignored for
+--- "move".
--- @param modifier string String of modifiers each represented by a single char. The
--- same specifiers are used as for a key press, except that
--- the "-" separator is optional, so "C-A-", "c-a" and "CA"
@@ -1411,6 +1471,7 @@ function vim.api.nvim_input(keys) end
function vim.api.nvim_input_mouse(button, action, modifier, grid, row, col) end
--- Gets the current list of buffer handles
+---
--- Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use
--- `nvim_buf_is_loaded()` to check if a buffer is loaded.
---
@@ -1449,6 +1510,7 @@ function vim.api.nvim_list_wins() end
function vim.api.nvim_load_context(dict) end
--- Notify the user with a message
+---
--- Relays the call to vim.notify . By default forwards your message in the
--- echo area but can be overridden to trigger desktop notifications.
---
@@ -1459,10 +1521,12 @@ function vim.api.nvim_load_context(dict) end
function vim.api.nvim_notify(msg, log_level, opts) end
--- Open a terminal instance in a buffer
+---
--- By default (and currently the only option) the terminal will not be
--- connected to an external process. Instead, input send on the channel will
--- be echoed directly by the terminal. This is useful to display ANSI
--- terminal sequences returned as part of a rpc message, or similar.
+---
--- Note: to directly initiate the terminal using the right size, display the
--- buffer in a configured window before calling this. For instance, for a
--- floating display, first create an empty buffer using `nvim_create_buf()`,
@@ -1472,27 +1536,30 @@ function vim.api.nvim_notify(msg, log_level, opts) end
---
--- @param buffer integer the buffer to use (expected to be empty)
--- @param opts vim.api.keyset.open_term Optional parameters.
---- • on_input: Lua callback for input sent, i e keypresses in
---- terminal mode. Note: keypresses are sent raw as they would
---- be to the pty master end. For instance, a carriage return
---- is sent as a "\r", not as a "\n". `textlock` applies. It
---- is possible to call `nvim_chan_send()` directly in the
---- callback however. ["input", term, bufnr, data]
---- • force_crlf: (boolean, default true) Convert "\n" to
---- "\r\n".
+--- • on_input: Lua callback for input sent, i e keypresses in
+--- terminal mode. Note: keypresses are sent raw as they would
+--- be to the pty master end. For instance, a carriage return is
+--- sent as a "\r", not as a "\n". `textlock` applies. It is
+--- possible to call `nvim_chan_send()` directly in the callback
+--- however. ["input", term, bufnr, data]
+--- • force_crlf: (boolean, default true) Convert "\n" to "\r\n".
--- @return integer
function vim.api.nvim_open_term(buffer, opts) end
--- Opens a new split window, or a floating window if `relative` is specified,
--- or an external window (managed by the UI) if `external` is specified.
+---
--- Floats are windows that are drawn above the split layout, at some anchor
--- position in some other window. Floats can be drawn internally or by
--- external GUI with the `ui-multigrid` extension. External windows are only
--- supported with multigrid GUIs, and are displayed as separate top-level
--- windows.
+---
--- For a general overview of floats, see `api-floatwin`.
+---
--- The `width` and `height` of the new window must be specified when opening
--- a floating window, but are optional for normal windows.
+---
--- If `relative` and `external` are omitted, a normal "split" window is
--- created. The `win` property determines which window will be split. If no
--- `win` is provided or `win == 0`, a window will be created adjacent to the
@@ -1501,15 +1568,18 @@ function vim.api.nvim_open_term(buffer, opts) end
--- control split direction. For `vertical`, the exact direction is determined
--- by `'splitright'` and `'splitbelow'`. Split windows cannot have
--- `bufpos`/`row`/`col`/`border`/`title`/`footer` properties.
+---
--- With relative=editor (row=0,col=0) refers to the top-left corner of the
--- screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
--- corner. Fractional values are allowed, but the builtin implementation
--- (used by non-multigrid UIs) will always round down to nearest integer.
+---
--- Out-of-bounds values, and configurations that make the float not fit
--- inside the main editor, are allowed. The builtin implementation truncates
--- values so floats are fully within the main screen grid. External GUIs
--- could let floats hover outside of the main window like a tooltip, but this
--- should not be used to specify arbitrary WM screen positions.
+---
--- Example (Lua): window-relative float
---
--- ```lua
@@ -1533,6 +1603,7 @@ function vim.api.nvim_open_term(buffer, opts) end
--- })
--- ```
---
+---
--- @param buffer integer Buffer to display, or 0 for current buffer
--- @param enter boolean Enter the window (make it the current window)
--- @param config vim.api.keyset.win_config Map defining the window configuration. Keys:
@@ -1543,7 +1614,6 @@ function vim.api.nvim_open_term(buffer, opts) end
--- window.
--- • "cursor" Cursor position in current window.
--- • "mouse" Mouse position
----
--- • win: `window-ID` window to split, or relative window when
--- creating a float (relative="win").
--- • anchor: Decides which corner of the float to place at
@@ -1552,17 +1622,15 @@ function vim.api.nvim_open_term(buffer, opts) end
--- • "NE" northeast
--- • "SW" southwest
--- • "SE" southeast
----
--- • width: Window width (in character cells). Minimum of 1.
--- • height: Window height (in character cells). Minimum of 1.
--- • bufpos: Places float relative to buffer text (only when
--- relative="win"). Takes a tuple of zero-indexed [line,
---- column]. `row` and `col` if given are
---- applied relative to this position, else they default to:
+--- column]. `row` and `col` if given are applied relative to
+--- this position, else they default to:
--- • `row=1` and `col=0` if `anchor` is "NW" or "NE"
--- • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
--- like a tooltip near the buffer text).
----
--- • row: Row position in units of "screen cell height", may be
--- fractional.
--- • col: Column position in units of "screen cell width", may
@@ -1583,7 +1651,6 @@ function vim.api.nvim_open_term(buffer, opts) end
--- wildoptions+=pum) The default value for floats are 50.
--- In general, values below 100 are recommended, unless
--- there is a good reason to overshadow builtin elements.
----
--- • style: (optional) Configure the appearance of the window.
--- Currently only supports one value:
--- • "minimal" Nvim will display the window with many UI
@@ -1596,14 +1663,13 @@ function vim.api.nvim_open_term(buffer, opts) end
--- empty. The end-of-buffer region is hidden by setting
--- `eob` flag of 'fillchars' to a space char, and clearing
--- the `hl-EndOfBuffer` region in 'winhighlight'.
----
--- • border: Style of (optional) window border. This can either
--- be a string or an array. The string values are
--- • "none": No border (default).
--- • "single": A single line box.
--- • "double": A double line box.
---- • "rounded": Like "single", but with rounded corners ("╭"
---- etc.).
+--- • "rounded": Like "single", but with rounded corners
+--- ("╭" etc.).
--- • "solid": Adds padding by a single whitespace cell.
--- • "shadow": A drop shadow effect by blending with the
--- background.
@@ -1611,18 +1677,35 @@ function vim.api.nvim_open_term(buffer, opts) end
--- any divisor of eight. The array will specify the eight
--- chars building up the border in a clockwise fashion
--- starting with the top-left corner. As an example, the
---- double box style could be specified as [ "╔", "═" ,"╗",
---- "║", "╝", "═", "╚", "║" ]. If the number of chars are
---- less than eight, they will be repeated. Thus an ASCII
---- border could be specified as [ "/", "-", "\\", "|" ], or
---- all chars the same as [ "x" ]. An empty string can be
---- used to turn off a specific border, for instance, [ "",
---- "", "", ">", "", "", "", "<" ] will only make vertical
---- borders but not horizontal ones. By default,
---- `FloatBorder` highlight is used, which links to
---- `WinSeparator` when not defined. It could also be
---- specified by character: [ ["+", "MyCorner"], ["x",
---- "MyBorder"] ].
+--- double box style could be specified as:
+--- ```
+--- [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
+--- ```
+---
+--- If the number of chars are less than eight, they will be
+--- repeated. Thus an ASCII border could be specified as
+--- ```
+--- [ "/", "-", \"\\\\\", "|" ],
+--- ```
+---
+--- or all chars the same as
+--- ```
+--- [ "x" ].
+--- ```
+---
+--- An empty string can be used to turn off a specific border,
+--- for instance,
+--- ```
+--- [ "", "", "", ">", "", "", "", "<" ]
+--- ```
+---
+--- will only make vertical borders but not horizontal ones.
+--- By default, `FloatBorder` highlight is used, which links
+--- to `WinSeparator` when not defined. It could also be
+--- specified by character:
+--- ```
+--- [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+--- ```
---
--- • title: Title (optional) in window border, string or list.
--- List should consist of `[text, highlight]` tuples. If
@@ -1654,6 +1737,7 @@ function vim.api.nvim_open_win(buffer, enter, config) end
function vim.api.nvim_out_write(str) end
--- Parse command line.
+---
--- Doesn't check the validity of command arguments.
---
--- @param str string Command line string to parse. Cannot contain "\n".
@@ -1665,17 +1749,17 @@ function vim.api.nvim_parse_cmd(str, opts) end
---
--- @param expr string Expression to parse. Always treated as a single line.
--- @param flags string Flags:
---- • "m" if multiple expressions in a row are allowed (only
---- the first one will be parsed),
---- • "E" if EOC tokens are not allowed (determines whether
---- they will stop parsing process or be recognized as an
---- operator/space, though also yielding an error).
---- • "l" when needing to start parsing with lvalues for
---- ":let" or ":for". Common flag sets:
---- • "m" to parse like for ":echo".
---- • "E" to parse like for "<C-r>=".
---- • empty string for ":call".
---- • "lm" to parse for ":let".
+--- • "m" if multiple expressions in a row are allowed (only the
+--- first one will be parsed),
+--- • "E" if EOC tokens are not allowed (determines whether they
+--- will stop parsing process or be recognized as an
+--- operator/space, though also yielding an error).
+--- • "l" when needing to start parsing with lvalues for ":let"
+--- or ":for". Common flag sets:
+--- • "m" to parse like for ":echo".
+--- • "E" to parse like for "<C-r>=".
+--- • empty string for ":call".
+--- • "lm" to parse for ":let".
--- @param highlight boolean If true, return value will also include "highlight" key
--- containing array of 4-tuples (arrays) (Integer, Integer,
--- Integer, String), where first three numbers define the
@@ -1686,8 +1770,10 @@ function vim.api.nvim_parse_cmd(str, opts) end
function vim.api.nvim_parse_expression(expr, flags, highlight) end
--- Pastes at cursor, in any mode.
+---
--- Invokes the `vim.paste` handler, which handles each mode appropriately.
--- Sets redo/undo. Faster than `nvim_input()`. Lines break at LF ("\n").
+---
--- Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err`
--- but do not affect the return value (which is strictly decided by
--- `vim.paste()`). On error, subsequent calls are ignored ("drained") until
@@ -1696,8 +1782,8 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end
--- @param data string Multiline input. May be binary (containing NUL bytes).
--- @param crlf boolean Also break lines at CR and CRLF.
--- @param phase integer -1: paste in a single call (i.e. without streaming). To
---- "stream" a paste, call `nvim_paste` sequentially
---- with these `phase` values:
+--- "stream" a paste, call `nvim_paste` sequentially with these
+--- `phase` values:
--- • 1: starts the paste (exactly once)
--- • 2: continues the paste (zero or more times)
--- • 3: ends the paste (exactly once)
@@ -1705,16 +1791,16 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end
function vim.api.nvim_paste(data, crlf, phase) end
--- Puts text at cursor, in any mode.
+---
--- Compare `:put` and `p` which are always linewise.
---
--- @param lines string[] `readfile()`-style list of lines. `channel-lines`
--- @param type string Edit behavior: any `getregtype()` result, or:
---- • "b" `blockwise-visual` mode (may include width, e.g. "b3")
---- • "c" `charwise` mode
---- • "l" `linewise` mode
---- • "" guess by contents, see `setreg()`
---- @param after boolean If true insert after cursor (like `p`), or before (like
---- `P`).
+--- • "b" `blockwise-visual` mode (may include width, e.g. "b3")
+--- • "c" `charwise` mode
+--- • "l" `linewise` mode
+--- • "" guess by contents, see `setreg()`
+--- @param after boolean If true insert after cursor (like `p`), or before (like `P`).
--- @param follow boolean If true place cursor at end of inserted text.
function vim.api.nvim_put(lines, type, after, follow) end
@@ -1729,14 +1815,15 @@ function vim.api.nvim_put(lines, type, after, follow) end
function vim.api.nvim_replace_termcodes(str, from_part, do_lt, special) end
--- Selects an item in the completion popup menu.
+---
--- If neither `ins-completion` nor `cmdline-completion` popup menu is active
--- this API call is silently ignored. Useful for an external UI using
--- `ui-popupmenu` to control the popup menu with the mouse. Can also be used
--- in a mapping; use <Cmd> `:map-cmd` or a Lua mapping to ensure the mapping
--- doesn't end completion mode.
---
---- @param item integer Index (zero-based) of the item to select. Value of -1
---- selects nothing and restores the original text.
+--- @param item integer Index (zero-based) of the item to select. Value of -1 selects
+--- nothing and restores the original text.
--- @param insert boolean For `ins-completion`, whether the selection should be
--- inserted in the buffer. Ignored for `cmdline-completion`.
--- @param finish boolean Finish the completion and dismiss the popup menu. Implies
@@ -1770,13 +1857,16 @@ function vim.api.nvim_set_current_tabpage(tabpage) end
function vim.api.nvim_set_current_win(window) end
--- Set or change decoration provider for a `namespace`
+---
--- This is a very general purpose interface for having Lua callbacks being
--- triggered during the redraw code.
+---
--- The expected usage is to set `extmarks` for the currently redrawn buffer.
--- `nvim_buf_set_extmark()` can be called to add marks on a per-window or
--- per-lines basis. Use the `ephemeral` key to only use the mark for the
--- current screen redraw (the callback will be called again for the next
--- redraw).
+---
--- Note: this function should not be called often. Rather, the callbacks
--- themselves can be used to throttle unneeded callbacks. the `on_start`
--- callback can return `false` to disable the provider until the next redraw.
@@ -1785,26 +1875,27 @@ function vim.api.nvim_set_current_win(window) end
--- plugin managing multiple sources of decoration should ideally only set one
--- provider, and merge the sources internally. You can use multiple `ns_id`
--- for the extmarks set/modified inside the callback anyway.
+---
--- Note: doing anything other than setting extmarks is considered
--- experimental. Doing things like changing options are not explicitly
--- forbidden, but is likely to have unexpected consequences (such as 100% CPU
--- consumption). doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
--- quite dubious for the moment.
+---
--- Note: It is not allowed to remove or update extmarks in 'on_line'
--- callbacks.
---
--- @param ns_id integer Namespace id from `nvim_create_namespace()`
--- @param opts vim.api.keyset.set_decoration_provider Table of callbacks:
---- • on_start: called first on each screen redraw ["start",
---- tick]
---- • on_buf: called for each buffer being redrawn (before window
---- callbacks) ["buf", bufnr, tick]
---- • on_win: called when starting to redraw a specific window.
---- ["win", winid, bufnr, topline, botline]
---- • on_line: called for each buffer line being redrawn. (The
---- interaction with fold lines is subject to change) ["line",
---- winid, bufnr, row]
---- • on_end: called at the end of a redraw cycle ["end", tick]
+--- • on_start: called first on each screen redraw ["start", tick]
+--- • on_buf: called for each buffer being redrawn (before window
+--- callbacks) ["buf", bufnr, tick]
+--- • on_win: called when starting to redraw a specific window.
+--- ["win", winid, bufnr, topline, botline]
+--- • on_line: called for each buffer line being redrawn. (The
+--- interaction with fold lines is subject to change) ["line",
+--- winid, bufnr, row]
+--- • on_end: called at the end of a redraw cycle ["end", tick]
function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- Sets a highlight group.
@@ -1816,31 +1907,31 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- activate them.
--- @param name string Highlight group name, e.g. "ErrorMsg"
--- @param val vim.api.keyset.highlight Highlight definition map, accepts the following keys:
---- • fg: color name or "#RRGGBB", see note.
---- • bg: color name or "#RRGGBB", see note.
---- • sp: color name or "#RRGGBB"
---- • blend: integer between 0 and 100
---- • bold: boolean
---- • standout: boolean
---- • underline: boolean
---- • undercurl: boolean
---- • underdouble: boolean
---- • underdotted: boolean
---- • underdashed: boolean
---- • strikethrough: boolean
---- • italic: boolean
---- • reverse: boolean
---- • nocombine: boolean
---- • link: name of another highlight group to link to, see
---- `:hi-link`.
---- • default: Don't override existing definition `:hi-default`
---- • ctermfg: Sets foreground of cterm color `ctermfg`
---- • ctermbg: Sets background of cterm color `ctermbg`
---- • cterm: cterm attribute map, like `highlight-args`. If not
---- set, cterm attributes will match those from the attribute
---- map documented above.
---- • force: if true force update the highlight group when it
---- exists.
+--- • fg: color name or "#RRGGBB", see note.
+--- • bg: color name or "#RRGGBB", see note.
+--- • sp: color name or "#RRGGBB"
+--- • blend: integer between 0 and 100
+--- • bold: boolean
+--- • standout: boolean
+--- • underline: boolean
+--- • undercurl: boolean
+--- • underdouble: boolean
+--- • underdotted: boolean
+--- • underdashed: boolean
+--- • strikethrough: boolean
+--- • italic: boolean
+--- • reverse: boolean
+--- • nocombine: boolean
+--- • link: name of another highlight group to link to, see
+--- `:hi-link`.
+--- • default: Don't override existing definition `:hi-default`
+--- • ctermfg: Sets foreground of cterm color `ctermfg`
+--- • ctermbg: Sets background of cterm color `ctermbg`
+--- • cterm: cterm attribute map, like `highlight-args`. If not
+--- set, cterm attributes will match those from the attribute map
+--- documented above.
+--- • force: if true force update the highlight group when it
+--- exists.
function vim.api.nvim_set_hl(ns_id, name, val) end
--- Set active namespace for highlights defined with `nvim_set_hl()`. This can
@@ -1851,6 +1942,7 @@ function vim.api.nvim_set_hl_ns(ns_id) end
--- Set active namespace for highlights defined with `nvim_set_hl()` while
--- redrawing.
+---
--- This function meant to be called while redrawing, primarily from
--- `nvim_set_decoration_provider()` on_win and on_line callbacks, which are
--- allowed to change the namespace during a redraw cycle.
@@ -1859,9 +1951,12 @@ function vim.api.nvim_set_hl_ns(ns_id) end
function vim.api.nvim_set_hl_ns_fast(ns_id) end
--- Sets a global `mapping` for the given mode.
+---
--- To set a buffer-local mapping, use `nvim_buf_set_keymap()`.
+---
--- Unlike `:map`, leading/trailing whitespace is accepted as part of the
--- {lhs} or {rhs}. Empty {rhs} is `<Nop>`. `keycodes` are replaced as usual.
+---
--- Example:
---
--- ```vim
@@ -1874,8 +1969,9 @@ function vim.api.nvim_set_hl_ns_fast(ns_id) end
--- nmap <nowait> <Space><NL> <Nop>
--- ```
---
---- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …) or
---- "!" for `:map!`, or empty string for `:map`. "ia", "ca" or
+---
+--- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …)
+--- or "!" for `:map!`, or empty string for `:map`. "ia", "ca" or
--- "!a" for abbreviation in Insert mode, Cmdline mode, or both,
--- respectively
--- @param lhs string Left-hand-side `{lhs}` of the mapping.
@@ -1899,15 +1995,16 @@ function vim.api.nvim_set_option(name, value) end
--- Sets the value of an option. The behavior of this function matches that of
--- `:set`: for global-local options, both the global and local value are set
--- unless otherwise specified with {scope}.
+---
--- Note the options {win} and {buf} cannot be used together.
---
--- @param name string Option name
--- @param value any New option value
--- @param opts vim.api.keyset.option Optional parameters
---- • scope: One of "global" or "local". Analogous to
---- `:setglobal` and `:setlocal`, respectively.
---- • win: `window-ID`. Used for setting window local option.
---- • buf: Buffer number. Used for setting buffer local option.
+--- • scope: One of "global" or "local". Analogous to `:setglobal`
+--- and `:setlocal`, respectively.
+--- • win: `window-ID`. Used for setting window local option.
+--- • buf: Buffer number. Used for setting buffer local option.
function vim.api.nvim_set_option_value(name, value, opts) end
--- Sets a global (g:) variable.
@@ -1990,7 +2087,7 @@ function vim.api.nvim_win_add_ns(window, ns_id) end
---
--- @param window integer Window handle, or 0 for current window
--- @param fun function Function to call inside the window (currently Lua callable
---- only)
+--- only)
--- @return any
function vim.api.nvim_win_call(window, fun) end
@@ -1998,8 +2095,8 @@ function vim.api.nvim_win_call(window, fun) end
---
--- @param window integer Window handle, or 0 for current window
--- @param force boolean Behave like `:close!` The last window of a buffer with
---- unwritten changes can be closed. The buffer will become
---- hidden, even if 'hidden' is not set.
+--- unwritten changes can be closed. The buffer will become
+--- hidden, even if 'hidden' is not set.
function vim.api.nvim_win_close(window, force) end
--- Removes a window-scoped (w:) variable
@@ -2015,7 +2112,9 @@ function vim.api.nvim_win_del_var(window, name) end
function vim.api.nvim_win_get_buf(window) end
--- Gets window configuration.
+---
--- The returned value may be given to `nvim_open_win()`.
+---
--- `relative` is empty for normal windows.
---
--- @param window integer Window handle, or 0 for current window
@@ -2081,6 +2180,7 @@ function vim.api.nvim_win_get_width(window) end
--- Closes the window and hide the buffer it contains (like `:hide` with a
--- `window-ID`).
+---
--- Like `:hide` the buffer becomes hidden unless another window is editing
--- it, or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to `:close`
--- or `nvim_win_close()`, which will close the buffer.
@@ -2109,6 +2209,7 @@ function vim.api.nvim_win_set_buf(window, buffer) end
--- Configures window layout. Currently only for floating and external windows
--- (including changing a split window to those layouts).
+---
--- When reconfiguring a floating window, absent option keys will not be
--- changed. `row`/`col` and `relative` must be reconfigured together.
---
@@ -2132,6 +2233,7 @@ function vim.api.nvim_win_set_height(window, height) end
--- Set highlight namespace for a window. This will use highlights defined
--- with `nvim_set_hl()` for this namespace, but fall back to global
--- highlights (ns=0) when missing.
+---
--- This takes precedence over the 'winhighlight' option.
---
--- @param window integer
@@ -2160,23 +2262,26 @@ function vim.api.nvim_win_set_width(window, width) end
--- Computes the number of screen lines occupied by a range of text in a given
--- window. Works for off-screen text and takes folds into account.
+---
--- Diff filler or virtual lines above a line are counted as a part of that
--- line, unless the line is on "start_row" and "start_vcol" is specified.
+---
--- Diff filler or virtual lines below the last buffer line are counted in the
--- result when "end_row" is omitted.
+---
--- Line indexing is similar to `nvim_buf_get_text()`.
---
--- @param window integer Window handle, or 0 for current window.
--- @param opts vim.api.keyset.win_text_height Optional parameters:
---- • start_row: Starting line index, 0-based inclusive. When
---- omitted start at the very top.
---- • end_row: Ending line index, 0-based inclusive. When
---- omitted end at the very bottom.
---- • start_vcol: Starting virtual column index on "start_row",
---- 0-based inclusive, rounded down to full screen lines. When
---- omitted include the whole line.
---- • end_vcol: Ending virtual column index on "end_row",
---- 0-based exclusive, rounded up to full screen lines. When
---- omitted include the whole line.
+--- • start_row: Starting line index, 0-based inclusive. When
+--- omitted start at the very top.
+--- • end_row: Ending line index, 0-based inclusive. When omitted
+--- end at the very bottom.
+--- • start_vcol: Starting virtual column index on "start_row",
+--- 0-based inclusive, rounded down to full screen lines. When
+--- omitted include the whole line.
+--- • end_vcol: Ending virtual column index on "end_row", 0-based
+--- exclusive, rounded up to full screen lines. When omitted
+--- include the whole line.
--- @return table<string,any>
function vim.api.nvim_win_text_height(window, opts) end
diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua
index a422a65792..472162ecc1 100644
--- a/runtime/lua/vim/_meta/builtin.lua
+++ b/runtime/lua/vim/_meta/builtin.lua
@@ -3,65 +3,63 @@
error('Cannot require a meta file')
----@defgroup vim.builtin
----
----@brief <pre>help
----vim.api.{func}({...}) *vim.api*
---- Invokes Nvim |API| function {func} with arguments {...}.
---- Example: call the "nvim_get_current_line()" API function: >lua
---- print(tostring(vim.api.nvim_get_current_line()))
----
----vim.NIL *vim.NIL*
---- Special value representing NIL in |RPC| and |v:null| in Vimscript
---- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
---- table representing a Dictionary or Array, because it is treated as
---- missing: `{"foo", nil}` is the same as `{"foo"}`.
----
----vim.type_idx *vim.type_idx*
---- Type index for use in |lua-special-tbl|. Specifying one of the values from
---- |vim.types| allows typing the empty table (it is unclear whether empty Lua
---- table represents empty list or empty array) and forcing integral numbers
---- to be |Float|. See |lua-special-tbl| for more details.
----
----vim.val_idx *vim.val_idx*
---- Value index for tables representing |Float|s. A table representing
---- floating-point value 1.0 looks like this: >lua
---- {
---- [vim.type_idx] = vim.types.float,
---- [vim.val_idx] = 1.0,
---- }
----< See also |vim.type_idx| and |lua-special-tbl|.
----
----vim.types *vim.types*
---- Table with possible values for |vim.type_idx|. Contains two sets of
---- key-value pairs: first maps possible values for |vim.type_idx| to
---- human-readable strings, second maps human-readable type names to values
---- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
---- `dictionary` types.
----
---- Note: One must expect that values corresponding to `vim.types.float`,
---- `vim.types.array` and `vim.types.dictionary` fall under only two following
---- assumptions:
---- 1. Value may serve both as a key and as a value in a table. Given the
---- properties of Lua tables this basically means “value is not `nil`”.
---- 2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
---- same as `value`.
---- No other restrictions are put on types, and it is not guaranteed that
---- values corresponding to `vim.types.float`, `vim.types.array` and
---- `vim.types.dictionary` will not change or that `vim.types` table will only
---- contain values for these three types.
----
---- *log_levels* *vim.log.levels*
----Log levels are one of the values defined in `vim.log.levels`:
----
---- vim.log.levels.DEBUG
---- vim.log.levels.ERROR
---- vim.log.levels.INFO
---- vim.log.levels.TRACE
---- vim.log.levels.WARN
---- vim.log.levels.OFF
----
----</pre>
+--- @brief <pre>help
+--- vim.api.{func}({...}) *vim.api*
+--- Invokes Nvim |API| function {func} with arguments {...}.
+--- Example: call the "nvim_get_current_line()" API function: >lua
+--- print(tostring(vim.api.nvim_get_current_line()))
+---
+--- vim.NIL *vim.NIL*
+--- Special value representing NIL in |RPC| and |v:null| in Vimscript
+--- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
+--- table representing a Dictionary or Array, because it is treated as
+--- missing: `{"foo", nil}` is the same as `{"foo"}`.
+---
+--- vim.type_idx *vim.type_idx*
+--- Type index for use in |lua-special-tbl|. Specifying one of the values from
+--- |vim.types| allows typing the empty table (it is unclear whether empty Lua
+--- table represents empty list or empty array) and forcing integral numbers
+--- to be |Float|. See |lua-special-tbl| for more details.
+---
+--- vim.val_idx *vim.val_idx*
+--- Value index for tables representing |Float|s. A table representing
+--- floating-point value 1.0 looks like this: >lua
+--- {
+--- [vim.type_idx] = vim.types.float,
+--- [vim.val_idx] = 1.0,
+--- }
+--- < See also |vim.type_idx| and |lua-special-tbl|.
+---
+--- vim.types *vim.types*
+--- Table with possible values for |vim.type_idx|. Contains two sets of
+--- key-value pairs: first maps possible values for |vim.type_idx| to
+--- human-readable strings, second maps human-readable type names to values
+--- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
+--- `dictionary` types.
+---
+--- Note: One must expect that values corresponding to `vim.types.float`,
+--- `vim.types.array` and `vim.types.dictionary` fall under only two following
+--- assumptions:
+--- 1. Value may serve both as a key and as a value in a table. Given the
+--- properties of Lua tables this basically means “value is not `nil`”.
+--- 2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
+--- same as `value`.
+--- No other restrictions are put on types, and it is not guaranteed that
+--- values corresponding to `vim.types.float`, `vim.types.array` and
+--- `vim.types.dictionary` will not change or that `vim.types` table will only
+--- contain values for these three types.
+---
+--- *log_levels* *vim.log.levels*
+--- Log levels are one of the values defined in `vim.log.levels`:
+---
+--- vim.log.levels.DEBUG
+--- vim.log.levels.ERROR
+--- vim.log.levels.INFO
+--- vim.log.levels.TRACE
+--- vim.log.levels.WARN
+--- vim.log.levels.OFF
+---
+--- </pre>
---@class vim.NIL
diff --git a/runtime/lua/vim/_meta/json.lua b/runtime/lua/vim/_meta/json.lua
index e010086615..07d89aafc8 100644
--- a/runtime/lua/vim/_meta/json.lua
+++ b/runtime/lua/vim/_meta/json.lua
@@ -5,7 +5,7 @@ vim.json = {}
-- luacheck: no unused args
----@defgroup vim.json
+---@brief
---
--- This module provides encoding and decoding of Lua objects to and
--- from JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua
index 5bd502a7c8..f2239e5e5a 100644
--- a/runtime/lua/vim/_meta/lpeg.lua
+++ b/runtime/lua/vim/_meta/lpeg.lua
@@ -5,22 +5,20 @@ error('Cannot require a meta file')
-- (based on revision 4aded588f9531d89555566bb1de27490354b91c7)
-- with types being renamed to include the vim namespace and with some descriptions made less verbose.
----@defgroup vim.lpeg
----<pre>help
----LPeg is a pattern-matching library for Lua, based on
----Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
+--- @brief <pre>help
+--- LPeg is a pattern-matching library for Lua, based on
+--- Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
---
---- *lua-lpeg*
---- *vim.lpeg.Pattern*
----The LPeg library for parsing expression grammars is included as `vim.lpeg`
----(https://www.inf.puc-rio.br/~roberto/lpeg/).
+--- *lua-lpeg*
+--- *vim.lpeg.Pattern*
+--- The LPeg library for parsing expression grammars is included as `vim.lpeg`
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/).
---
----In addition, its regex-like interface is available as |vim.re|
----(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+--- In addition, its regex-like interface is available as |vim.re|
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
---
----</pre>
+--- </pre>
---- *LPeg* is a new pattern-matching library for Lua, based on [Parsing Expression Grammars](https://bford.info/packrat/) (PEGs).
vim.lpeg = {}
--- @class vim.lpeg.Pattern
@@ -88,6 +86,7 @@ function Pattern:match(subject, init) end
--- Returns the string `"pattern"` if the given value is a pattern, otherwise `nil`.
---
+--- @param value vim.lpeg.Pattern|string|integer|boolean|table|function
--- @return "pattern"|nil
function vim.lpeg.type(value) end
diff --git a/runtime/lua/vim/_meta/mpack.lua b/runtime/lua/vim/_meta/mpack.lua
index 54e097ad97..3970341b78 100644
--- a/runtime/lua/vim/_meta/mpack.lua
+++ b/runtime/lua/vim/_meta/mpack.lua
@@ -2,14 +2,17 @@
-- luacheck: no unused args
---- @defgroup vim.mpack
+--- @brief
---
--- This module provides encoding and decoding of Lua objects to and
--- from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
--- Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
--- @param str string
+--- @return any
function vim.mpack.decode(str) end
--- Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
+--- @param obj any
+--- @return string
function vim.mpack.encode(obj) end
diff --git a/runtime/lua/vim/_meta/re.lua b/runtime/lua/vim/_meta/re.lua
index 4f254b19a0..14c94c7824 100644
--- a/runtime/lua/vim/_meta/re.lua
+++ b/runtime/lua/vim/_meta/re.lua
@@ -7,15 +7,12 @@ error('Cannot require a meta file')
-- Copyright © 2007-2023 Lua.org, PUC-Rio.
-- See 'lpeg.html' for license
---- @defgroup vim.re
----<pre>help
----The `vim.re` module provides a conventional regex-like syntax for pattern usage
----within LPeg |vim.lpeg|.
+--- @brief
+--- The `vim.re` module provides a conventional regex-like syntax for pattern usage
+--- within LPeg |vim.lpeg|.
---
----See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
----documentation including regex syntax and more concrete examples.
----
----</pre>
+--- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
+--- documentation including regex syntax and more concrete examples.
--- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define
--- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used
diff --git a/runtime/lua/vim/_meta/regex.lua b/runtime/lua/vim/_meta/regex.lua
index 58aa2be8c2..ab403b97e7 100644
--- a/runtime/lua/vim/_meta/regex.lua
+++ b/runtime/lua/vim/_meta/regex.lua
@@ -2,8 +2,6 @@
-- luacheck: no unused args
---- @defgroup vim.regex
----
--- @brief Vim regexes can be used directly from Lua. Currently they only allow
--- matching within a single line.
diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua
index b83a8dd4b1..f1fed50c6d 100644
--- a/runtime/lua/vim/_options.lua
+++ b/runtime/lua/vim/_options.lua
@@ -1,12 +1,10 @@
----@defgroup lua-vimscript
+--- @brief Nvim Lua provides an interface or "bridge" to Vimscript variables and
+--- functions, and editor commands and options.
---
----@brief Nvim Lua provides an interface or "bridge" to Vimscript variables and
----functions, and editor commands and options.
----
----Objects passed over this bridge are COPIED (marshalled): there are no
----"references". |lua-guide-variables| For example, using \`vim.fn.remove()\` on
----a Lua list copies the list object to Vimscript and does NOT modify the Lua
----list:
+--- Objects passed over this bridge are COPIED (marshalled): there are no
+--- "references". |lua-guide-variables| For example, using `vim.fn.remove()` on
+--- a Lua list copies the list object to Vimscript and does NOT modify the Lua
+--- list:
---
--- ```lua
--- local list = { 1, 2, 3 }
@@ -14,86 +12,85 @@
--- vim.print(list) --> "{ 1, 2, 3 }"
--- ```
----@addtogroup lua-vimscript
----@brief <pre>help
----vim.call({func}, {...}) *vim.call()*
---- Invokes |vim-function| or |user-function| {func} with arguments {...}.
---- See also |vim.fn|.
---- Equivalent to: >lua
---- vim.fn[func]({...})
----<
----vim.cmd({command})
---- See |vim.cmd()|.
----
----vim.fn.{func}({...}) *vim.fn*
---- Invokes |vim-function| or |user-function| {func} with arguments {...}.
---- To call autoload functions, use the syntax: >lua
---- vim.fn['some\#function']({...})
----<
---- Unlike vim.api.|nvim_call_function()| this converts directly between Vim
---- objects and Lua objects. If the Vim function returns a float, it will be
---- represented directly as a Lua number. Empty lists and dictionaries both
---- are represented by an empty table.
----
---- Note: |v:null| values as part of the return value is represented as
---- |vim.NIL| special value
----
---- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
---- enumerates functions that were called at least once.
----
---- Note: The majority of functions cannot run in |api-fast| callbacks with some
---- undocumented exceptions which are allowed.
----
---- *lua-vim-variables*
----The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
----from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
----described below. In this way you can easily read and modify global Vimscript
----variables from Lua.
----
----Example: >lua
----
---- vim.g.foo = 5 -- Set the g:foo Vimscript variable.
---- print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
---- vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
---- vim.b[2].foo = 6 -- Set b:foo for buffer 2
----<
----
----Note that setting dictionary fields directly will not write them back into
----Nvim. This is because the index into the namespace simply returns a copy.
----Instead the whole dictionary must be written as one. This can be achieved by
----creating a short-lived temporary.
----
----Example: >lua
----
---- vim.g.my_dict.field1 = 'value' -- Does not work
----
---- local my_dict = vim.g.my_dict --
---- my_dict.field1 = 'value' -- Instead do
---- vim.g.my_dict = my_dict --
----
----vim.g *vim.g*
---- Global (|g:|) editor variables.
---- Key with no value returns `nil`.
----
----vim.b *vim.b*
---- Buffer-scoped (|b:|) variables for the current buffer.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific buffer.
----
----vim.w *vim.w*
---- Window-scoped (|w:|) variables for the current window.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific window.
----
----vim.t *vim.t*
---- Tabpage-scoped (|t:|) variables for the current tabpage.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific tabpage.
----
----vim.v *vim.v*
---- |v:| variables.
---- Invalid or unset key returns `nil`.
----</pre>
+--- @brief <pre>help
+--- vim.call({func}, {...}) *vim.call()*
+--- Invokes |vim-function| or |user-function| {func} with arguments {...}.
+--- See also |vim.fn|.
+--- Equivalent to: >lua
+--- vim.fn[func]({...})
+--- <
+--- vim.cmd({command})
+--- See |vim.cmd()|.
+---
+--- vim.fn.{func}({...}) *vim.fn*
+--- Invokes |vim-function| or |user-function| {func} with arguments {...}.
+--- To call autoload functions, use the syntax: >lua
+--- vim.fn['some#function']({...})
+--- <
+--- Unlike vim.api.|nvim_call_function()| this converts directly between Vim
+--- objects and Lua objects. If the Vim function returns a float, it will be
+--- represented directly as a Lua number. Empty lists and dictionaries both
+--- are represented by an empty table.
+---
+--- Note: |v:null| values as part of the return value is represented as
+--- |vim.NIL| special value
+---
+--- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
+--- enumerates functions that were called at least once.
+---
+--- Note: The majority of functions cannot run in |api-fast| callbacks with some
+--- undocumented exceptions which are allowed.
+---
+--- *lua-vim-variables*
+--- The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
+--- from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
+--- described below. In this way you can easily read and modify global Vimscript
+--- variables from Lua.
+---
+--- Example: >lua
+---
+--- vim.g.foo = 5 -- Set the g:foo Vimscript variable.
+--- print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
+--- vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
+--- vim.b[2].foo = 6 -- Set b:foo for buffer 2
+--- <
+---
+--- Note that setting dictionary fields directly will not write them back into
+--- Nvim. This is because the index into the namespace simply returns a copy.
+--- Instead the whole dictionary must be written as one. This can be achieved by
+--- creating a short-lived temporary.
+---
+--- Example: >lua
+---
+--- vim.g.my_dict.field1 = 'value' -- Does not work
+---
+--- local my_dict = vim.g.my_dict --
+--- my_dict.field1 = 'value' -- Instead do
+--- vim.g.my_dict = my_dict --
+---
+--- vim.g *vim.g*
+--- Global (|g:|) editor variables.
+--- Key with no value returns `nil`.
+---
+--- vim.b *vim.b*
+--- Buffer-scoped (|b:|) variables for the current buffer.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific buffer.
+---
+--- vim.w *vim.w*
+--- Window-scoped (|w:|) variables for the current window.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific window.
+---
+--- vim.t *vim.t*
+--- Tabpage-scoped (|t:|) variables for the current tabpage.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific tabpage.
+---
+--- vim.v *vim.v*
+--- |v:| variables.
+--- Invalid or unset key returns `nil`.
+--- </pre>
local api = vim.api
@@ -142,7 +139,6 @@ end
--- vim.env.FOO = 'bar'
--- print(vim.env.TERM)
--- ```
----
---@param var string
vim.env = setmetatable({}, {
__index = function(_, k)
@@ -205,31 +201,30 @@ local function new_win_opt_accessor(winid, bufnr)
})
end
----@addtogroup lua-vimscript
----@brief <pre>help
----` ` *lua-options*
---- *lua-vim-options*
---- *lua-vim-set*
---- *lua-vim-setlocal*
+--- @brief <pre>help
+--- *lua-options*
+--- *lua-vim-options*
+--- *lua-vim-set*
+--- *lua-vim-setlocal*
---
----Vim options can be accessed through |vim.o|, which behaves like Vimscript
----|:set|.
+--- Vim options can be accessed through |vim.o|, which behaves like Vimscript
+--- |:set|.
---
---- Examples: ~
+--- Examples: ~
---
---- To set a boolean toggle:
---- Vimscript: `set number`
---- Lua: `vim.o.number = true`
+--- To set a boolean toggle:
+--- Vimscript: `set number`
+--- Lua: `vim.o.number = true`
---
---- To set a string value:
---- Vimscript: `set wildignore=*.o,*.a,__pycache__`
---- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
+--- To set a string value:
+--- Vimscript: `set wildignore=*.o,*.a,__pycache__`
+--- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
---
----Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
----window-scoped options. Note that this must NOT be confused with
----|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
----global value of a |global-local| option, see |:setglobal|.
----</pre>
+--- Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
+--- window-scoped options. Note that this must NOT be confused with
+--- |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
+--- global value of a |global-local| option, see |:setglobal|.
+--- </pre>
--- Get or set |options|. Like `:set`. Invalid key is an error.
---
@@ -310,13 +305,10 @@ vim.bo = new_buf_opt_accessor()
--- ```
vim.wo = new_win_opt_accessor()
----@brief [[
--- vim.opt, vim.opt_local and vim.opt_global implementation
---
--- To be used as helpers for working with options within neovim.
--- For information on how to use, see :help vim.opt
----
----@brief ]]
--- Preserves the order and does not mutate the original list
local function remove_duplicate_values(t)
@@ -739,74 +731,73 @@ local function create_option_accessor(scope)
})
end
----@addtogroup lua-vimscript
----@brief <pre>help
----` ` *vim.opt_local*
---- *vim.opt_global*
---- *vim.opt*
----
----
----A special interface |vim.opt| exists for conveniently interacting with list-
----and map-style option from Lua: It allows accessing them as Lua tables and
----offers object-oriented method for adding and removing entries.
----
---- Examples: ~
----
---- The following methods of setting a list-style option are equivalent:
---- In Vimscript: >vim
---- set wildignore=*.o,*.a,__pycache__
----<
---- In Lua using `vim.o`: >lua
---- vim.o.wildignore = '*.o,*.a,__pycache__'
----<
---- In Lua using `vim.opt`: >lua
---- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
----<
---- To replicate the behavior of |:set+=|, use: >lua
----
---- vim.opt.wildignore:append { "*.pyc", "node_modules" }
----<
---- To replicate the behavior of |:set^=|, use: >lua
----
---- vim.opt.wildignore:prepend { "new_first_value" }
----<
---- To replicate the behavior of |:set-=|, use: >lua
----
---- vim.opt.wildignore:remove { "node_modules" }
----<
---- The following methods of setting a map-style option are equivalent:
---- In Vimscript: >vim
---- set listchars=space:_,tab:>~
----<
---- In Lua using `vim.o`: >lua
---- vim.o.listchars = 'space:_,tab:>~'
----<
---- In Lua using `vim.opt`: >lua
---- vim.opt.listchars = { space = '_', tab = '>~' }
----<
----
----Note that |vim.opt| returns an `Option` object, not the value of the option,
----which is accessed through |vim.opt:get()|:
----
---- Examples: ~
----
---- The following methods of getting a list-style option are equivalent:
---- In Vimscript: >vim
---- echo wildignore
----<
---- In Lua using `vim.o`: >lua
---- print(vim.o.wildignore)
----<
---- In Lua using `vim.opt`: >lua
---- vim.print(vim.opt.wildignore:get())
----<
----
----In any of the above examples, to replicate the behavior |:setlocal|, use
----`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
----`vim.opt_global`.
----</pre>
-
---- @diagnostic disable-next-line:unused-local used for gen_vimdoc
+--- @brief <pre>help
+--- *vim.opt_local*
+--- *vim.opt_global*
+--- *vim.opt*
+---
+---
+--- A special interface |vim.opt| exists for conveniently interacting with list-
+--- and map-style option from Lua: It allows accessing them as Lua tables and
+--- offers object-oriented method for adding and removing entries.
+---
+--- Examples: ~
+---
+--- The following methods of setting a list-style option are equivalent:
+--- In Vimscript: >vim
+--- set wildignore=*.o,*.a,__pycache__
+--- <
+--- In Lua using `vim.o`: >lua
+--- vim.o.wildignore = '*.o,*.a,__pycache__'
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
+--- <
+--- To replicate the behavior of |:set+=|, use: >lua
+---
+--- vim.opt.wildignore:append { "*.pyc", "node_modules" }
+--- <
+--- To replicate the behavior of |:set^=|, use: >lua
+---
+--- vim.opt.wildignore:prepend { "new_first_value" }
+--- <
+--- To replicate the behavior of |:set-=|, use: >lua
+---
+--- vim.opt.wildignore:remove { "node_modules" }
+--- <
+--- The following methods of setting a map-style option are equivalent:
+--- In Vimscript: >vim
+--- set listchars=space:_,tab:>~
+--- <
+--- In Lua using `vim.o`: >lua
+--- vim.o.listchars = 'space:_,tab:>~'
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.opt.listchars = { space = '_', tab = '>~' }
+--- <
+---
+--- Note that |vim.opt| returns an `Option` object, not the value of the option,
+--- which is accessed through |vim.opt:get()|:
+---
+--- Examples: ~
+---
+--- The following methods of getting a list-style option are equivalent:
+--- In Vimscript: >vim
+--- echo wildignore
+--- <
+--- In Lua using `vim.o`: >lua
+--- print(vim.o.wildignore)
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.print(vim.opt.wildignore:get())
+--- <
+---
+--- In any of the above examples, to replicate the behavior |:setlocal|, use
+--- `vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
+--- `vim.opt_global`.
+--- </pre>
+
+--- @class vim.Option
local Option = {} -- luacheck: no unused
--- Returns a Lua-representation of the option. Boolean, number and string
@@ -856,9 +847,7 @@ local Option = {} -- luacheck: no unused
--- print("J is enabled!")
--- end
--- ```
----
---@return string|integer|boolean|nil value of option
----@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:get() end
--- Append a value to string-style options. See |:set+=|
@@ -869,7 +858,6 @@ function Option:get() end
--- vim.opt.formatoptions:append('j')
--- vim.opt.formatoptions = vim.opt.formatoptions + 'j'
--- ```
----
---@param value string Value to append
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:append(value) end -- luacheck: no unused
@@ -882,7 +870,6 @@ function Option:append(value) end -- luacheck: no unused
--- vim.opt.wildignore:prepend('*.o')
--- vim.opt.wildignore = vim.opt.wildignore ^ '*.o'
--- ```
----
---@param value string Value to prepend
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:prepend(value) end -- luacheck: no unused
@@ -895,7 +882,6 @@ function Option:prepend(value) end -- luacheck: no unused
--- vim.opt.wildignore:remove('*.pyc')
--- vim.opt.wildignore = vim.opt.wildignore - '*.pyc'
--- ```
----
---@param value string Value to remove
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:remove(value) end -- luacheck: no unused
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 91f91b5879..49165c4db9 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -70,6 +70,7 @@ local M = {}
--- @field linehl? table<vim.diagnostic.Severity,string>
--- @field texthl? table<vim.diagnostic.Severity,string>
+--- @nodoc
--- @enum vim.diagnostic.Severity
M.severity = {
ERROR = 1,
@@ -107,6 +108,7 @@ local global_diagnostic_options = {
--- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved)
--- @field hide? fun(namespace:integer, bufnr:integer)
+--- @nodoc
--- @type table<string,vim.diagnostic.Handler>
M.handlers = setmetatable({}, {
__newindex = function(t, name, handler)
@@ -731,71 +733,71 @@ end
--- - `function`: Function with signature (namespace, bufnr) that returns any of the above.
---
---@param opts vim.diagnostic.Opts? (table?) When omitted or "nil", retrieve the current
---- configuration. Otherwise, a configuration table with the following keys:
+--- configuration. Otherwise, a configuration table with the following keys:
--- - underline: (default true) Use underline for diagnostics. Options:
---- * severity: Only underline diagnostics matching the given
---- severity |diagnostic-severity|
+--- * severity: Only underline diagnostics matching the given
+--- severity |diagnostic-severity|
--- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics
---- are set for a namespace, one prefix per diagnostic + the last diagnostic
---- message are shown. In addition to the options listed below, the
---- "virt_text" options of |nvim_buf_set_extmark()| may also be used here
---- (e.g. "virt_text_pos" and "hl_mode").
---- Options:
---- * severity: Only show virtual text for diagnostics matching the given
---- severity |diagnostic-severity|
---- * source: (boolean or string) Include the diagnostic source in virtual
---- text. Use "if_many" to only show sources if there is more than
---- one diagnostic source in the buffer. Otherwise, any truthy value
---- means to always show the diagnostic source.
---- * spacing: (number) Amount of empty spaces inserted at the beginning
---- of the virtual text.
---- * prefix: (string or function) prepend diagnostic message with prefix.
---- If a function, it must have the signature (diagnostic, i, total)
---- -> string, where {diagnostic} is of type |diagnostic-structure|,
---- {i} is the index of the diagnostic being evaluated, and {total}
---- is the total number of diagnostics for the line. This can be
---- used to render diagnostic symbols or error codes.
---- * suffix: (string or function) Append diagnostic message with suffix.
---- If a function, it must have the signature (diagnostic) ->
---- string, where {diagnostic} is of type |diagnostic-structure|.
---- This can be used to render an LSP diagnostic error code.
---- * format: (function) A function that takes a diagnostic as input and
---- returns a string. The return value is the text used to display
---- the diagnostic. Example:
---- <pre>lua
---- function(diagnostic)
---- if diagnostic.severity == vim.diagnostic.severity.ERROR then
---- return string.format("E: %s", diagnostic.message)
---- end
---- return diagnostic.message
---- end
---- </pre>
+--- are set for a namespace, one prefix per diagnostic + the last diagnostic
+--- message are shown. In addition to the options listed below, the
+--- "virt_text" options of |nvim_buf_set_extmark()| may also be used here
+--- (e.g. "virt_text_pos" and "hl_mode").
+--- Options:
+--- * severity: Only show virtual text for diagnostics matching the given
+--- severity |diagnostic-severity|
+--- * source: (boolean or string) Include the diagnostic source in virtual
+--- text. Use "if_many" to only show sources if there is more than
+--- one diagnostic source in the buffer. Otherwise, any truthy value
+--- means to always show the diagnostic source.
+--- * spacing: (number) Amount of empty spaces inserted at the beginning
+--- of the virtual text.
+--- * prefix: (string or function) prepend diagnostic message with prefix.
+--- If a function, it must have the signature (diagnostic, i, total)
+--- -> string, where {diagnostic} is of type |diagnostic-structure|,
+--- {i} is the index of the diagnostic being evaluated, and {total}
+--- is the total number of diagnostics for the line. This can be
+--- used to render diagnostic symbols or error codes.
+--- * suffix: (string or function) Append diagnostic message with suffix.
+--- If a function, it must have the signature (diagnostic) ->
+--- string, where {diagnostic} is of type |diagnostic-structure|.
+--- This can be used to render an LSP diagnostic error code.
+--- * format: (function) A function that takes a diagnostic as input and
+--- returns a string. The return value is the text used to display
+--- the diagnostic. Example:
+--- ```lua
+--- function(diagnostic)
+--- if diagnostic.severity == vim.diagnostic.severity.ERROR then
+--- return string.format("E: %s", diagnostic.message)
+--- end
+--- return diagnostic.message
+--- end
+--- ```
--- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options:
---- * severity: Only show signs for diagnostics matching the given
---- severity |diagnostic-severity|
---- * priority: (number, default 10) Base priority to use for signs. When
---- {severity_sort} is used, the priority of a sign is adjusted based on
---- its severity. Otherwise, all signs use the same priority.
---- * text: (table) A table mapping |diagnostic-severity| to the sign text
---- to display in the sign column. The default is to use "E", "W", "I", and "H"
---- for errors, warnings, information, and hints, respectively. Example:
---- <pre>lua
---- vim.diagnostic.config({
---- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
---- })
---- </pre>
---- * numhl: (table) A table mapping |diagnostic-severity| to the highlight
---- group used for the line number where the sign is placed.
---- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group
---- used for the whole line the sign is placed in.
+--- * severity: Only show signs for diagnostics matching the given
+--- severity |diagnostic-severity|
+--- * priority: (number, default 10) Base priority to use for signs. When
+--- {severity_sort} is used, the priority of a sign is adjusted based on
+--- its severity. Otherwise, all signs use the same priority.
+--- * text: (table) A table mapping |diagnostic-severity| to the sign text
+--- to display in the sign column. The default is to use "E", "W", "I", and "H"
+--- for errors, warnings, information, and hints, respectively. Example:
+--- ```lua
+--- vim.diagnostic.config({
+--- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
+--- })
+--- ```
+--- * numhl: (table) A table mapping |diagnostic-severity| to the highlight
+--- group used for the line number where the sign is placed.
+--- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group
+--- used for the whole line the sign is placed in.
--- - float: Options for floating windows. See |vim.diagnostic.open_float()|.
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
--- diagnostics are updated on InsertLeave)
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
---- which signs and virtual text are displayed. When true, higher severities
---- are displayed before lower severities (e.g. ERROR is displayed before WARN).
---- Options:
---- * reverse: (boolean) Reverse sort order
+--- which signs and virtual text are displayed. When true, higher severities
+--- are displayed before lower severities (e.g. ERROR is displayed before WARN).
+--- Options:
+--- * reverse: (boolean) Reverse sort order
---
---@param namespace integer? Update the options for the given namespace. When omitted, update the
--- global diagnostic options.
@@ -1090,8 +1092,8 @@ M.handlers.signs = {
api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name))
end
- --- Handle legacy diagnostic sign definitions
- --- These were deprecated in 0.10 and will be removed in 0.12
+ -- Handle legacy diagnostic sign definitions
+ -- These were deprecated in 0.10 and will be removed in 0.12
if opts.signs and not opts.signs.text and not opts.signs.numhl and not opts.signs.texthl then
for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do
local name = string.format('DiagnosticSign%s', v)
@@ -1543,7 +1545,8 @@ end
--- Overrides the setting from |vim.diagnostic.config()|.
--- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of
--- prepending it. Overrides the setting from |vim.diagnostic.config()|.
----@return integer?, integer?: ({float_bufnr}, {win_id})
+---@return integer? float_bufnr
+---@return integer? win_id
function M.open_float(opts, ...)
-- Support old (bufnr, opts) signature
local bufnr --- @type integer?
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index b43072a725..e7971d8916 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -2279,9 +2279,9 @@ end
--- Perform filetype detection.
---
--- The filetype can be detected using one of three methods:
---- 1. Using an existing buffer
---- 2. Using only a file name
---- 3. Using only file contents
+--- 1. Using an existing buffer
+--- 2. Using only a file name
+--- 3. Using only file contents
---
--- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and
--- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index 22612a7255..0af5fc4f30 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -320,7 +320,7 @@ end
--- Normalize a path to a standard format. A tilde (~) character at the
--- beginning of the path is expanded to the user's home directory and any
---- backslash (\\) characters are converted to forward slashes (/). Environment
+--- backslash (\) characters are converted to forward slashes (/). Environment
--- variables are also expanded.
---
--- Examples:
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index b055cce49d..effe280dee 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -1,4 +1,4 @@
----@defgroup vim.highlight
+---@brief
---
--- Nvim includes a function for highlighting a selection on yank.
---
@@ -19,18 +19,19 @@
--- ```vim
--- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
--- ```
+---
local api = vim.api
local M = {}
--- Table with default priorities used for highlighting:
---- - `syntax`: `50`, used for standard syntax highlighting
---- - `treesitter`: `100`, used for treesitter-based highlighting
---- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
---- - `diagnostics`: `150`, used for code analysis such as diagnostics
---- - `user`: `200`, used for user-triggered highlights such as LSP document
---- symbols or `on_yank` autocommands
+--- - `syntax`: `50`, used for standard syntax highlighting
+--- - `treesitter`: `100`, used for treesitter-based highlighting
+--- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
+--- - `diagnostics`: `150`, used for code analysis such as diagnostics
+--- - `user`: `200`, used for user-triggered highlights such as LSP document
+--- symbols or `on_yank` autocommands
M.priorities = {
syntax = 50,
treesitter = 100,
diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua
index d720745110..798428014d 100644
--- a/runtime/lua/vim/iter.lua
+++ b/runtime/lua/vim/iter.lua
@@ -1,4 +1,4 @@
----@defgroup vim.iter
+--- @brief
---
--- \*vim.iter()\* is an interface for |iterable|s: it wraps a table or function argument into an
--- \*Iter\* object with methods (such as |Iter:filter()| and |Iter:map()|) that transform the
@@ -66,6 +66,7 @@
---@class IterMod
---@operator call:Iter
+
local M = {}
---@class Iter
@@ -599,7 +600,7 @@ end
--- -- 12
---
--- ```
----
+---@param f any
---@return any
function Iter.find(self, f)
if type(f) ~= 'function' then
@@ -645,6 +646,7 @@ end
---
---@see Iter.find
---
+---@param f any
---@return any
---@diagnostic disable-next-line: unused-local
function Iter.rfind(self, f) -- luacheck: no unused args
@@ -724,6 +726,7 @@ function Iter.nextback(self) -- luacheck: no unused args
error('nextback() requires a list-like table')
end
+--- @nodoc
function ListIter.nextback(self)
if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1
@@ -754,6 +757,7 @@ function Iter.peekback(self) -- luacheck: no unused args
error('peekback() requires a list-like table')
end
+---@nodoc
function ListIter.peekback(self)
if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index 8e4e123fe0..84e9b4197d 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -90,6 +90,8 @@ end
--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
--- ```
---
+---@param modes string|string[]
+---@param lhs string
---@param opts table|nil A table of optional arguments:
--- - "buffer": (integer|boolean) Remove a mapping from the given buffer.
--- When `0` or `true`, use the current buffer.
diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua
index ec99e417c2..5f3da55544 100644
--- a/runtime/lua/vim/loader.lua
+++ b/runtime/lua/vim/loader.lua
@@ -190,7 +190,6 @@ function Loader.loader_lib(modname)
local sysname = uv.os_uname().sysname:lower() or ''
local is_win = sysname:find('win', 1, true) and not sysname:find('darwin', 1, true)
local ret = M.find(modname, { patterns = is_win and { '.dll' } or { '.so' } })[1]
- ---@type function?, string?
if ret then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
-- a) strip prefix up to and including the first dash, if any
@@ -208,15 +207,13 @@ end
--- `loadfile` using the cache
--- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible.
---@param filename? string
----@param mode? "b"|"t"|"bt"
+---@param _mode? "b"|"t"|"bt"
---@param env? table
---@return function?, string? error_message
---@private
--- luacheck: ignore 312
-function Loader.loadfile(filename, mode, env)
+function Loader.loadfile(filename, _mode, env)
-- ignore mode, since we byte-compile the Lua source files
- mode = nil
- return Loader.load(normalize(filename), { mode = mode, env = env })
+ return Loader.load(normalize(filename), { env = env })
end
--- Checks whether two cache hashes are the same based on:
@@ -273,14 +270,14 @@ end
--- Finds Lua modules for the given module name.
---@param modname string Module name, or `"*"` to find the top-level modules instead
----@param opts? ModuleFindOpts (table|nil) Options for finding a module:
+---@param opts? ModuleFindOpts (table) Options for finding a module:
--- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`)
--- - paths: (string[]) Extra paths to search for modname (defaults to `{}`)
--- - patterns: (string[]) List of patterns to use when searching for modules.
--- A pattern is a string added to the basename of the Lua module being searched.
--- (defaults to `{"/init.lua", ".lua"}`)
--- - all: (boolean) Return all matches instead of just the first one (defaults to `false`)
----@return ModuleInfo[] (list) A list of results with the following properties:
+---@return ModuleInfo[] (table) A list of results with the following properties:
--- - modpath: (string) the path to the module
--- - modname: (string) the name of the module
--- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"`
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 3a74c3ee90..19497e40dc 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -206,99 +206,96 @@ end
--- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
---
--- - Methods:
----
---- - request(method, params, [handler], bufnr)
---- Sends a request to the server.
---- This is a thin wrapper around {client.rpc.request} with some additional
---- checking.
---- If {handler} is not specified, If one is not found there, then an error will occur.
---- Returns: {status}, {[client_id]}. {status} is a boolean indicating if
---- the notification was successful. If it is `false`, then it will always
---- be `false` (the client has shutdown).
---- If {status} is `true`, the function returns {request_id} as the second
---- result. You can use this with `client.cancel_request(request_id)`
---- to cancel the request.
----
---- - request_sync(method, params, timeout_ms, bufnr)
---- Sends a request to the server and synchronously waits for the response.
---- This is a wrapper around {client.request}
---- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
---- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
---- string describing the failure reason. If the request was unsuccessful returns `nil`.
----
---- - notify(method, params)
---- Sends a notification to an LSP server.
---- Returns: a boolean to indicate if the notification was successful. If
---- it is false, then it will always be false (the client has shutdown).
----
---- - cancel_request(id)
---- Cancels a request with a given request id.
---- Returns: same as `notify()`.
----
---- - stop([force])
---- Stops a client, optionally with force.
---- By default, it will just ask the server to shutdown without force.
---- If you request to stop a client which has previously been requested to
---- shutdown, it will automatically escalate and force shutdown.
----
---- - is_stopped()
---- Checks whether a client is stopped.
---- Returns: true if the client is fully stopped.
----
---- - on_attach(client, bufnr)
---- Runs the on_attach function from the client's config if it was defined.
---- Useful for buffer-local setup.
----
---- - supports_method(method, [opts]): boolean
---- Checks if a client supports a given method.
---- Always returns true for unknown off-spec methods.
---- [opts] is a optional `{bufnr?: integer}` table.
---- Some language server capabilities can be file specific.
+--- - request(method, params, [handler], bufnr)
+--- Sends a request to the server.
+--- This is a thin wrapper around {client.rpc.request} with some additional
+--- checking.
+--- If {handler} is not specified, If one is not found there, then an error will occur.
+--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if
+--- the notification was successful. If it is `false`, then it will always
+--- be `false` (the client has shutdown).
+--- If {status} is `true`, the function returns {request_id} as the second
+--- result. You can use this with `client.cancel_request(request_id)`
+--- to cancel the request.
+---
+--- - request_sync(method, params, timeout_ms, bufnr)
+--- Sends a request to the server and synchronously waits for the response.
+--- This is a wrapper around {client.request}
+--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
+--- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
+--- string describing the failure reason. If the request was unsuccessful returns `nil`.
+---
+--- - notify(method, params)
+--- Sends a notification to an LSP server.
+--- Returns: a boolean to indicate if the notification was successful. If
+--- it is false, then it will always be false (the client has shutdown).
+---
+--- - cancel_request(id)
+--- Cancels a request with a given request id.
+--- Returns: same as `notify()`.
+---
+--- - stop([force])
+--- Stops a client, optionally with force.
+--- By default, it will just ask the server to shutdown without force.
+--- If you request to stop a client which has previously been requested to
+--- shutdown, it will automatically escalate and force shutdown.
+---
+--- - is_stopped()
+--- Checks whether a client is stopped.
+--- Returns: true if the client is fully stopped.
+---
+--- - on_attach(client, bufnr)
+--- Runs the on_attach function from the client's config if it was defined.
+--- Useful for buffer-local setup.
+---
+--- - supports_method(method, [opts]): boolean
+--- Checks if a client supports a given method.
+--- Always returns true for unknown off-spec methods.
+--- [opts] is a optional `{bufnr?: integer}` table.
+--- Some language server capabilities can be file specific.
---
--- - Members
---- - {id} (number): The id allocated to the client.
+--- - {id} (number): The id allocated to the client.
---
---- - {name} (string): If a name is specified on creation, that will be
---- used. Otherwise it is just the client id. This is used for
---- logs and messages.
+--- - {name} (string): If a name is specified on creation, that will be
+--- used. Otherwise it is just the client id. This is used for
+--- logs and messages.
---
---- - {rpc} (table): RPC client object, for low level interaction with the
---- client. See |vim.lsp.rpc.start()|.
+--- - {rpc} (table): RPC client object, for low level interaction with the
+--- client. See |vim.lsp.rpc.start()|.
---
---- - {offset_encoding} (string): The encoding used for communicating
---- with the server. You can modify this in the `config`'s `on_init` method
---- before text is sent to the server.
+--- - {offset_encoding} (string): The encoding used for communicating
+--- with the server. You can modify this in the `config`'s `on_init` method
+--- before text is sent to the server.
---
---- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
+--- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
---
---- - {commands} (table): Table of command name to function which is called if
---- any LSP action (code action, code lenses, ...) triggers the command.
---- Client commands take precedence over the global command registry.
+--- - {commands} (table): Table of command name to function which is called if
+--- any LSP action (code action, code lenses, ...) triggers the command.
+--- Client commands take precedence over the global command registry.
---
---- - {requests} (table): The current pending requests in flight
---- to the server. Entries are key-value pairs with the key
---- being the request ID while the value is a table with `type`,
---- `bufnr`, and `method` key-value pairs. `type` is either "pending"
---- for an active request, or "cancel" for a cancel request. It will
---- be "complete" ephemerally while executing |LspRequest| autocmds
---- when replies are received from the server.
+--- - {requests} (table): The current pending requests in flight
+--- to the server. Entries are key-value pairs with the key
+--- being the request ID while the value is a table with `type`,
+--- `bufnr`, and `method` key-value pairs. `type` is either "pending"
+--- for an active request, or "cancel" for a cancel request. It will
+--- be "complete" ephemerally while executing |LspRequest| autocmds
+--- when replies are received from the server.
---
---- - {config} (table): Reference of the table that was passed by the user
---- to |vim.lsp.start_client()|.
+--- - {config} (table): Reference of the table that was passed by the user
+--- to |vim.lsp.start_client()|.
---
---- - {server_capabilities} (table): Response from the server sent on
---- `initialize` describing the server's capabilities.
+--- - {server_capabilities} (table): Response from the server sent on
+--- `initialize` describing the server's capabilities.
---
---- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages
---- sent by the server.
+--- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages
+--- sent by the server.
---
---- - {settings} Map with language server specific settings.
---- See {config} in |vim.lsp.start_client()|
+--- - {settings} Map with language server specific settings.
+--- See {config} in |vim.lsp.start_client()|
---
---- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()|
-function lsp.client()
- error()
-end
+--- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()|
+lsp.client = nil
--- @class lsp.StartOpts
--- @field reuse_client fun(client: lsp.Client, config: table): boolean
@@ -581,9 +578,9 @@ end
--- spawn. Must be specified using a table.
--- Non-string values are coerced to string.
--- Example:
---- <pre>
---- { PORT = 8080; HOST = "0.0.0.0"; }
---- </pre>
+--- ```
+--- { PORT = 8080; HOST = "0.0.0.0"; }
+--- ```
---
--- - detached: (boolean, default true) Daemonize the server process so that it runs in a
--- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to
@@ -598,8 +595,9 @@ end
--- \|vim.lsp.protocol.make_client_capabilities()|, passed to the language
--- server on initialization. Hint: use make_client_capabilities() and modify
--- its result.
---- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
---- array.
+---
+--- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
+--- array.
---
--- - handlers: Map of language server method names to |lsp-handler|
---
@@ -645,9 +643,9 @@ end
---
--- - on_exit Callback (code, signal, client_id) invoked on client
--- exit.
---- - code: exit code of the process
---- - signal: number describing the signal used to terminate (if any)
---- - client_id: client handle
+--- - code: exit code of the process
+--- - signal: number describing the signal used to terminate (if any)
+--- - client_id: client handle
---
--- - on_attach: Callback (client, bufnr) invoked when client
--- attaches to a buffer.
@@ -656,13 +654,13 @@ end
--- server in the initialize request. Invalid/empty values will default to "off"
---
--- - flags: A table with flags for the client. The current (experimental) flags are:
---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
---- - debounce_text_changes (number, default 150): Debounce didChange
---- notifications to the server by the given number in milliseconds. No debounce
---- occurs if nil
---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
---- exit cleanly after sending the "shutdown" request before sending kill -15.
---- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
+--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
+--- - debounce_text_changes (number, default 150): Debounce didChange
+--- notifications to the server by the given number in milliseconds. No debounce
+--- occurs if nil
+--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
+--- exit cleanly after sending the "shutdown" request before sending kill -15.
+--- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
---
--- - root_dir: (string) Directory where the LSP
--- server will base its workspaceFolders, rootUri, and rootPath
@@ -1239,7 +1237,7 @@ end
---
--- Currently only supports a single client. This can be set via
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
---- via ``vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'``.
+--- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
---
---@param opts table options for customizing the formatting expression which takes the
--- following optional keys:
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 7fc5286a78..d2e92de083 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -12,7 +12,7 @@ local M = {}
---@param method (string) LSP method name
---@param params (table|nil) Parameters to send to the server
---@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution|
---
+---
---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs
---for all successful requests.
---@return function _cancel_all_requests Function which can be used to
@@ -172,12 +172,13 @@ end
---
--- - filter (function|nil):
--- Predicate used to filter clients. Receives a client as argument and must return a
---- boolean. Clients matching the predicate are included. Example: <pre>lua
---- -- Never request typescript-language-server for formatting
---- vim.lsp.buf.format {
---- filter = function(client) return client.name ~= "tsserver" end
---- }
---- </pre>
+--- boolean. Clients matching the predicate are included. Example:
+--- ```lua
+--- -- Never request typescript-language-server for formatting
+--- vim.lsp.buf.format {
+--- filter = function(client) return client.name ~= "tsserver" end
+--- }
+--- ```
---
--- - async boolean|nil
--- If true the method won't block. Defaults to false.
@@ -472,6 +473,7 @@ end
--- Add the folder at path to the workspace folders. If {path} is
--- not provided, the user will be prompted for a path using |input()|.
+--- @param workspace_folder? string
function M.add_workspace_folder(workspace_folder)
workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'), 'dir')
@@ -511,6 +513,7 @@ end
--- Remove the folder at path from the workspace folders. If
--- {path} is not provided, the user will be prompted for
--- a path using |input()|.
+--- @param workspace_folder? string
function M.remove_workspace_folder(workspace_folder)
workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'))
@@ -725,15 +728,15 @@ end
---
---@param options table|nil Optional table which holds the following optional fields:
--- - context: (table|nil)
---- Corresponds to `CodeActionContext` of the LSP specification:
---- - diagnostics (table|nil):
---- LSP `Diagnostic[]`. Inferred from the current
---- position if not provided.
---- - only (table|nil):
---- List of LSP `CodeActionKind`s used to filter the code actions.
---- Most language servers support values like `refactor`
---- or `quickfix`.
---- - triggerKind (number|nil): The reason why code actions were requested.
+--- Corresponds to `CodeActionContext` of the LSP specification:
+--- - diagnostics (table|nil):
+--- LSP `Diagnostic[]`. Inferred from the current
+--- position if not provided.
+--- - only (table|nil):
+--- List of LSP `CodeActionKind`s used to filter the code actions.
+--- Most language servers support values like `refactor`
+--- or `quickfix`.
+--- - triggerKind (number|nil): The reason why code actions were requested.
--- - filter: (function|nil)
--- Predicate taking an `CodeAction` and returning a boolean.
--- - apply: (boolean|nil)
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 966c7f4d03..7aed6f99e3 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -258,6 +258,8 @@ end
--- |lsp-handler| for the method `textDocument/codeLens`
---
+---@param err lsp.ResponseError?
+---@param result lsp.CodeLens[]
---@param ctx lsp.HandlerContext
function M.on_codelens(err, result, ctx, _)
if err then
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 33051ab61c..1fa67fc473 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1,5 +1,3 @@
----@brief lsp-diagnostic
-
local protocol = require('vim.lsp.protocol')
local ms = protocol.Methods
@@ -287,6 +285,7 @@ end
--- )
--- ```
---
+---@param _ lsp.ResponseError?
---@param result lsp.PublishDiagnosticsParams
---@param ctx lsp.HandlerContext
---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|).
@@ -319,6 +318,7 @@ end
--- )
--- ```
---
+---@param _ lsp.ResponseError?
---@param result lsp.DocumentDiagnosticReport
---@param ctx lsp.HandlerContext
---@param config table Configuration table (see |vim.diagnostic.config()|).
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index a9da812231..781d720486 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -368,6 +368,8 @@ end
--- )
--- ```
---
+---@param _ lsp.ResponseError?
+---@param result lsp.Hover
---@param ctx lsp.HandlerContext
---@param config table Configuration table.
--- - border: (default=nil)
@@ -464,7 +466,8 @@ M[ms.textDocument_implementation] = location_handler
--- )
--- ```
---
----@param result table Response from the language server
+---@param _ lsp.ResponseError?
+---@param result lsp.SignatureHelp Response from the language server
---@param ctx lsp.HandlerContext Client context
---@param config table Configuration table.
--- - border: (default=nil)
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index a9d49bc8f4..018003bb81 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -165,7 +165,7 @@ end
--- Checks whether the level is sufficient for logging.
---@param level integer log level
----@returns (bool) true if would log, false if not
+---@return bool : true if would log, false if not
function log.should_log(level)
return level >= current_log_level
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index e849bb4f2a..1455ab51fa 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -273,8 +273,6 @@ end
---@field notify_reply_callbacks table<integer, function> dict of message_id to callback
---@field transport vim.lsp.rpc.Transport
---@field dispatchers vim.lsp.rpc.Dispatchers
-
----@class vim.lsp.rpc.Client
local Client = {}
---@private
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index 62fa0b33f4..936579e003 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -53,7 +53,7 @@ local str_utf_end = vim.str_utf_end
---@param line string the line to index into
---@param byte integer the byte idx
---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
---@returns integer the utf idx for the given encoding
+---@return integer utf_idx for the given encoding
local function byte_to_utf(line, byte, offset_encoding)
-- convert to 0 based indexing for str_utfindex
byte = byte - 1
@@ -204,7 +204,7 @@ end
--- Normalized to the next codepoint.
--- prev_end_range is the text range sent to the server representing the changed region.
--- curr_end_range is the text that should be collected and sent to the server.
---
+---
---@param prev_lines string[] list of lines
---@param curr_lines string[] list of lines
---@param start_range vim.lsp.sync.Range
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index b60135f851..e371cb0e15 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -574,6 +574,7 @@ end
---
---@param text_document_edit table: a `TextDocumentEdit` object
---@param index integer: Optional index of the edit, if from a list of edits (or nil, if not from a list)
+---@param offset_encoding? string
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
local text_document = text_document_edit.textDocument
@@ -770,7 +771,7 @@ end
---
---@param workspace_edit table `WorkspaceEdit`
---@param offset_encoding string utf-8|utf-16|utf-32 (required)
---see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
function M.apply_workspace_edit(workspace_edit, offset_encoding)
if offset_encoding == nil then
vim.notify_once(
@@ -1130,6 +1131,7 @@ end
--- - for LocationLink, targetRange is shown (e.g., body of function definition)
---
---@param location table a single `Location` or `LocationLink`
+---@param opts table
---@return integer|nil buffer id of float window
---@return integer|nil window id of float window
function M.preview_location(location, opts)
@@ -1243,6 +1245,7 @@ end
---
--- If you want to open a popup with fancy markdown, use `open_floating_preview` instead
---
+---@param bufnr integer
---@param contents table of lines to show in window
---@param opts table with optional fields
--- - height of floating window
@@ -1603,7 +1606,7 @@ end
---@param contents table of lines to show in window
---@param syntax string of syntax to set for opened buffer
---@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()|
---- before they are passed on to |nvim_open_win()|)
+--- before they are passed on to |nvim_open_win()|)
--- - height: (integer) height of floating window
--- - width: (integer) width of floating window
--- - wrap: (boolean, default true) wrap long lines
@@ -1868,6 +1871,7 @@ end
--- Converts symbols to quickfix list items.
---
---@param symbols table DocumentSymbol[] or SymbolInformation[]
+---@param bufnr integer
function M.symbols_to_items(symbols, bufnr)
local function _symbols_to_items(_symbols, _items, _bufnr)
for _, symbol in ipairs(_symbols) do
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 5cf8390843..83fdfede89 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -6,6 +6,7 @@
-- or the test suite. (Eventually the test suite will be run in a worker process,
-- so this wouldn't be a separate case to consider)
+---@nodoc
---@diagnostic disable-next-line: lowercase-global
vim = vim or {}
@@ -191,8 +192,8 @@ end
---
---@param s string String to split
---@param sep string Separator or pattern
----@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()|
----@return string[] List of split components
+---@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()|
+---@return string[] : List of split components
function vim.split(s, sep, opts)
local t = {}
for c in vim.gsplit(s, sep, opts) do
@@ -206,9 +207,9 @@ end
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@generic T: table
+---@generic T
---@param t table<T, any> (table) Table
----@return T[] (list) List of keys
+---@return T[] : List of keys
function vim.tbl_keys(t)
vim.validate({ t = { t, 't' } })
--- @cast t table<any,any>
@@ -225,7 +226,7 @@ end
---
---@generic T
---@param t table<any, T> (table) Table
----@return T[] (list) List of values
+---@return T[] : List of values
function vim.tbl_values(t)
vim.validate({ t = { t, 't' } })
@@ -243,7 +244,7 @@ end
---@generic T
---@param func fun(value: T): any (function) Function
---@param t table<any, T> (table) Table
----@return table Table of transformed values
+---@return table : Table of transformed values
function vim.tbl_map(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } })
--- @cast t table<any,any>
@@ -260,7 +261,7 @@ end
---@generic T
---@param func fun(value: T): boolean (function) Function
---@param t table<any, T> (table) Table
----@return T[] (table) Table of filtered values
+---@return T[] : Table of filtered values
function vim.tbl_filter(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } })
--- @cast t table<any,any>
@@ -401,7 +402,7 @@ end
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
---@param ... table Two or more tables
----@return table Merged table
+---@return table : Merged table
function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...)
end
@@ -456,7 +457,7 @@ end
--- Add the reverse lookup values to an existing table.
--- For example:
---- ``tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }``
+--- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
---
--- Note that this *modifies* the input.
---@param o table Table to add the reverse to
@@ -493,7 +494,7 @@ end
---
---@param o table Table to index
---@param ... any Optional keys (0 or more, variadic) via which to index the table
----@return any Nested value indexed by key (if it exists), else nil
+---@return any : Nested value indexed by key (if it exists), else nil
function vim.tbl_get(o, ...)
local keys = { ... }
if #keys == 0 then
@@ -519,8 +520,8 @@ end
---@generic T: table
---@param dst T List which will be modified and appended to
---@param src table List from which values will be inserted
----@param start (integer|nil) Start index on src. Defaults to 1
----@param finish (integer|nil) Final index on src. Defaults to `#src`
+---@param start integer? Start index on src. Defaults to 1
+---@param finish integer? Final index on src. Defaults to `#src`
---@return T dst
function vim.list_extend(dst, src, start, finish)
vim.validate({
@@ -666,7 +667,7 @@ end
---
---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
---@param t table Table
----@return integer Number of non-nil values in table
+---@return integer : Number of non-nil values in table
function vim.tbl_count(t)
vim.validate({ t = { t, 't' } })
--- @cast t table<any,any>
@@ -681,10 +682,10 @@ end
--- Creates a copy of a table containing only elements from start to end (inclusive)
---
---@generic T
----@param list T[] (list) Table
+---@param list T[] Table
---@param start integer|nil Start range of slice
---@param finish integer|nil End range of slice
----@return T[] (list) Copy of table sliced from start to finish (inclusive)
+---@return T[] Copy of table sliced from start to finish (inclusive)
function vim.list_slice(list, start, finish)
local new_list = {} --- @type `T`[]
for i = start or 1, finish or #list do
@@ -840,38 +841,37 @@ do
--- Usage example:
---
--- ```lua
- --- function user.new(name, age, hobbies)
- --- vim.validate{
- --- name={name, 'string'},
- --- age={age, 'number'},
- --- hobbies={hobbies, 'table'},
- --- }
- --- ...
- --- end
+ --- function user.new(name, age, hobbies)
+ --- vim.validate{
+ --- name={name, 'string'},
+ --- age={age, 'number'},
+ --- hobbies={hobbies, 'table'},
+ --- }
+ --- ...
+ --- end
--- ```
---
--- Examples with explicit argument values (can be run directly):
---
--- ```lua
- --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
- --- --> NOP (success)
+ --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
+ --- --> NOP (success)
---
- --- vim.validate{arg1={1, 'table'}}
- --- --> error('arg1: expected table, got number')
+ --- vim.validate{arg1={1, 'table'}}
+ --- --> error('arg1: expected table, got number')
---
- --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- --- --> error('arg1: expected even number, got 3')
+ --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ --- --> error('arg1: expected even number, got 3')
--- ```
---
--- If multiple types are valid they can be given as a list.
---
--- ```lua
- --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
- --- -- NOP (success)
- ---
- --- vim.validate{arg1={1, {'string', 'table'}}}
- --- -- error('arg1: expected string|table, got number')
+ --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
+ --- -- NOP (success)
---
+ --- vim.validate{arg1={1, {'string', 'table'}}}
+ --- -- error('arg1: expected string|table, got number')
--- ```
---
---@param opt table<vim.validate.Type,vim.validate.Spec> (table) Names of parameters to validate. Each key is a parameter
@@ -989,19 +989,19 @@ do
--- Once the buffer is full, adding a new entry overrides the oldest entry.
---
--- ```lua
- --- local ringbuf = vim.ringbuf(4)
- --- ringbuf:push("a")
- --- ringbuf:push("b")
- --- ringbuf:push("c")
- --- ringbuf:push("d")
- --- ringbuf:push("e") -- overrides "a"
- --- print(ringbuf:pop()) -- returns "b"
- --- print(ringbuf:pop()) -- returns "c"
+ --- local ringbuf = vim.ringbuf(4)
+ --- ringbuf:push("a")
+ --- ringbuf:push("b")
+ --- ringbuf:push("c")
+ --- ringbuf:push("d")
+ --- ringbuf:push("e") -- overrides "a"
+ --- print(ringbuf:pop()) -- returns "b"
+ --- print(ringbuf:pop()) -- returns "c"
---
- --- -- Can be used as iterator. Pops remaining items:
- --- for val in ringbuf do
- --- print(val)
- --- end
+ --- -- Can be used as iterator. Pops remaining items:
+ --- for val in ringbuf do
+ --- print(val)
+ --- end
--- ```
---
--- Returns a Ringbuf instance with the following methods:
diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua
index 7e37d84393..09b7576d97 100644
--- a/runtime/lua/vim/snippet.lua
+++ b/runtime/lua/vim/snippet.lua
@@ -245,8 +245,6 @@ function Session:set_group_gravity(index, right_gravity)
end
end
---- @class vim.snippet.Snippet
---- @field private _session? vim.snippet.Session
local M = { session = nil }
--- Displays the choices for the given tabstop as completion items.
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index e2197168f0..9b69f95f54 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -432,7 +432,7 @@ end
--- Can be used in an ftplugin or FileType autocommand.
---
--- Note: By default, disables regex syntax highlighting, which may be required for some plugins.
---- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`.
+--- In this case, add `vim.bo.syntax = 'on'` after the call to `start`.
---
--- Example:
---
diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua
index 556c910feb..6ec997eb4a 100644
--- a/runtime/lua/vim/treesitter/_query_linter.lua
+++ b/runtime/lua/vim/treesitter/_query_linter.lua
@@ -197,7 +197,7 @@ function M.clear(buf)
end
--- @private
---- @param findstart integer
+--- @param findstart 0|1
--- @param base string
function M.omnifunc(findstart, base)
if findstart == 1 then
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 99cc9bea09..8fb591bc46 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -231,7 +231,6 @@ function TSHighlighter:on_changedtree(changes)
end
--- Gets the query used for @param lang
---
---@package
---@param lang string Language used by the highlighter.
---@return vim.treesitter.highlighter.Query
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 79566f5eeb..d01da8be71 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -1,5 +1,3 @@
---- @defgroup lua-treesitter-languagetree
----
--- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and
--- any "injected" language parsers, which themselves may inject other languages, recursively.
--- For example a Lua buffer containing some Vimscript commands needs multiple parsers to fully
@@ -433,7 +431,7 @@ function LanguageTree:parse(range)
local query_time = 0
local total_parse_time = 0
- --- At least 1 region is invalid
+ -- At least 1 region is invalid
if not self:is_valid(true) then
changes, no_regions_parsed, total_parse_time = self:_parse_regions(range)
-- Need to run injections when we parsed something
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 5bb9e07a82..57272dbd60 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -231,7 +231,7 @@ end
---@param lang string Language to use for the query
---@param query_name string Name of the query (e.g. "highlights")
---
----@return vim.treesitter.Query|nil -- Parsed query. `nil` if no query files are found.
+---@return vim.treesitter.Query|nil : Parsed query. `nil` if no query files are found.
M.get = vim.func._memoize('concat-2', function(lang, query_name)
if explicit_queries[lang][query_name] then
return explicit_queries[lang][query_name]
@@ -1019,6 +1019,8 @@ end
--- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
--- ```
---
+--- @param findstart 0|1
+--- @param base string
function M.omnifunc(findstart, base)
return vim.treesitter._query_linter.omnifunc(findstart, base)
end
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 038aa8acfb..7660dc42e7 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -1,4 +1,4 @@
----TODO: This is implemented only for files currently.
+-- TODO: This is implemented only for files currently.
-- https://tools.ietf.org/html/rfc3986
-- https://tools.ietf.org/html/rfc2732
-- https://tools.ietf.org/html/rfc2396
@@ -116,7 +116,6 @@ end
---Gets the buffer for a uri.
---Creates a new unloaded buffer if no buffer for the uri already exists.
---
---@param uri string
---@return integer bufnr
function M.uri_to_bufnr(uri)
diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua
index 58c2a2386d..09a6fa825b 100644
--- a/runtime/lua/vim/version.lua
+++ b/runtime/lua/vim/version.lua
@@ -1,6 +1,5 @@
---- @defgroup vim.version
----
---- @brief The \`vim.version\` module provides functions for comparing versions and ranges
+--- @brief
+--- The `vim.version` module provides functions for comparing versions and ranges
--- conforming to the https://semver.org spec. Plugins, and plugin managers, can use this to check
--- available tools and dependencies on the current system.
---
@@ -13,9 +12,9 @@
--- end
--- ```
---
---- \*vim.version()\* returns the version of the current Nvim process.
+--- *vim.version()* returns the version of the current Nvim process.
---
---- VERSION RANGE SPEC \*version-range\*
+--- VERSION RANGE SPEC *version-range*
---
--- A version "range spec" defines a semantic version range which can be tested against a version,
--- using |vim.version.range()|.
diff --git a/scripts/cdoc_grammar.lua b/scripts/cdoc_grammar.lua
new file mode 100644
index 0000000000..6a7610883b
--- /dev/null
+++ b/scripts/cdoc_grammar.lua
@@ -0,0 +1,87 @@
+--[[!
+LPEG grammar for C doc comments
+]]
+
+--- @class nvim.cdoc.Param
+--- @field kind 'param'
+--- @field name string
+--- @field desc? string
+
+--- @class nvim.cdoc.Return
+--- @field kind 'return'
+--- @field desc string
+
+--- @class nvim.cdoc.Note
+--- @field desc? string
+
+--- @alias nvim.cdoc.grammar.result
+--- | nvim.cdoc.Param
+--- | nvim.cdoc.Return
+--- | nvim.cdoc.Note
+
+--- @class nvim.cdoc.grammar
+--- @field match fun(self, input: string): nvim.cdoc.grammar.result?
+
+local lpeg = vim.lpeg
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
+local Ct, Cg = lpeg.Ct, lpeg.Cg
+
+--- @param x vim.lpeg.Pattern
+local function rep(x)
+ return x ^ 0
+end
+
+--- @param x vim.lpeg.Pattern
+local function rep1(x)
+ return x ^ 1
+end
+
+--- @param x vim.lpeg.Pattern
+local function opt(x)
+ return x ^ -1
+end
+
+local nl = P('\r\n') + P('\n')
+local ws = rep1(S(' \t') + nl)
+
+local any = P(1) -- (consume one character)
+local letter = R('az', 'AZ') + S('_$')
+local ident = letter * rep(letter + R('09'))
+
+local io = P('[') * (P('in') + P('out') + P('inout')) * P(']')
+
+--- @param x string
+local function Pf(x)
+ return opt(ws) * P(x) * opt(ws)
+end
+
+--- @type table<string,vim.lpeg.Pattern>
+local v = setmetatable({}, {
+ __index = function(_, k)
+ return lpeg.V(k)
+ end,
+})
+
+local grammar = P {
+ rep1(P('@') * v.ats),
+
+ ats = v.at_param + v.at_return + v.at_deprecated + v.at_see + v.at_brief + v.at_note + v.at_nodoc,
+
+ at_param = Ct(
+ Cg(P('param'), 'kind') * opt(io) * ws * Cg(ident, 'name') * opt(ws * Cg(rep(any), 'desc'))
+ ),
+
+ at_return = Ct(Cg(P('return'), 'kind') * opt(S('s')) * opt(ws * Cg(rep(any), 'desc'))),
+
+ at_deprecated = Ct(Cg(P('deprecated'), 'kind')),
+
+ at_see = Ct(Cg(P('see'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
+
+ at_brief = Ct(Cg(P('brief'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ at_note = Ct(Cg(P('note'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ at_nodoc = Ct(Cg(P('nodoc'), 'kind')),
+}
+
+return grammar --[[@as nvim.cdoc.grammar]]
diff --git a/scripts/cdoc_parser.lua b/scripts/cdoc_parser.lua
new file mode 100644
index 0000000000..5f0dc7be2c
--- /dev/null
+++ b/scripts/cdoc_parser.lua
@@ -0,0 +1,223 @@
+local cdoc_grammar = require('scripts.cdoc_grammar')
+local c_grammar = require('src.nvim.generators.c_grammar')
+
+--- @class nvim.cdoc.parser.param
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.cdoc.parser.return
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.cdoc.parser.note
+--- @field desc string
+
+--- @class nvim.cdoc.parser.brief
+--- @field kind 'brief'
+--- @field desc string
+
+--- @class nvim.cdoc.parser.fun
+--- @field name string
+--- @field params nvim.cdoc.parser.param[]
+--- @field returns nvim.cdoc.parser.return[]
+--- @field desc string
+--- @field deprecated? true
+--- @field since? string
+--- @field attrs? string[]
+--- @field nodoc? true
+--- @field notes? nvim.cdoc.parser.note[]
+--- @field see? nvim.cdoc.parser.note[]
+
+--- @class nvim.cdoc.parser.State
+--- @field doc_lines? string[]
+--- @field cur_obj? nvim.cdoc.parser.obj
+--- @field last_doc_item? nvim.cdoc.parser.param|nvim.cdoc.parser.return|nvim.cdoc.parser.note
+--- @field last_doc_item_indent? integer
+
+--- @alias nvim.cdoc.parser.obj
+--- | nvim.cdoc.parser.fun
+--- | nvim.cdoc.parser.brief
+
+--- If we collected any `---` lines. Add them to the existing (or new) object
+--- Used for function/class descriptions and multiline param descriptions.
+--- @param state nvim.cdoc.parser.State
+local function add_doc_lines_to_obj(state)
+ if state.doc_lines then
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ local txt = table.concat(state.doc_lines, '\n')
+ if cur_obj.desc then
+ cur_obj.desc = cur_obj.desc .. '\n' .. txt
+ else
+ cur_obj.desc = txt
+ end
+ state.doc_lines = nil
+ end
+end
+
+--- @param line string
+--- @param state nvim.cdoc.parser.State
+local function process_doc_line(line, state)
+ line = line:gsub('^%s+@', '@')
+
+ local parsed = cdoc_grammar:match(line)
+
+ if not parsed then
+ if line:match('^ ') then
+ line = line:sub(2)
+ end
+
+ if state.last_doc_item then
+ if not state.last_doc_item_indent then
+ state.last_doc_item_indent = #line:match('^%s*') + 1
+ end
+ state.last_doc_item.desc = (state.last_doc_item.desc or '')
+ .. '\n'
+ .. line:sub(state.last_doc_item_indent or 1)
+ else
+ state.doc_lines = state.doc_lines or {}
+ table.insert(state.doc_lines, line)
+ end
+ return
+ end
+
+ state.last_doc_item_indent = nil
+ state.last_doc_item = nil
+
+ local kind = parsed.kind
+
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ if kind == 'brief' then
+ state.cur_obj = {
+ kind = 'brief',
+ desc = parsed.desc,
+ }
+ elseif kind == 'param' then
+ state.last_doc_item_indent = nil
+ cur_obj.params = cur_obj.params or {}
+ state.last_doc_item = {
+ name = parsed.name,
+ desc = parsed.desc,
+ }
+ table.insert(cur_obj.params, state.last_doc_item)
+ elseif kind == 'return' then
+ cur_obj.returns = { {
+ desc = parsed.desc,
+ } }
+ state.last_doc_item_indent = nil
+ state.last_doc_item = cur_obj.returns[1]
+ elseif kind == 'deprecated' then
+ cur_obj.deprecated = true
+ elseif kind == 'nodoc' then
+ cur_obj.nodoc = true
+ elseif kind == 'since' then
+ cur_obj.since = parsed.desc
+ elseif kind == 'see' then
+ cur_obj.see = cur_obj.see or {}
+ table.insert(cur_obj.see, { desc = parsed.desc })
+ elseif kind == 'note' then
+ state.last_doc_item_indent = nil
+ state.last_doc_item = {
+ desc = parsed.desc,
+ }
+ cur_obj.notes = cur_obj.notes or {}
+ table.insert(cur_obj.notes, state.last_doc_item)
+ else
+ error('Unhandled' .. vim.inspect(parsed))
+ end
+end
+
+--- @param item table
+--- @param state nvim.cdoc.parser.State
+local function process_proto(item, state)
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ cur_obj.name = item.name
+ cur_obj.params = cur_obj.params or {}
+
+ for _, p in ipairs(item.parameters) do
+ local param = { name = p[2], type = p[1] }
+ local added = false
+ for _, cp in ipairs(cur_obj.params) do
+ if cp.name == param.name then
+ cp.type = param.type
+ added = true
+ break
+ end
+ end
+
+ if not added then
+ table.insert(cur_obj.params, param)
+ end
+ end
+
+ cur_obj.returns = cur_obj.returns or { {} }
+ cur_obj.returns[1].type = item.return_type
+
+ for _, a in ipairs({
+ 'fast',
+ 'remote_only',
+ 'lua_only',
+ 'textlock',
+ 'textlock_allow_cmdwin',
+ }) do
+ if item[a] then
+ cur_obj.attrs = cur_obj.attrs or {}
+ table.insert(cur_obj.attrs, a)
+ end
+ end
+
+ cur_obj.deprecated_since = item.deprecated_since
+
+ -- Remove some arguments
+ for i = #cur_obj.params, 1, -1 do
+ local p = cur_obj.params[i]
+ if p.name == 'channel_id' or vim.tbl_contains({ 'lstate', 'arena', 'error' }, p.type) then
+ table.remove(cur_obj.params, i)
+ end
+ end
+end
+
+local M = {}
+
+--- @param filename string
+--- @return {} classes
+--- @return nvim.cdoc.parser.fun[] funs
+--- @return string[] briefs
+function M.parse(filename)
+ local funs = {} --- @type nvim.cdoc.parser.fun[]
+ local briefs = {} --- @type string[]
+ local state = {} --- @type nvim.cdoc.parser.State
+
+ local txt = assert(io.open(filename, 'r')):read('*all')
+
+ local parsed = c_grammar.grammar:match(txt)
+ for _, item in ipairs(parsed) do
+ if item.comment then
+ process_doc_line(item.comment, state)
+ else
+ add_doc_lines_to_obj(state)
+ if item[1] == 'proto' then
+ process_proto(item, state)
+ table.insert(funs, state.cur_obj)
+ end
+ local cur_obj = state.cur_obj
+ if cur_obj and not item.static then
+ if cur_obj.kind == 'brief' then
+ table.insert(briefs, cur_obj.desc)
+ end
+ end
+ state = {}
+ end
+ end
+
+ return {}, funs, briefs
+end
+
+-- M.parse('src/nvim/api/vim.c')
+
+return M
diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index b7f17a2d58..895033d5af 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -3,7 +3,6 @@
-- Generator for various vimdoc and Lua type files
local DEP_API_METADATA = 'build/api_metadata.mpack'
-local DEP_API_DOC = 'runtime/doc/api.mpack'
--- @class vim.api.metadata
--- @field name string
@@ -210,44 +209,65 @@ end
--- @return table<string, vim.EvalFn>
local function get_api_meta()
- local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
- local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]]
local ret = {} --- @type table<string, vim.EvalFn>
- local doc_mpack_f = assert(io.open(DEP_API_DOC, 'rb'))
- local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table<string,vim.gen_vim_doc_fun>]]
-
- for _, fun in ipairs(metadata) do
- if fun.lua then
- local fdoc = doc_metadata[fun.name]
-
- local params = {} --- @type {[1]:string,[2]:string}[]
- for _, p in ipairs(fun.parameters) do
- local ptype, pname = p[1], p[2]
- params[#params + 1] = {
- pname,
- api_type(ptype),
- fdoc and fdoc.parameters_doc[pname] or nil,
- }
- end
+ local cdoc_parser = require('scripts.cdoc_parser')
- local r = {
- signature = 'NA',
- name = fun.name,
- params = params,
- returns = api_type(fun.return_type),
- deprecated = fun.deprecated_since ~= nil,
- }
+ local f = 'src/nvim/api'
- if fdoc then
- if #fdoc.doc > 0 then
- r.desc = table.concat(fdoc.doc, '\n')
+ local function include(fun)
+ if not vim.startswith(fun.name, 'nvim_') then
+ return false
+ end
+ if vim.tbl_contains(fun.attrs or {}, 'lua_only') then
+ return true
+ end
+ if vim.tbl_contains(fun.attrs or {}, 'remote_only') then
+ return false
+ end
+ return true
+ end
+
+ --- @type table<string,nvim.cdoc.parser.fun>
+ local functions = {}
+ for path, ty in vim.fs.dir(f) do
+ if ty == 'file' then
+ local filename = vim.fs.joinpath(f, path)
+ local _, funs = cdoc_parser.parse(filename)
+ for _, fn in ipairs(funs) do
+ if include(fn) then
+ functions[fn.name] = fn
end
- r.return_desc = (fdoc['return'] or {})[1]
end
+ end
+ end
+
+ for _, fun in pairs(functions) do
+ local deprecated = fun.deprecated_since ~= nil
+
+ local params = {} --- @type {[1]:string,[2]:string}[]
+ for _, p in ipairs(fun.params) do
+ params[#params + 1] = {
+ p.name,
+ api_type(p.type),
+ not deprecated and p.desc or nil,
+ }
+ end
+
+ local r = {
+ signature = 'NA',
+ name = fun.name,
+ params = params,
+ returns = api_type(fun.returns[1].type),
+ deprecated = deprecated,
+ }
- ret[fun.name] = r
+ if not deprecated then
+ r.desc = fun.desc
+ r.return_desc = fun.returns[1].desc
end
+
+ ret[fun.name] = r
end
return ret
end
@@ -275,12 +295,10 @@ end
--- @param fun vim.EvalFn
--- @param write fun(line: string)
local function render_api_meta(_f, fun, write)
- if not vim.startswith(fun.name, 'nvim_') then
- return
- end
-
write('')
+ local text_utils = require('scripts.text_utils')
+
if vim.startswith(fun.name, 'nvim__') then
write('--- @private')
end
@@ -291,10 +309,10 @@ local function render_api_meta(_f, fun, write)
local desc = fun.desc
if desc then
+ desc = text_utils.md_to_vimdoc(desc, 0, 0, 74)
for _, l in ipairs(split(norm_text(desc))) do
write('--- ' .. l)
end
- write('---')
end
local param_names = {} --- @type string[]
@@ -303,8 +321,11 @@ local function render_api_meta(_f, fun, write)
param_names[#param_names + 1] = p[1]
local pdesc = p[3]
if pdesc then
- local pdesc_a = split(norm_text(pdesc))
- write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1])
+ local s = '--- @param ' .. p[1] .. ' ' .. p[2] .. ' '
+ local indent = #('@param ' .. p[1] .. ' ')
+ pdesc = text_utils.md_to_vimdoc(pdesc, #s, indent, 74, true)
+ local pdesc_a = split(vim.trim(norm_text(pdesc)))
+ write(s .. pdesc_a[1])
for i = 2, #pdesc_a do
if not pdesc_a[i] then
break
@@ -317,6 +338,7 @@ local function render_api_meta(_f, fun, write)
end
if fun.returns ~= '' then
local ret_desc = fun.returns_desc and ' : ' .. fun.returns_desc or ''
+ ret_desc = text_utils.md_to_vimdoc(ret_desc, 0, 0, 74)
local ret = LUA_API_RETURN_OVERRIDES[fun.name] or fun.returns
write('--- @return ' .. ret .. ret_desc)
end
@@ -328,8 +350,6 @@ end
--- @return table<string, vim.EvalFn>
local function get_api_keysets_meta()
local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
-
- --- @diagnostic disable-next-line:no-unknown
local metadata = assert(vim.mpack.decode(mpack_f:read('*all')))
local ret = {} --- @type table<string, vim.EvalFn>
diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua
new file mode 100755
index 0000000000..290cd83fbc
--- /dev/null
+++ b/scripts/gen_vimdoc.lua
@@ -0,0 +1,787 @@
+#!/usr/bin/env -S nvim -l
+--- Generates Nvim :help docs from Lua/C docstrings
+---
+--- The generated :help text for each function is formatted as follows:
+--- - Max width of 78 columns (`TEXT_WIDTH`).
+--- - Indent with spaces (not tabs).
+--- - Indent of 4 columns for body text (`INDENTATION`).
+--- - Function signature and helptag (right-aligned) on the same line.
+--- - Signature and helptag must have a minimum of 8 spaces between them.
+--- - If the signature is too long, it is placed on the line after the helptag.
+--- Signature wraps with subsequent lines indented to the open parenthesis.
+--- - Subsection bodies are indented an additional 4 spaces.
+--- - Body consists of function description, parameters, return description, and
+--- C declaration (`INCLUDE_C_DECL`).
+--- - Parameters are omitted for the `void` and `Error *` types, or if the
+--- parameter is marked as [out].
+--- - Each function documentation is separated by a single line.
+
+local luacats_parser = require('scripts.luacats_parser')
+local cdoc_parser = require('scripts.cdoc_parser')
+local text_utils = require('scripts.text_utils')
+
+local fmt = string.format
+
+local wrap = text_utils.wrap
+local md_to_vimdoc = text_utils.md_to_vimdoc
+
+local TEXT_WIDTH = 78
+local INDENTATION = 4
+
+--- @class (exact) nvim.gen_vimdoc.Config
+---
+--- Generated documentation target, e.g. api.txt
+--- @field filename string
+---
+--- @field section_order string[]
+---
+--- List of files/directories for doxygen to read, relative to `base_dir`.
+--- @field files string[]
+---
+--- @field exclude_types? true
+---
+--- Section name overrides. Key: filename (e.g., vim.c)
+--- @field section_name? table<string,string>
+---
+--- @field fn_name_pat? string
+---
+--- @field fn_xform? fun(fun: nvim.luacats.parser.fun)
+---
+--- For generated section names.
+--- @field section_fmt fun(name: string): string
+---
+--- @field helptag_fmt fun(name: string): string
+---
+--- Per-function helptag.
+--- @field fn_helptag_fmt? fun(fun: nvim.luacats.parser.fun): string
+---
+--- @field append_only? string[]
+
+local function contains(t, xs)
+ return vim.tbl_contains(xs, t)
+end
+
+--- @type {level:integer, prerelease:boolean}?
+local nvim_api_info_
+
+--- @return {level: integer, prerelease:boolean}
+local function nvim_api_info()
+ if not nvim_api_info_ then
+ --- @type integer?, boolean?
+ local level, prerelease
+ for l in io.lines('CMakeLists.txt') do
+ --- @cast l string
+ if level and prerelease then
+ break
+ end
+ local m1 = l:match('^set%(NVIM_API_LEVEL%s+(%d+)%)')
+ if m1 then
+ level = tonumber(m1) --[[@as integer]]
+ end
+ local m2 = l:match('^set%(NVIM_API_PRERELEASE%s+(%w+)%)')
+ if m2 then
+ prerelease = m2 == 'true'
+ end
+ end
+ nvim_api_info_ = { level = level, prerelease = prerelease }
+ end
+
+ return nvim_api_info_
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @return string
+local function fn_helptag_fmt_common(fun)
+ local fn_sfx = fun.table and '' or '()'
+ if fun.classvar then
+ return fmt('*%s:%s%s*', fun.classvar, fun.name, fn_sfx)
+ end
+ if fun.module then
+ return fmt('*%s.%s%s*', fun.module, fun.name, fn_sfx)
+ end
+ return fmt('*%s%s*', fun.name, fn_sfx)
+end
+
+--- @type table<string,nvim.gen_vimdoc.Config>
+local config = {
+ api = {
+ filename = 'api.txt',
+ section_order = {
+ 'vim.c',
+ 'vimscript.c',
+ 'command.c',
+ 'options.c',
+ 'buffer.c',
+ 'extmark.c',
+ 'window.c',
+ 'win_config.c',
+ 'tabpage.c',
+ 'autocmd.c',
+ 'ui.c',
+ },
+ exclude_types = true,
+ fn_name_pat = 'nvim_.*',
+ files = { 'src/nvim/api' },
+ section_name = {
+ ['vim.c'] = 'Global',
+ },
+ section_fmt = function(name)
+ return name .. ' Functions'
+ end,
+ helptag_fmt = function(name)
+ return fmt('*api-%s*', name:lower())
+ end,
+ },
+ lua = {
+ filename = 'lua.txt',
+ section_order = {
+ 'highlight.lua',
+ 'diff.lua',
+ 'mpack.lua',
+ 'json.lua',
+ 'base64.lua',
+ 'spell.lua',
+ 'builtin.lua',
+ '_options.lua',
+ '_editor.lua',
+ '_inspector.lua',
+ 'shared.lua',
+ 'loader.lua',
+ 'uri.lua',
+ 'ui.lua',
+ 'filetype.lua',
+ 'keymap.lua',
+ 'fs.lua',
+ 'glob.lua',
+ 'lpeg.lua',
+ 're.lua',
+ 'regex.lua',
+ 'secure.lua',
+ 'version.lua',
+ 'iter.lua',
+ 'snippet.lua',
+ 'text.lua',
+ },
+ files = {
+ 'runtime/lua/vim/iter.lua',
+ 'runtime/lua/vim/_editor.lua',
+ 'runtime/lua/vim/_options.lua',
+ 'runtime/lua/vim/shared.lua',
+ 'runtime/lua/vim/loader.lua',
+ 'runtime/lua/vim/uri.lua',
+ 'runtime/lua/vim/ui.lua',
+ 'runtime/lua/vim/filetype.lua',
+ 'runtime/lua/vim/keymap.lua',
+ 'runtime/lua/vim/fs.lua',
+ 'runtime/lua/vim/highlight.lua',
+ 'runtime/lua/vim/secure.lua',
+ 'runtime/lua/vim/version.lua',
+ 'runtime/lua/vim/_inspector.lua',
+ 'runtime/lua/vim/snippet.lua',
+ 'runtime/lua/vim/text.lua',
+ 'runtime/lua/vim/glob.lua',
+ 'runtime/lua/vim/_meta/builtin.lua',
+ 'runtime/lua/vim/_meta/diff.lua',
+ 'runtime/lua/vim/_meta/mpack.lua',
+ 'runtime/lua/vim/_meta/json.lua',
+ 'runtime/lua/vim/_meta/base64.lua',
+ 'runtime/lua/vim/_meta/regex.lua',
+ 'runtime/lua/vim/_meta/lpeg.lua',
+ 'runtime/lua/vim/_meta/re.lua',
+ 'runtime/lua/vim/_meta/spell.lua',
+ },
+ fn_xform = function(fun)
+ if contains(fun.module, { 'vim.uri', 'vim.shared', 'vim._editor' }) then
+ fun.module = 'vim'
+ end
+
+ if fun.module == 'vim' and contains(fun.name, { 'cmd', 'inspect' }) then
+ fun.table = nil
+ end
+
+ if fun.classvar or vim.startswith(fun.name, 'vim.') or fun.module == 'vim.iter' then
+ return
+ end
+
+ fun.name = fmt('%s.%s', fun.module, fun.name)
+ end,
+ section_name = {
+ ['_inspector.lua'] = 'inspector',
+ },
+ section_fmt = function(name)
+ name = name:lower()
+ if name == '_editor' then
+ return 'Lua module: vim'
+ elseif name == '_options' then
+ return 'LUA-VIMSCRIPT BRIDGE'
+ elseif name == 'builtin' then
+ return 'VIM'
+ end
+ if
+ contains(name, {
+ 'highlight',
+ 'mpack',
+ 'json',
+ 'base64',
+ 'diff',
+ 'spell',
+ 'regex',
+ 'lpeg',
+ 're',
+ })
+ then
+ return 'VIM.' .. name:upper()
+ end
+ return 'Lua module: vim.' .. name
+ end,
+ helptag_fmt = function(name)
+ if name == '_editor' then
+ return '*lua-vim*'
+ elseif name == '_options' then
+ return '*lua-vimscript*'
+ end
+ return '*vim.' .. name:lower() .. '*'
+ end,
+ fn_helptag_fmt = function(fun)
+ local name = fun.name
+
+ if vim.startswith(name, 'vim.') then
+ local fn_sfx = fun.table and '' or '()'
+ return fmt('*%s%s*', name, fn_sfx)
+ elseif fun.classvar == 'Option' then
+ return fmt('*vim.opt:%s()*', name)
+ end
+
+ return fn_helptag_fmt_common(fun)
+ end,
+ append_only = {
+ 'shared.lua',
+ },
+ },
+ lsp = {
+ filename = 'lsp.txt',
+ section_order = {
+ 'lsp.lua',
+ 'buf.lua',
+ 'diagnostic.lua',
+ 'codelens.lua',
+ 'inlay_hint.lua',
+ 'tagfunc.lua',
+ 'semantic_tokens.lua',
+ 'handlers.lua',
+ 'util.lua',
+ 'log.lua',
+ 'rpc.lua',
+ 'protocol.lua',
+ },
+ files = {
+ 'runtime/lua/vim/lsp',
+ 'runtime/lua/vim/lsp.lua',
+ },
+ fn_xform = function(fun)
+ fun.name = fun.name:gsub('result%.', '')
+ end,
+ section_fmt = function(name)
+ if name:lower() == 'lsp' then
+ return 'Lua module: vim.lsp'
+ end
+ return 'Lua module: vim.lsp.' .. name:lower()
+ end,
+ helptag_fmt = function(name)
+ if name:lower() == 'lsp' then
+ return '*lsp-core*'
+ end
+ return fmt('*lsp-%s*', name:lower())
+ end,
+ },
+ diagnostic = {
+ filename = 'diagnostic.txt',
+ section_order = {
+ 'diagnostic.lua',
+ },
+ files = { 'runtime/lua/vim/diagnostic.lua' },
+ section_fmt = function()
+ return 'Lua module: vim.diagnostic'
+ end,
+ helptag_fmt = function()
+ return '*diagnostic-api*'
+ end,
+ },
+ treesitter = {
+ filename = 'treesitter.txt',
+ section_order = {
+ 'treesitter.lua',
+ 'language.lua',
+ 'query.lua',
+ 'highlighter.lua',
+ 'languagetree.lua',
+ 'dev.lua',
+ },
+ files = {
+ 'runtime/lua/vim/treesitter.lua',
+ 'runtime/lua/vim/treesitter/',
+ },
+ section_fmt = function(name)
+ if name:lower() == 'treesitter' then
+ return 'Lua module: vim.treesitter'
+ end
+ return 'Lua module: vim.treesitter.' .. name:lower()
+ end,
+ helptag_fmt = function(name)
+ if name:lower() == 'treesitter' then
+ return '*lua-treesitter-core*'
+ end
+ return '*lua-treesitter-' .. name:lower() .. '*'
+ end,
+ },
+}
+
+--- @param ty string
+--- @param generics table<string,string>
+--- @return string
+local function replace_generics(ty, generics)
+ if ty:sub(-2) == '[]' then
+ local ty0 = ty:sub(1, -3)
+ if generics[ty0] then
+ return generics[ty0] .. '[]'
+ end
+ elseif ty:sub(-1) == '?' then
+ local ty0 = ty:sub(1, -2)
+ if generics[ty0] then
+ return generics[ty0] .. '?'
+ end
+ end
+
+ return generics[ty] or ty
+end
+
+--- @param ty string
+--- @param generics? table<string,string>
+local function render_type(ty, generics)
+ if generics then
+ ty = replace_generics(ty, generics)
+ end
+ ty = ty:gsub('%s*|%s*nil', '?')
+ ty = ty:gsub('nil%s*|%s*(.*)', '%1?')
+ ty = ty:gsub('%s*|%s*', '|')
+ return fmt('(`%s`)', ty)
+end
+
+--- @param p nvim.luacats.parser.param|nvim.luacats.parser.field
+local function should_render_param(p)
+ return not p.access and not contains(p.name, { '_', 'self' })
+end
+
+--- @param xs (nvim.luacats.parser.param|nvim.luacats.parser.field)[]
+--- @param generics? table<string,string>
+--- @param exclude_types? true
+local function render_fields_or_params(xs, generics, exclude_types)
+ local ret = {} --- @type string[]
+
+ xs = vim.tbl_filter(should_render_param, xs)
+
+ local indent = 0
+ for _, p in ipairs(xs) do
+ if p.type or p.desc then
+ indent = math.max(indent, #p.name + 3)
+ end
+ if exclude_types then
+ p.type = nil
+ end
+ end
+
+ for _, p in ipairs(xs) do
+ local nm, ty = p.name, p.type
+ local desc = p.desc
+ local pnm = fmt(' • %-' .. indent .. 's', '{' .. nm .. '}')
+ if ty then
+ local pty = render_type(ty, generics)
+ if desc then
+ desc = fmt('%s %s', pty, desc)
+ table.insert(ret, pnm)
+ table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
+ else
+ table.insert(ret, fmt('%s %s\n', pnm, pty))
+ end
+ else
+ if desc then
+ table.insert(ret, pnm)
+ table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
+ end
+ end
+ end
+
+ return table.concat(ret)
+end
+
+-- --- @param class lua2vimdoc.class
+-- local function render_class(class)
+-- writeln(fmt('*%s*', class.name))
+-- writeln()
+-- if #class.fields > 0 then
+-- writeln(' Fields: ~')
+-- render_fields_or_params(class.fields)
+-- end
+-- writeln()
+-- end
+
+-- --- @param cls table<string,lua2vimdoc.class>
+-- local function render_classes(cls)
+-- --- @diagnostic disable-next-line:no-unknown
+-- for _, class in vim.spairs(cls) do
+-- render_class(class)
+-- end
+-- end
+
+--- @param fun nvim.luacats.parser.fun
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_fun_header(fun, cfg)
+ local ret = {} --- @type string[]
+
+ local args = {} --- @type string[]
+ for _, p in ipairs(fun.params or {}) do
+ if p.name ~= 'self' then
+ args[#args + 1] = fmt('{%s}', p.name:gsub('%?$', ''))
+ end
+ end
+
+ local nm = fun.name
+ if fun.classvar then
+ nm = fmt('%s:%s', fun.classvar, nm)
+ end
+
+ local proto = fun.table and nm or nm .. '(' .. table.concat(args, ', ') .. ')'
+
+ if not cfg.fn_helptag_fmt then
+ cfg.fn_helptag_fmt = fn_helptag_fmt_common
+ end
+
+ local tag = cfg.fn_helptag_fmt(fun)
+
+ if #proto + #tag > TEXT_WIDTH - 8 then
+ table.insert(ret, fmt('%78s\n', tag))
+ local name, pargs = proto:match('([^(]+%()(.*)')
+ table.insert(ret, name)
+ table.insert(ret, wrap(pargs, 0, #name, TEXT_WIDTH))
+ else
+ local pad = TEXT_WIDTH - #proto - #tag
+ table.insert(ret, proto .. string.rep(' ', pad) .. tag)
+ end
+
+ return table.concat(ret)
+end
+
+--- @param returns nvim.luacats.parser.return[]
+--- @param generics? table<string,string>
+--- @param exclude_types boolean
+local function render_returns(returns, generics, exclude_types)
+ local ret = {} --- @type string[]
+
+ returns = vim.deepcopy(returns)
+ if exclude_types then
+ for _, r in ipairs(returns) do
+ r.type = nil
+ end
+ end
+
+ if #returns > 1 then
+ table.insert(ret, ' Return (multiple): ~\n')
+ elseif #returns == 1 and next(returns[1]) then
+ table.insert(ret, ' Return: ~\n')
+ end
+
+ for _, p in ipairs(returns) do
+ local rnm, ty, desc = p.name, p.type, p.desc
+ local blk = ''
+ if ty then
+ blk = render_type(ty, generics)
+ end
+ if rnm then
+ blk = blk .. ' ' .. rnm
+ end
+ if desc then
+ blk = blk .. ' ' .. desc
+ end
+ table.insert(ret, md_to_vimdoc(blk, 8, 8, TEXT_WIDTH, true))
+ end
+
+ return table.concat(ret)
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_fun(fun, cfg)
+ if fun.access or fun.deprecated or fun.nodoc then
+ return
+ end
+
+ if cfg.fn_name_pat and not fun.name:match(cfg.fn_name_pat) then
+ return
+ end
+
+ if vim.startswith(fun.name, '_') or fun.name:find('[:.]_') then
+ return
+ end
+
+ local ret = {} --- @type string[]
+
+ table.insert(ret, render_fun_header(fun, cfg))
+ table.insert(ret, '\n')
+
+ if fun.desc then
+ table.insert(ret, md_to_vimdoc(fun.desc, INDENTATION, INDENTATION, TEXT_WIDTH))
+ end
+
+ if fun.since then
+ local since = tonumber(fun.since)
+ local info = nvim_api_info()
+ if since and (since > info.level or since == info.level and info.prerelease) then
+ fun.notes = fun.notes or {}
+ table.insert(fun.notes, { desc = 'This API is pre-release (unstable).' })
+ end
+ end
+
+ if fun.notes then
+ table.insert(ret, '\n Note: ~\n')
+ for _, p in ipairs(fun.notes) do
+ table.insert(ret, ' • ' .. md_to_vimdoc(p.desc, 0, 8, TEXT_WIDTH, true))
+ end
+ end
+
+ if fun.attrs then
+ table.insert(ret, '\n Attributes: ~\n')
+ for _, attr in ipairs(fun.attrs) do
+ local attr_str = ({
+ textlock = 'not allowed when |textlock| is active or in the |cmdwin|',
+ textlock_allow_cmdwin = 'not allowed when |textlock| is active',
+ fast = '|api-fast|',
+ remote_only = '|RPC| only',
+ lua_only = 'Lua |vim.api| only',
+ })[attr] or attr
+ table.insert(ret, fmt(' %s\n', attr_str))
+ end
+ end
+
+ if fun.params and #fun.params > 0 then
+ local param_txt = render_fields_or_params(fun.params, fun.generics, cfg.exclude_types)
+ if not param_txt:match('^%s*$') then
+ table.insert(ret, '\n Parameters: ~\n')
+ ret[#ret + 1] = param_txt
+ end
+ end
+
+ if fun.returns then
+ local txt = render_returns(fun.returns, fun.generics, cfg.exclude_types)
+ if not txt:match('^%s*$') then
+ table.insert(ret, '\n')
+ ret[#ret + 1] = txt
+ end
+ end
+
+ if fun.see then
+ table.insert(ret, '\n See also: ~\n')
+ for _, p in ipairs(fun.see) do
+ table.insert(ret, ' • ' .. md_to_vimdoc(p.desc, 0, 8, TEXT_WIDTH, true))
+ end
+ end
+
+ table.insert(ret, '\n')
+ return table.concat(ret)
+end
+
+--- @param funs nvim.luacats.parser.fun[]
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_funs(funs, cfg)
+ local ret = {} --- @type string[]
+
+ for _, f in ipairs(funs) do
+ if cfg.fn_xform then
+ cfg.fn_xform(f)
+ end
+ ret[#ret + 1] = render_fun(f, cfg)
+ end
+
+ -- Sort via prototype
+ table.sort(ret, function(a, b)
+ local a1 = ('\n' .. a):match('\n[a-zA-Z_][^\n]+\n')
+ local b1 = ('\n' .. b):match('\n[a-zA-Z_][^\n]+\n')
+ return a1:lower() < b1:lower()
+ end)
+
+ return table.concat(ret)
+end
+
+--- @return string
+local function get_script_path()
+ local str = debug.getinfo(2, 'S').source:sub(2)
+ return str:match('(.*[/\\])') or './'
+end
+
+local script_path = get_script_path()
+local base_dir = vim.fs.dirname(assert(vim.fs.dirname(script_path)))
+
+local function delete_lines_below(doc_file, tokenstr)
+ local lines = {} --- @type string[]
+ local found = false
+ for line in io.lines(doc_file) do
+ if line:find(vim.pesc(tokenstr)) then
+ found = true
+ break
+ end
+ lines[#lines + 1] = line
+ end
+ if not found then
+ error(fmt('not found: %s in %s', tokenstr, doc_file))
+ end
+ lines[#lines] = nil
+ local fp = assert(io.open(doc_file, 'w'))
+ fp:write(table.concat(lines, '\n'))
+ fp:write('\n')
+ fp:close()
+end
+
+--- @param x string
+local function mktitle(x)
+ if x == 'ui' then
+ return 'UI'
+ end
+ return x:sub(1, 1):upper() .. x:sub(2)
+end
+
+--- @class nvim.gen_vimdoc.Section
+--- @field name string
+--- @field title string
+--- @field help_tag string
+--- @field funs_txt string
+--- @field doc? string[]
+
+--- @param filename string
+--- @param cfg nvim.gen_vimdoc.Config
+--- @param section_docs table<string,nvim.gen_vimdoc.Section>
+--- @param funs_txt string
+--- @return nvim.gen_vimdoc.Section?
+local function make_section(filename, cfg, section_docs, funs_txt)
+ -- filename: e.g., 'autocmd.c'
+ -- name: e.g. 'autocmd'
+ local name = filename:match('(.*)%.[a-z]+')
+
+ -- Formatted (this is what's going to be written in the vimdoc)
+ -- e.g., "Autocmd Functions"
+ local sectname = cfg.section_name and cfg.section_name[filename] or mktitle(name)
+
+ -- section tag: e.g., "*api-autocmd*"
+ local help_tag = cfg.helptag_fmt(sectname)
+
+ if funs_txt == '' and #section_docs == 0 then
+ return
+ end
+
+ return {
+ name = sectname,
+ title = cfg.section_fmt(sectname),
+ help_tag = help_tag,
+ funs_txt = funs_txt,
+ doc = section_docs,
+ }
+end
+
+--- @param section nvim.gen_vimdoc.Section
+--- @param add_header? boolean
+local function render_section(section, add_header)
+ local doc = {} --- @type string[]
+
+ if add_header ~= false then
+ vim.list_extend(doc, {
+ string.rep('=', TEXT_WIDTH),
+ '\n',
+ section.title,
+ fmt('%' .. (TEXT_WIDTH - section.title:len()) .. 's', section.help_tag),
+ })
+ end
+
+ if section.doc and #section.doc > 0 then
+ table.insert(doc, '\n\n')
+ vim.list_extend(doc, section.doc)
+ end
+
+ if section.funs_txt then
+ table.insert(doc, '\n\n')
+ table.insert(doc, section.funs_txt)
+ end
+
+ return table.concat(doc)
+end
+
+local parsers = {
+ lua = luacats_parser.parse,
+ c = cdoc_parser.parse,
+ h = cdoc_parser.parse,
+}
+
+--- @param files string[]
+local function expand_files(files)
+ for k, f in pairs(files) do
+ if vim.fn.isdirectory(f) == 1 then
+ table.remove(files, k)
+ for path, ty in vim.fs.dir(f) do
+ if ty == 'file' then
+ table.insert(files, vim.fs.joinpath(f, path))
+ end
+ end
+ end
+ end
+end
+
+--- @param cfg nvim.gen_vimdoc.Config
+local function gen_target(cfg)
+ local sections = {} --- @type table<string,nvim.gen_vimdoc.Section>
+
+ expand_files(cfg.files)
+
+ for _, f in pairs(cfg.files) do
+ local ext = assert(f:match('%.([^.]+)$')) --[[@as 'h'|'c'|'lua']]
+ local parser = assert(parsers[ext])
+ local _, funs, briefs = parser(f)
+ local briefs_txt = {} --- @type string[]
+ for _, b in ipairs(briefs) do
+ briefs_txt[#briefs_txt + 1] = md_to_vimdoc(b, 0, 0, TEXT_WIDTH)
+ end
+ local funs_txt = render_funs(funs, cfg)
+ -- FIXME: Using f_base will confuse `_meta/protocol.lua` with `protocol.lua`
+ local f_base = assert(vim.fs.basename(f))
+ sections[f_base] = make_section(f_base, cfg, briefs_txt, funs_txt)
+ end
+
+ local first_section_tag = sections[cfg.section_order[1]].help_tag
+ local docs = {} --- @type string[]
+ for _, f in ipairs(cfg.section_order) do
+ local section = sections[f]
+ if section then
+ local add_sep_and_header = not vim.tbl_contains(cfg.append_only or {}, f)
+ table.insert(docs, render_section(section, add_sep_and_header))
+ end
+ end
+
+ table.insert(
+ docs,
+ fmt(' vim:tw=78:ts=8:sw=%d:sts=%d:et:ft=help:norl:\n', INDENTATION, INDENTATION)
+ )
+
+ local doc_file = vim.fs.joinpath(base_dir, 'runtime', 'doc', cfg.filename)
+
+ if vim.uv.fs_stat(doc_file) then
+ delete_lines_below(doc_file, first_section_tag)
+ end
+
+ local fp = assert(io.open(doc_file, 'a'))
+ fp:write(table.concat(docs, '\n'))
+ fp:close()
+end
+
+local function run()
+ for _, cfg in pairs(config) do
+ gen_target(cfg)
+ end
+end
+
+run()
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
deleted file mode 100755
index c1a2183f24..0000000000
--- a/scripts/gen_vimdoc.py
+++ /dev/null
@@ -1,1766 +0,0 @@
-#!/usr/bin/env python3
-
-r"""Generates Nvim :help docs from C/Lua docstrings, using Doxygen.
-
-Also generates *.mpack files. To inspect the *.mpack structure:
- :new | put=v:lua.vim.inspect(v:lua.vim.mpack.decode(readfile('runtime/doc/api.mpack','B')))
-
-Flow:
- main
- extract_from_xml
- fmt_node_as_vimhelp \
- para_as_map } recursive
- update_params_map /
- render_node
-
-TODO: eliminate this script and use Lua+treesitter (requires parsers for C and
-Lua markdown-style docstrings).
-
-The generated :help text for each function is formatted as follows:
-
- - Max width of 78 columns (`text_width`).
- - Indent with spaces (not tabs).
- - Indent of 4 columns for body text (`indentation`).
- - Function signature and helptag (right-aligned) on the same line.
- - Signature and helptag must have a minimum of 8 spaces between them.
- - If the signature is too long, it is placed on the line after the helptag.
- Signature wraps at `text_width - 8` characters with subsequent
- lines indented to the open parenthesis.
- - Subsection bodies are indented an additional 4 spaces.
- - Body consists of function description, parameters, return description, and
- C declaration (`INCLUDE_C_DECL`).
- - Parameters are omitted for the `void` and `Error *` types, or if the
- parameter is marked as [out].
- - Each function documentation is separated by a single line.
-"""
-
-from __future__ import annotations # PEP-563, python 3.7+
-
-import argparse
-import collections
-import dataclasses
-import logging
-import os
-import re
-import shutil
-import subprocess
-import sys
-import textwrap
-from pathlib import Path
-from typing import Any, Callable, Dict, List, Tuple
-from xml.dom import minidom
-
-if sys.version_info >= (3, 8):
- from typing import Literal
-
-import msgpack
-
-Element = minidom.Element
-Document = minidom.Document
-
-MIN_PYTHON_VERSION = (3, 7)
-MIN_DOXYGEN_VERSION = (1, 9, 0)
-
-if sys.version_info < MIN_PYTHON_VERSION:
- print("requires Python {}.{}+".format(*MIN_PYTHON_VERSION))
- sys.exit(1)
-
-doxygen_version = tuple((int(i) for i in subprocess.check_output(["doxygen", "-v"],
- universal_newlines=True).split()[0].split('.')))
-
-if doxygen_version < MIN_DOXYGEN_VERSION:
- print("\nRequires doxygen {}.{}.{}+".format(*MIN_DOXYGEN_VERSION))
- print("Your doxygen version is {}.{}.{}\n".format(*doxygen_version))
- sys.exit(1)
-
-
-# Need a `nvim` that supports `-l`, try the local build
-nvim_path = Path(__file__).parent / "../build/bin/nvim"
-if nvim_path.exists():
- nvim = nvim_path.resolve()
-else:
- # Until 0.9 is released, use this hacky way to check that "nvim -l foo.lua" works.
- nvim_out = subprocess.check_output(['nvim', '-h'], universal_newlines=True)
- nvim_version = [line for line in nvim_out.split('\n')
- if '-l ' in line]
- if len(nvim_version) == 0:
- print((
- "\nYou need to have a local Neovim build or a `nvim` version 0.9 for `-l` "
- "support to build the documentation."))
- sys.exit(1)
- nvim = 'nvim'
-
-
-# DEBUG = ('DEBUG' in os.environ)
-INCLUDE_C_DECL = os.environ.get('INCLUDE_C_DECL', '0') != '0'
-INCLUDE_DEPRECATED = os.environ.get('INCLUDE_DEPRECATED', '0') != '0'
-
-log = logging.getLogger(__name__)
-
-LOG_LEVELS = {
- logging.getLevelName(level): level for level in [
- logging.DEBUG, logging.INFO, logging.ERROR
- ]
-}
-
-text_width = 78
-indentation = 4
-SECTION_SEP = '=' * text_width
-
-script_path = os.path.abspath(__file__)
-base_dir = os.path.dirname(os.path.dirname(script_path))
-out_dir = os.path.join(base_dir, 'tmp-{target}-doc')
-filter_cmd = '%s %s' % (sys.executable, script_path)
-msgs = [] # Messages to show on exit.
-lua2dox = os.path.join(base_dir, 'scripts', 'lua2dox.lua')
-
-
-SectionName = str
-
-Docstring = str # Represents (formatted) vimdoc string
-
-FunctionName = str
-
-
-@dataclasses.dataclass
-class Config:
- """Config for documentation."""
-
- mode: Literal['c', 'lua']
-
- filename: str
- """Generated documentation target, e.g. api.txt"""
-
- section_order: List[str]
- """Section ordering."""
-
- files: List[str]
- """List of files/directories for doxygen to read, relative to `base_dir`."""
-
- file_patterns: str
- """file patterns used by doxygen."""
-
- section_name: Dict[str, SectionName]
- """Section name overrides. Key: filename (e.g., vim.c)"""
-
- section_fmt: Callable[[SectionName], str]
- """For generated section names."""
-
- helptag_fmt: Callable[[SectionName], str]
- """Section helptag."""
-
- fn_helptag_fmt: Callable[[str, str, bool], str]
- """Per-function helptag."""
-
- module_override: Dict[str, str]
- """Module name overrides (for Lua)."""
-
- append_only: List[str]
- """Append the docs for these modules, do not start a new section."""
-
- fn_name_prefix: str
- """Only function with this prefix are considered"""
-
- fn_name_fmt: Callable[[str, str], str] | None = None
-
- include_tables: bool = True
-
-
-CONFIG: Dict[str, Config] = {
- 'api': Config(
- mode='c',
- filename = 'api.txt',
- # Section ordering.
- section_order=[x for x in [
- 'vim.c',
- 'vimscript.c',
- 'command.c',
- 'options.c',
- 'buffer.c',
- 'extmark.c',
- 'window.c',
- 'win_config.c',
- 'tabpage.c',
- 'autocmd.c',
- 'ui.c',
- 'deprecated.c' if INCLUDE_DEPRECATED else ''
- ] if x],
- files=['src/nvim/api'],
- file_patterns = '*.h *.c',
- fn_name_prefix = 'nvim_',
- section_name={
- 'vim.c': 'Global',
- },
- section_fmt=lambda name: f'{name} Functions',
- helptag_fmt=lambda name: f'*api-{name.lower()}*',
- fn_helptag_fmt=lambda fstem, name, istbl: f'*{name}()*',
- module_override={},
- append_only=[],
- ),
- 'lua': Config(
- mode='lua',
- filename='lua.txt',
- section_order=[
- 'highlight.lua',
- 'diff.lua',
- 'mpack.lua',
- 'json.lua',
- 'base64.lua',
- 'spell.lua',
- 'builtin.lua',
- '_options.lua',
- '_editor.lua',
- '_inspector.lua',
- 'shared.lua',
- 'loader.lua',
- 'uri.lua',
- 'ui.lua',
- 'filetype.lua',
- 'keymap.lua',
- 'fs.lua',
- 'glob.lua',
- 'lpeg.lua',
- 're.lua',
- 'regex.lua',
- 'secure.lua',
- 'version.lua',
- 'iter.lua',
- 'snippet.lua',
- 'text.lua',
- ],
- files=[
- 'runtime/lua/vim/iter.lua',
- 'runtime/lua/vim/_editor.lua',
- 'runtime/lua/vim/_options.lua',
- 'runtime/lua/vim/shared.lua',
- 'runtime/lua/vim/loader.lua',
- 'runtime/lua/vim/uri.lua',
- 'runtime/lua/vim/ui.lua',
- 'runtime/lua/vim/filetype.lua',
- 'runtime/lua/vim/keymap.lua',
- 'runtime/lua/vim/fs.lua',
- 'runtime/lua/vim/highlight.lua',
- 'runtime/lua/vim/secure.lua',
- 'runtime/lua/vim/version.lua',
- 'runtime/lua/vim/_inspector.lua',
- 'runtime/lua/vim/snippet.lua',
- 'runtime/lua/vim/text.lua',
- 'runtime/lua/vim/glob.lua',
- 'runtime/lua/vim/_meta/builtin.lua',
- 'runtime/lua/vim/_meta/diff.lua',
- 'runtime/lua/vim/_meta/mpack.lua',
- 'runtime/lua/vim/_meta/json.lua',
- 'runtime/lua/vim/_meta/base64.lua',
- 'runtime/lua/vim/_meta/regex.lua',
- 'runtime/lua/vim/_meta/lpeg.lua',
- 'runtime/lua/vim/_meta/re.lua',
- 'runtime/lua/vim/_meta/spell.lua',
- ],
- file_patterns='*.lua',
- fn_name_prefix='',
- fn_name_fmt=lambda fstem, name: (
- name if fstem in [ 'vim.iter' ] else
- f'vim.{name}' if fstem in [ '_editor', 'vim.regex'] else
- f'vim.{name}' if fstem == '_options' and not name[0].isupper() else
- f'{fstem}.{name}' if fstem.startswith('vim') else
- name
- ),
- section_name={
- 'lsp.lua': 'core',
- '_inspector.lua': 'inspector',
- },
- section_fmt=lambda name: (
- 'Lua module: vim' if name.lower() == '_editor' else
- 'LUA-VIMSCRIPT BRIDGE' if name.lower() == '_options' else
- f'VIM.{name.upper()}' if name.lower() in [
- 'highlight', 'mpack', 'json', 'base64', 'diff', 'spell',
- 'regex', 'lpeg', 're',
- ] else
- 'VIM' if name.lower() == 'builtin' else
- f'Lua module: vim.{name.lower()}'),
- helptag_fmt=lambda name: (
- '*lua-vim*' if name.lower() == '_editor' else
- '*lua-vimscript*' if name.lower() == '_options' else
- f'*vim.{name.lower()}*'),
- fn_helptag_fmt=lambda fstem, name, istbl: (
- f'*vim.opt:{name.split(":")[-1]}()*' if ':' in name and name.startswith('Option') else
- # Exclude fstem for methods
- f'*{name}()*' if ':' in name else
- f'*vim.{name}()*' if fstem.lower() == '_editor' else
- f'*vim.{name}*' if fstem.lower() == '_options' and istbl else
- # Prevents vim.regex.regex
- f'*{fstem}()*' if fstem.endswith('.' + name) else
- f'*{fstem}.{name}{"" if istbl else "()"}*'
- ),
- module_override={
- # `shared` functions are exposed on the `vim` module.
- 'shared': 'vim',
- '_inspector': 'vim',
- 'uri': 'vim',
- 'ui': 'vim.ui',
- 'loader': 'vim.loader',
- 'filetype': 'vim.filetype',
- 'keymap': 'vim.keymap',
- 'fs': 'vim.fs',
- 'highlight': 'vim.highlight',
- 'secure': 'vim.secure',
- 'version': 'vim.version',
- 'iter': 'vim.iter',
- 'diff': 'vim',
- 'builtin': 'vim',
- 'mpack': 'vim.mpack',
- 'json': 'vim.json',
- 'base64': 'vim.base64',
- 'regex': 'vim.regex',
- 'lpeg': 'vim.lpeg',
- 're': 'vim.re',
- 'spell': 'vim.spell',
- 'snippet': 'vim.snippet',
- 'text': 'vim.text',
- 'glob': 'vim.glob',
- },
- append_only=[
- 'shared.lua',
- ],
- ),
- 'lsp': Config(
- mode='lua',
- filename='lsp.txt',
- section_order=[
- 'lsp.lua',
- 'buf.lua',
- 'diagnostic.lua',
- 'codelens.lua',
- 'inlay_hint.lua',
- 'tagfunc.lua',
- 'semantic_tokens.lua',
- 'handlers.lua',
- 'util.lua',
- 'log.lua',
- 'rpc.lua',
- 'protocol.lua',
- ],
- files=[
- 'runtime/lua/vim/lsp',
- 'runtime/lua/vim/lsp.lua',
- ],
- file_patterns='*.lua',
- fn_name_prefix='',
- section_name={'lsp.lua': 'lsp'},
- section_fmt=lambda name: (
- 'Lua module: vim.lsp'
- if name.lower() == 'lsp'
- else f'Lua module: vim.lsp.{name.lower()}'),
- helptag_fmt=lambda name: (
- '*lsp-core*'
- if name.lower() == 'lsp'
- else f'*lsp-{name.lower()}*'),
- fn_helptag_fmt=lambda fstem, name, istbl: (
- f'*vim.lsp.{name}{"" if istbl else "()"}*' if fstem == 'lsp' and name != 'client' else
- # HACK. TODO(justinmk): class/structure support in lua2dox
- '*vim.lsp.client*' if 'lsp.client' == f'{fstem}.{name}' else
- f'*vim.lsp.{fstem}.{name}{"" if istbl else "()"}*'),
- module_override={},
- append_only=[],
- ),
- 'diagnostic': Config(
- mode='lua',
- filename='diagnostic.txt',
- section_order=[
- 'diagnostic.lua',
- ],
- files=['runtime/lua/vim/diagnostic.lua'],
- file_patterns='*.lua',
- fn_name_prefix='',
- include_tables=False,
- section_name={'diagnostic.lua': 'diagnostic'},
- section_fmt=lambda _: 'Lua module: vim.diagnostic',
- helptag_fmt=lambda _: '*diagnostic-api*',
- fn_helptag_fmt=lambda fstem, name, istbl: f'*vim.{fstem}.{name}{"" if istbl else "()"}*',
- module_override={},
- append_only=[],
- ),
- 'treesitter': Config(
- mode='lua',
- filename='treesitter.txt',
- section_order=[
- 'treesitter.lua',
- 'language.lua',
- 'query.lua',
- 'highlighter.lua',
- 'languagetree.lua',
- 'dev.lua',
- ],
- files=[
- 'runtime/lua/vim/treesitter.lua',
- 'runtime/lua/vim/treesitter/',
- ],
- file_patterns='*.lua',
- fn_name_prefix='',
- section_name={},
- section_fmt=lambda name: (
- 'Lua module: vim.treesitter'
- if name.lower() == 'treesitter'
- else f'Lua module: vim.treesitter.{name.lower()}'),
- helptag_fmt=lambda name: (
- '*lua-treesitter-core*'
- if name.lower() == 'treesitter'
- else f'*lua-treesitter-{name.lower()}*'),
- fn_helptag_fmt=lambda fstem, name, istbl: (
- f'*vim.{fstem}.{name}()*'
- if fstem == 'treesitter'
- else f'*{name}()*'
- if name[0].isupper()
- else f'*vim.treesitter.{fstem}.{name}()*'),
- module_override={},
- append_only=[],
- ),
-}
-
-param_exclude = (
- 'channel_id',
-)
-
-# Annotations are displayed as line items after API function descriptions.
-annotation_map = {
- 'FUNC_API_FAST': '|api-fast|',
- 'FUNC_API_TEXTLOCK': 'not allowed when |textlock| is active or in the |cmdwin|',
- 'FUNC_API_TEXTLOCK_ALLOW_CMDWIN': 'not allowed when |textlock| is active',
- 'FUNC_API_REMOTE_ONLY': '|RPC| only',
- 'FUNC_API_LUA_ONLY': 'Lua |vim.api| only',
-}
-
-
-def nvim_api_info() -> Tuple[int, bool]:
- """Returns NVIM_API_LEVEL, NVIM_API_PRERELEASE from CMakeLists.txt"""
- if not hasattr(nvim_api_info, 'LEVEL'):
- script_dir = os.path.dirname(os.path.abspath(__file__))
- cmake_file_path = os.path.join(script_dir, '..', 'CMakeLists.txt')
- with open(cmake_file_path, 'r') as cmake_file:
- cmake_content = cmake_file.read()
-
- api_level_match = re.search(r'set\(NVIM_API_LEVEL (\d+)\)', cmake_content)
- api_prerelease_match = re.search(
- r'set\(NVIM_API_PRERELEASE (\w+)\)', cmake_content
- )
-
- if not api_level_match or not api_prerelease_match:
- raise RuntimeError(
- 'Could not find NVIM_API_LEVEL or NVIM_API_PRERELEASE in CMakeLists.txt'
- )
-
- nvim_api_info.LEVEL = int(api_level_match.group(1))
- nvim_api_info.PRERELEASE = api_prerelease_match.group(1).lower() == 'true'
-
- return nvim_api_info.LEVEL, nvim_api_info.PRERELEASE
-
-
-# Raises an error with details about `o`, if `cond` is in object `o`,
-# or if `cond()` is callable and returns True.
-def debug_this(o, cond=True):
- name = ''
- if cond is False:
- return
- if not isinstance(o, str):
- try:
- name = o.nodeName
- o = o.toprettyxml(indent=' ', newl='\n')
- except Exception:
- pass
- if (cond is True
- or (callable(cond) and cond())
- or (not callable(cond) and cond in o)):
- raise RuntimeError('xxx: {}\n{}'.format(name, o))
-
-
-# Appends a message to a list which will be printed on exit.
-def msg(s):
- msgs.append(s)
-
-
-# Print all collected messages.
-def msg_report():
- for m in msgs:
- print(f' {m}')
-
-
-# Print collected messages, then throw an exception.
-def fail(s):
- msg_report()
- raise RuntimeError(s)
-
-
-def find_first(parent, name):
- """Finds the first matching node within parent."""
- sub = parent.getElementsByTagName(name)
- if not sub:
- return None
- return sub[0]
-
-
-def iter_children(parent, name):
- """Yields matching child nodes within parent."""
- for child in parent.childNodes:
- if child.nodeType == child.ELEMENT_NODE and child.nodeName == name:
- yield child
-
-
-def get_child(parent, name):
- """Gets the first matching child node."""
- for child in iter_children(parent, name):
- return child
- return None
-
-
-def self_or_child(n):
- """Gets the first child node, or self."""
- if len(n.childNodes) == 0:
- return n
- return n.childNodes[0]
-
-
-def align_tags(line):
- tag_regex = r"\s(\*.+?\*)(?:\s|$)"
- tags = re.findall(tag_regex, line)
-
- if len(tags) > 0:
- line = re.sub(tag_regex, "", line)
- tags = " " + " ".join(tags)
- line = line + (" " * (78 - len(line) - len(tags))) + tags
- return line
-
-
-def clean_lines(text):
- """Removes superfluous lines.
-
- The beginning and end of the string is trimmed. Empty lines are collapsed.
- """
- return re.sub(r'\A\n\s*\n*|\n\s*\n*\Z', '', re.sub(r'(\n\s*\n+)+', '\n\n', text))
-
-
-def is_blank(text):
- return '' == clean_lines(text)
-
-
-def get_text(n):
- """Recursively concatenates all text in a node tree."""
- text = ''
- if n.nodeType == n.TEXT_NODE:
- return n.data
- if n.nodeName == 'computeroutput':
- for node in n.childNodes:
- text += get_text(node)
- return '`{}`'.format(text)
- if n.nodeName == 'sp': # space, used in "programlisting" nodes
- return ' '
- for node in n.childNodes:
- if node.nodeType == node.TEXT_NODE:
- text += node.data
- elif node.nodeType == node.ELEMENT_NODE:
- text += get_text(node)
- return text
-
-
-# Gets the length of the last line in `text`, excluding newline ("\n") char.
-def len_lastline(text):
- lastnl = text.rfind('\n')
- if -1 == lastnl:
- return len(text)
- if '\n' == text[-1]:
- return lastnl - (1 + text.rfind('\n', 0, lastnl))
- return len(text) - (1 + lastnl)
-
-
-def len_lastline_withoutindent(text, indent):
- n = len_lastline(text)
- return (n - len(indent)) if n > len(indent) else 0
-
-
-# Returns True if node `n` contains only inline (not block-level) elements.
-def is_inline(n):
- # if len(n.childNodes) == 0:
- # return n.nodeType == n.TEXT_NODE or n.nodeName == 'computeroutput'
- for c in n.childNodes:
- if c.nodeType != c.TEXT_NODE and c.nodeName != 'computeroutput':
- return False
- if not is_inline(c):
- return False
- return True
-
-
-def doc_wrap(text, prefix='', width=70, func=False, indent=None) -> str:
- """Wraps text to `width`.
-
- First line is prefixed with `prefix`, subsequent lines are aligned.
- If `func` is True, only wrap at commas.
- """
- if not width:
- # return prefix + text
- return text
-
- # Whitespace used to indent all lines except the first line.
- indent = ' ' * len(prefix) if indent is None else indent
- indent_only = (prefix == '' and indent is not None)
-
- if func:
- lines = [prefix]
- for part in text.split(', '):
- if part[-1] not in ');':
- part += ', '
- if len(lines[-1]) + len(part) > width:
- lines.append(indent)
- lines[-1] += part
- return '\n'.join(x.rstrip() for x in lines).rstrip()
-
- # XXX: Dummy prefix to force TextWrapper() to wrap the first line.
- if indent_only:
- prefix = indent
-
- tw = textwrap.TextWrapper(break_long_words=False,
- break_on_hyphens=False,
- width=width,
- initial_indent=prefix,
- subsequent_indent=indent)
- result = '\n'.join(tw.wrap(text.strip()))
-
- # XXX: Remove the dummy prefix.
- if indent_only:
- result = result[len(indent):]
-
- return result
-
-
-def max_name(names):
- if len(names) == 0:
- return 0
- return max(len(name) for name in names)
-
-
-def update_params_map(parent, ret_map, width=text_width - indentation):
- """Updates `ret_map` with name:desc key-value pairs extracted
- from Doxygen XML node `parent`.
- """
- params = collections.OrderedDict()
- for node in parent.childNodes:
- if node.nodeType == node.TEXT_NODE:
- continue
- name_node = find_first(node, 'parametername')
- if name_node.getAttribute('direction') == 'out':
- continue
- name = get_text(name_node)
- if name in param_exclude:
- continue
- params[name.strip()] = node
- max_name_len = max_name(params.keys()) + 8
- # `ret_map` is a name:desc map.
- for name, node in params.items():
- desc = ''
- desc_node = get_child(node, 'parameterdescription')
- if desc_node:
- desc = fmt_node_as_vimhelp(
- desc_node, width=width, indent=(' ' * max_name_len))
- ret_map[name] = desc
- return ret_map
-
-
-def render_node(n: Element, text: str, prefix='', *,
- indent: str = '',
- width: int = (text_width - indentation),
- fmt_vimhelp: bool = False):
- """Renders a node as Vim help text, recursively traversing all descendants."""
-
- def ind(s):
- return s if fmt_vimhelp else ''
-
- # Get the current column offset from the last line of `text`
- # (needed to appropriately wrap multiple and contiguous inline elements)
- col_offset: int = len_lastline(text)
-
- text = ''
- # space_preceding = (len(text) > 0 and ' ' == text[-1][-1])
- # text += (int(not space_preceding) * ' ')
-
- if n.nodeName == 'preformatted':
- o = get_text(n)
- ensure_nl = '' if o[-1] == '\n' else '\n'
- if o[0:4] == 'lua\n':
- text += '>lua{}{}\n<'.format(ensure_nl, o[3:-1])
- elif o[0:4] == 'vim\n':
- text += '>vim{}{}\n<'.format(ensure_nl, o[3:-1])
- elif o[0:5] == 'help\n':
- text += o[4:-1]
- else:
- text += '>{}{}\n<'.format(ensure_nl, o)
- elif n.nodeName == 'programlisting': # codeblock (```)
- o = get_text(n)
- text += '>'
- if 'filename' in n.attributes:
- filename = n.attributes['filename'].value
- text += filename.lstrip('.')
-
- text += '\n{}\n<'.format(textwrap.indent(o, ' ' * 4))
- elif is_inline(n):
- o = get_text(n).strip()
- if o:
- DEL = chr(127) # a dummy character to pad for proper line wrap
- assert len(DEL) == 1
- dummy_padding = DEL * max(0, col_offset - len(prefix))
- text += doc_wrap(dummy_padding + o,
- prefix=prefix, indent=indent, width=width
- ).replace(DEL, "")
- elif n.nodeName == 'verbatim':
- # TODO: currently we don't use this. The "[verbatim]" hint is there as
- # a reminder that we must decide how to format this if we do use it.
- text += ' [verbatim] {}'.format(get_text(n))
- elif n.nodeName == 'listitem':
- for c in n.childNodes:
- result = render_node(
- c,
- text,
- indent=indent + (' ' * len(prefix)),
- width=width
- )
- if is_blank(result):
- continue
- text += indent + prefix + result
- elif n.nodeName in ('para', 'heading'):
- did_prefix = False
- for c in n.childNodes:
- c_text = render_node(c, text, prefix=(prefix if not did_prefix else ''), indent=indent, width=width)
- if (is_inline(c)
- and '' != c_text.strip()
- and text
- and text[-1] not in (' ', '(', '|')
- and not c_text.startswith(')')):
- text += ' '
- text += c_text
- did_prefix = True
- elif n.nodeName == 'itemizedlist':
- for c in n.childNodes:
- text += '{}\n'.format(render_node(c, text, prefix='• ',
- indent=indent, width=width))
- elif n.nodeName == 'orderedlist':
- i = 1
- for c in n.childNodes:
- if is_blank(get_text(c)):
- text += '\n'
- continue
- text += '{}\n'.format(render_node(c, text, prefix='{}. '.format(i),
- indent=indent, width=width))
- i = i + 1
- elif n.nodeName == 'simplesect' and 'note' == n.getAttribute('kind'):
- text += ind(' ')
- for c in n.childNodes:
- if is_blank(render_node(c, text, prefix='• ', indent=' ', width=width)):
- continue
- text += render_node(c, text, prefix='• ', indent=' ', width=width)
- # text += '\n'
- elif n.nodeName == 'simplesect' and 'warning' == n.getAttribute('kind'):
- text += 'Warning:\n '
- for c in n.childNodes:
- text += render_node(c, text, indent=' ', width=width)
- text += '\n'
- elif n.nodeName == 'simplesect' and 'see' == n.getAttribute('kind'):
- text += ind(' ')
- # Example:
- # <simplesect kind="see">
- # <para>|autocommand|</para>
- # </simplesect>
- for c in n.childNodes:
- text += render_node(c, text, prefix='• ', indent=' ', width=width)
- elif n.nodeName == 'simplesect' and 'return' == n.getAttribute('kind'):
- text += ind(' ')
- for c in n.childNodes:
- text += render_node(c, text, indent=' ', width=width)
- elif n.nodeName == 'computeroutput':
- return get_text(n)
- else:
- raise RuntimeError('unhandled node type: {}\n{}'.format(
- n.nodeName, n.toprettyxml(indent=' ', newl='\n')))
-
- return text
-
-
-def para_as_map(parent: Element,
- indent: str = '',
- width: int = (text_width - indentation),
- ):
- """Extracts a Doxygen XML <para> node to a map.
-
- Keys:
- 'text': Text from this <para> element
- 'note': List of @note strings
- 'params': <parameterlist> map
- 'return': List of @return strings
- 'seealso': List of @see strings
- 'xrefs': ?
- """
- chunks = {
- 'text': '',
- 'note': [],
- 'params': collections.OrderedDict(),
- 'return': [],
- 'seealso': [],
- 'prerelease': False,
- 'xrefs': []
- }
-
- # Ordered dict of ordered lists.
- groups = collections.OrderedDict([
- ('note', []),
- ('params', []),
- ('return', []),
- ('seealso', []),
- ('xrefs', []),
- ])
-
- # Gather nodes into groups. Mostly this is because we want "parameterlist"
- # nodes to appear together.
- text = ''
- kind = ''
- if is_inline(parent):
- # Flatten inline text from a tree of non-block nodes.
- text = doc_wrap(render_node(parent, ""),
- indent=indent, width=width)
- else:
- prev = None # Previous node
- for child in parent.childNodes:
- if child.nodeName == 'parameterlist':
- groups['params'].append(child)
- elif child.nodeName == 'xrefsect':
- groups['xrefs'].append(child)
- elif child.nodeName == 'simplesect':
- kind = child.getAttribute('kind')
- if kind == 'note':
- groups['note'].append(child)
- elif kind == 'return':
- groups['return'].append(child)
- elif kind == 'see':
- groups['seealso'].append(child)
- elif kind == 'warning':
- text += render_node(child, text, indent=indent, width=width)
- elif kind == 'since':
- since_match = re.match(r'^(\d+)', get_text(child))
- since = int(since_match.group(1)) if since_match else 0
- NVIM_API_LEVEL, NVIM_API_PRERELEASE = nvim_api_info()
- if since > NVIM_API_LEVEL or (
- since == NVIM_API_LEVEL and NVIM_API_PRERELEASE
- ):
- chunks['prerelease'] = True
- else:
- raise RuntimeError('unhandled simplesect: {}\n{}'.format(
- child.nodeName, child.toprettyxml(indent=' ', newl='\n')))
- else:
- child_text = render_node(child, text, indent=indent, width=width)
- if (prev is not None
- and is_inline(self_or_child(prev))
- and is_inline(self_or_child(child))
- and '' != get_text(self_or_child(child)).strip()
- and text
- and text[-1] not in (' ', '(', '|')
- and not child_text.startswith(')')):
- text += ' '
-
- text += child_text
- prev = child
-
- chunks['text'] += text
-
- # Generate map from the gathered items.
- if len(groups['params']) > 0:
- for child in groups['params']:
- update_params_map(child, ret_map=chunks['params'], width=width)
- for child in groups['note']:
- chunks['note'].append(render_node(
- child, '', indent=indent, width=width).rstrip())
- for child in groups['return']:
- chunks['return'].append(render_node(
- child, '', indent=indent, width=width))
- for child in groups['seealso']:
- # Example:
- # <simplesect kind="see">
- # <para>|autocommand|</para>
- # </simplesect>
- chunks['seealso'].append(render_node(
- child, '', indent=indent, width=width))
-
- xrefs = set()
- for child in groups['xrefs']:
- # XXX: Add a space (or any char) to `title` here, otherwise xrefs
- # ("Deprecated" section) acts very weird...
- title = get_text(get_child(child, 'xreftitle')) + ' '
- xrefs.add(title)
- xrefdesc = get_text(get_child(child, 'xrefdescription'))
- chunks['xrefs'].append(doc_wrap(xrefdesc, prefix='{}: '.format(title),
- width=width) + '\n')
-
- return chunks, xrefs
-
-
-def is_program_listing(para):
- """
- Return True if `para` contains a "programlisting" (i.e. a Markdown code
- block ```).
-
- Sometimes a <para> element will have only a single "programlisting" child
- node, but othertimes it will have extra whitespace around the
- "programlisting" node.
-
- @param para XML <para> node
- @return True if <para> is a programlisting
- """
-
- # Remove any child text nodes that are only whitespace
- children = [
- n for n in para.childNodes
- if n.nodeType != n.TEXT_NODE or n.data.strip() != ''
- ]
-
- return len(children) == 1 and children[0].nodeName == 'programlisting'
-
-
-FunctionParam = Tuple[
- str, # type
- str, # parameter name
-]
-
-@dataclasses.dataclass
-class FunctionDoc:
- """Data structure for function documentation. Also exported as msgpack."""
-
- annotations: List[str]
- """Attributes, e.g., FUNC_API_REMOTE_ONLY. See annotation_map"""
-
- notes: List[Docstring]
- """Notes: (@note strings)"""
-
- signature: str
- """Function signature with *tags*."""
-
- parameters: List[FunctionParam]
- """Parameters: (type, name)"""
-
- parameters_doc: Dict[str, Docstring]
- """Parameters documentation. Key is parameter name, value is doc."""
-
- doc: List[Docstring]
- """Main description for the function. Separated by paragraph."""
-
- return_: List[Docstring]
- """Return:, or Return (multiple): (@return strings)"""
-
- seealso: List[Docstring]
- """See also: (@see strings)"""
-
- xrefs: List[Docstring]
- """XRefs. Currently only used to track Deprecated functions."""
-
- # for INCLUDE_C_DECL
- c_decl: str | None = None
-
- prerelease: bool = False
-
- def export_mpack(self) -> Dict[str, Any]:
- """Convert a dict to be exported as mpack data."""
- exported = self.__dict__.copy()
- del exported['notes']
- del exported['c_decl']
- del exported['prerelease']
- del exported['xrefs']
- exported['return'] = exported.pop('return_')
- return exported
-
- def doc_concatenated(self) -> Docstring:
- """Concatenate all the paragraphs in `doc` into a single string, but
- remove blank lines before 'programlisting' blocks. #25127
-
- BEFORE (without programlisting processing):
- ```vimdoc
- Example:
-
- >vim
- :echo nvim_get_color_by_name("Pink")
- <
- ```
-
- AFTER:
- ```vimdoc
- Example: >vim
- :echo nvim_get_color_by_name("Pink")
- <
- ```
- """
- def is_program_listing(paragraph: str) -> bool:
- lines = paragraph.strip().split('\n')
- return lines[0].startswith('>') and lines[-1] == '<'
-
- rendered = []
- for paragraph in self.doc:
- if is_program_listing(paragraph):
- rendered.append(' ') # Example: >vim
- elif rendered:
- rendered.append('\n\n')
- rendered.append(paragraph)
- return ''.join(rendered)
-
- def render(self) -> Docstring:
- """Renders function documentation as Vim :help text."""
- rendered_blocks: List[Docstring] = []
-
- def fmt_param_doc(m):
- """Renders a params map as Vim :help text."""
- max_name_len = max_name(m.keys()) + 4
- out = ''
- for name, desc in m.items():
- if name == 'self':
- continue
- name = ' • {}'.format('{{{}}}'.format(name).ljust(max_name_len))
- out += '{}{}\n'.format(name, desc)
- return out.rstrip()
-
- # Generate text from the gathered items.
- chunks: List[Docstring] = [self.doc_concatenated()]
-
- notes = []
- if self.prerelease:
- notes = [" This API is pre-release (unstable)."]
- notes += self.notes
- if len(notes) > 0:
- chunks.append('\nNote: ~')
- for s in notes:
- chunks.append(' ' + s)
-
- if self.parameters_doc:
- chunks.append('\nParameters: ~')
- chunks.append(fmt_param_doc(self.parameters_doc))
-
- if self.return_:
- chunks.append('\nReturn (multiple): ~' if len(self.return_) > 1
- else '\nReturn: ~')
- for s in self.return_:
- chunks.append(' ' + s)
-
- if self.seealso:
- chunks.append('\nSee also: ~')
- for s in self.seealso:
- chunks.append(' ' + s)
-
- # Note: xrefs are currently only used to remark "Deprecated: "
- # for deprecated functions; visible when INCLUDE_DEPRECATED is set
- for s in self.xrefs:
- chunks.append('\n' + s)
-
- rendered_blocks.append(clean_lines('\n'.join(chunks).strip()))
- rendered_blocks.append('')
-
- return clean_lines('\n'.join(rendered_blocks).strip())
-
-
-def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent=''):
- """Renders (nested) Doxygen <para> nodes as Vim :help text.
-
- Only handles "text" nodes. Used for individual elements (see render_node())
- and in extract_defgroups().
-
- NB: Blank lines in a docstring manifest as <para> tags.
- """
- rendered_blocks = []
-
- for child in parent.childNodes:
- para, _ = para_as_map(child, indent, width)
-
- # 'programlisting' blocks are Markdown code blocks. Do not include
- # these as a separate paragraph, but append to the last non-empty line
- # in the text
- if is_program_listing(child):
- while rendered_blocks and rendered_blocks[-1] == '':
- rendered_blocks.pop()
- rendered_blocks[-1] += ' ' + para['text']
- continue
-
- # Generate text from the gathered items.
- chunks = [para['text']]
-
- rendered_blocks.append(clean_lines('\n'.join(chunks).strip()))
- rendered_blocks.append('')
-
- return clean_lines('\n'.join(rendered_blocks).strip())
-
-
-def extract_from_xml(filename, target, *,
- width: int, fmt_vimhelp: bool) -> Tuple[
- Dict[FunctionName, FunctionDoc],
- Dict[FunctionName, FunctionDoc],
-]:
- """Extracts Doxygen info as maps without formatting the text.
-
- Returns two maps:
- 1. Functions
- 2. Deprecated functions
-
- The `fmt_vimhelp` variable controls some special cases for use by
- fmt_doxygen_xml_as_vimhelp(). (TODO: ugly :)
- """
- config: Config = CONFIG[target]
-
- fns: Dict[FunctionName, FunctionDoc] = {}
- deprecated_fns: Dict[FunctionName, FunctionDoc] = {}
-
- dom = minidom.parse(filename)
- compoundname = get_text(dom.getElementsByTagName('compoundname')[0])
- for member in dom.getElementsByTagName('memberdef'):
- if member.getAttribute('static') == 'yes' or \
- member.getAttribute('kind') != 'function' or \
- member.getAttribute('prot') == 'private' or \
- get_text(get_child(member, 'name')).startswith('_'):
- continue
-
- loc = find_first(member, 'location')
- if 'private' in loc.getAttribute('file'):
- continue
-
- return_type = get_text(get_child(member, 'type'))
- if return_type == '':
- continue
-
- if 'local_function' in return_type: # Special from lua2dox.lua.
- continue
-
- istbl = return_type.startswith('table') # Special from lua2dox.lua.
- if istbl and not config.include_tables:
- continue
-
- if return_type.startswith(('ArrayOf', 'DictionaryOf')):
- parts = return_type.strip('_').split('_')
- return_type = '{}({})'.format(parts[0], ', '.join(parts[1:]))
-
- name = get_text(get_child(member, 'name'))
-
- annotations = get_text(get_child(member, 'argsstring'))
- if annotations and ')' in annotations:
- annotations = annotations.rsplit(')', 1)[-1].strip()
- # XXX: (doxygen 1.8.11) 'argsstring' only includes attributes of
- # non-void functions. Special-case void functions here.
- if name == 'nvim_get_mode' and len(annotations) == 0:
- annotations += 'FUNC_API_FAST'
- annotations = filter(None, map(lambda x: annotation_map.get(x),
- annotations.split()))
-
- params = []
- type_length = 0
-
- for param in iter_children(member, 'param'):
- param_type = get_text(get_child(param, 'type')).strip()
- param_name = ''
- declname = get_child(param, 'declname')
- if declname:
- param_name = get_text(declname).strip()
- elif config.mode == 'lua':
- # XXX: this is what lua2dox gives us...
- param_name = param_type
- param_type = ''
-
- if param_name in param_exclude:
- continue
-
- if fmt_vimhelp and param_type.endswith('*'):
- param_type = param_type.strip('* ')
- param_name = '*' + param_name
-
- type_length = max(type_length, len(param_type))
- params.append((param_type, param_name))
-
- # Handle Object Oriented style functions here.
- # We make sure they have "self" in the parameters,
- # and a parent function
- if return_type.startswith('function') \
- and len(return_type.split(' ')) >= 2 \
- and any(x[1] == 'self' for x in params):
- split_return = return_type.split(' ')
- name = f'{split_return[1]}:{name}'
- params = [x for x in params if x[1] != 'self']
-
- c_args = []
- for param_type, param_name in params:
- c_args.append((' ' if fmt_vimhelp else '') + (
- '%s %s' % (param_type.ljust(type_length), param_name)).strip())
-
- if not fmt_vimhelp:
- pass
- else:
- fstem = '?'
- if '.' in compoundname:
- fstem = compoundname.split('.')[0]
- fstem = config.module_override.get(fstem, fstem)
- vimtag = config.fn_helptag_fmt(fstem, name, istbl)
-
- if config.fn_name_fmt:
- name = config.fn_name_fmt(fstem, name)
-
- if istbl:
- aopen, aclose = '', ''
- else:
- aopen, aclose = '(', ')'
-
- prefix = name + aopen
- suffix = ', '.join('{%s}' % a[1] for a in params
- if a[0] not in ('void', 'Error', 'Arena',
- 'lua_State')) + aclose
-
- if not fmt_vimhelp:
- c_decl = '%s %s(%s);' % (return_type, name, ', '.join(c_args))
- signature = prefix + suffix
- else:
- c_decl = textwrap.indent('%s %s(\n%s\n);' % (return_type, name,
- ',\n'.join(c_args)),
- ' ')
-
- # Minimum 8 chars between signature and vimtag
- lhs = (width - 8) - len(vimtag)
-
- if len(prefix) + len(suffix) > lhs:
- signature = vimtag.rjust(width) + '\n'
- signature += doc_wrap(suffix, width=width, prefix=prefix,
- func=True)
- else:
- signature = prefix + suffix
- signature += vimtag.rjust(width - len(signature))
-
- # Tracks `xrefsect` titles. As of this writing, used only for separating
- # deprecated functions.
- xrefs_all = set()
- paras: List[Dict[str, Any]] = [] # paras means paragraphs!
- brief_desc = find_first(member, 'briefdescription')
- if brief_desc:
- for child in brief_desc.childNodes:
- para, xrefs = para_as_map(child)
- paras.append(para)
- xrefs_all.update(xrefs)
-
- desc = find_first(member, 'detaileddescription')
- if desc:
- paras_detail = [] # override briefdescription
- for child in desc.childNodes:
- para, xrefs = para_as_map(child)
- paras_detail.append(para)
- xrefs_all.update(xrefs)
- log.debug(
- textwrap.indent(
- re.sub(r'\n\s*\n+', '\n',
- desc.toprettyxml(indent=' ', newl='\n')),
- ' ' * indentation))
-
- # override briefdescription, if detaileddescription is not empty
- # (note: briefdescription can contain some erroneous luadoc
- # comments from preceding comments, this is a bug of lua2dox)
- if any((para['text'] or para['note'] or para['params'] or
- para['return'] or para['seealso']
- ) for para in paras_detail):
- paras = paras_detail
-
- fn = FunctionDoc(
- annotations=list(annotations),
- notes=[],
- signature=signature,
- parameters=params,
- parameters_doc=collections.OrderedDict(),
- doc=[],
- return_=[],
- seealso=[],
- xrefs=[],
- )
-
- for m in paras:
- if m.get('text', ''):
- fn.doc.append(m['text'])
- if 'params' in m:
- # Merge OrderedDicts.
- fn.parameters_doc.update(m['params'])
- if 'return' in m and len(m['return']) > 0:
- fn.return_ += m['return']
- if 'seealso' in m and len(m['seealso']) > 0:
- fn.seealso += m['seealso']
- if m.get('prerelease', False):
- fn.prerelease = True
- if 'note' in m:
- fn.notes += m['note']
- if 'xrefs' in m:
- fn.xrefs += m['xrefs']
-
- if INCLUDE_C_DECL:
- fn.c_decl = c_decl
-
- if 'Deprecated' in str(xrefs_all):
- deprecated_fns[name] = fn
- elif name.startswith(config.fn_name_prefix):
- fns[name] = fn
-
- # sort functions by name (lexicographically)
- fns = collections.OrderedDict(sorted(
- fns.items(),
- key=lambda key_item_tuple: key_item_tuple[0].lower(),
- ))
- deprecated_fns = collections.OrderedDict(sorted(deprecated_fns.items()))
- return fns, deprecated_fns
-
-
-def fmt_doxygen_xml_as_vimhelp(filename, target) -> Tuple[Docstring, Docstring]:
- """Entrypoint for generating Vim :help from from Doxygen XML.
-
- Returns 2 items:
- 1. Vim help text for functions found in `filename`.
- 2. Vim help text for deprecated functions.
- """
- config: Config = CONFIG[target]
-
- fns_txt = {} # Map of func_name:vim-help-text.
- deprecated_fns_txt = {} # Map of func_name:vim-help-text.
-
- fns: Dict[FunctionName, FunctionDoc]
- deprecated_fns: Dict[FunctionName, FunctionDoc]
- fns, deprecated_fns = extract_from_xml(
- filename, target, width=text_width, fmt_vimhelp=True)
-
- def _handle_fn(fn_name: FunctionName, fn: FunctionDoc,
- fns_txt: Dict[FunctionName, Docstring], deprecated=False):
- # Generate Vim :help for parameters.
-
- # Generate body from FunctionDoc, not XML nodes
- doc = fn.render()
- if not doc and fn_name.startswith("nvim__"):
- return
- if not doc:
- doc = ('TODO: Documentation' if not deprecated
- else 'Deprecated.')
-
- # Annotations: put before Parameters
- annotations: str = '\n'.join(fn.annotations)
- if annotations:
- annotations = ('\n\nAttributes: ~\n' +
- textwrap.indent(annotations, ' '))
- i = doc.rfind('Parameters: ~')
- if i == -1:
- doc += annotations
- else:
- doc = doc[:i] + annotations + '\n\n' + doc[i:]
-
- # C Declaration: (debug only)
- if INCLUDE_C_DECL:
- doc += '\n\nC Declaration: ~\n>\n'
- assert fn.c_decl is not None
- doc += fn.c_decl
- doc += '\n<'
-
- # Start of function documentations. e.g.,
- # nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
- func_doc = fn.signature + '\n'
- func_doc += textwrap.indent(clean_lines(doc), ' ' * indentation)
-
- # Verbatim handling.
- func_doc = re.sub(r'^\s+([<>])$', r'\1', func_doc, flags=re.M)
-
- def process_helptags(func_doc: str) -> str:
- lines: List[str] = func_doc.split('\n')
- # skip ">lang ... <" regions
- is_verbatim: bool = False
- for i in range(len(lines)):
- if re.search(' >([a-z])*$', lines[i]):
- is_verbatim = True
- elif is_verbatim and lines[i].strip() == '<':
- is_verbatim = False
- if not is_verbatim:
- lines[i] = align_tags(lines[i])
- return "\n".join(lines)
-
- func_doc = process_helptags(func_doc)
-
- if (fn_name.startswith(config.fn_name_prefix)
- and fn_name != "nvim_error_event"):
- fns_txt[fn_name] = func_doc
-
- for fn_name, fn in fns.items():
- _handle_fn(fn_name, fn, fns_txt)
- for fn_name, fn in deprecated_fns.items():
- _handle_fn(fn_name, fn, deprecated_fns_txt, deprecated=True)
-
- return (
- '\n\n'.join(list(fns_txt.values())),
- '\n\n'.join(list(deprecated_fns_txt.values())),
- )
-
-
-def delete_lines_below(filename, tokenstr):
- """Deletes all lines below the line containing `tokenstr`, the line itself,
- and one line above it.
- """
- lines = open(filename).readlines()
- i = 0
- found = False
- for i, line in enumerate(lines, 1):
- if tokenstr in line:
- found = True
- break
- if not found:
- raise RuntimeError(f'not found: "{tokenstr}"')
- i = max(0, i - 2)
- with open(filename, 'wt') as fp:
- fp.writelines(lines[0:i])
-
-
-def extract_defgroups(base: str, dom: Document) -> Dict[SectionName, Docstring]:
- '''Generate module-level (section) docs (@defgroup).'''
- section_docs = {}
-
- for compound in dom.getElementsByTagName('compound'):
- if compound.getAttribute('kind') != 'group':
- continue
-
- # Doxygen "@defgroup" directive.
- groupname = get_text(find_first(compound, 'name'))
- groupxml = os.path.join(base, '%s.xml' %
- compound.getAttribute('refid'))
-
- group_parsed = minidom.parse(groupxml)
- doc_list = []
- brief_desc = find_first(group_parsed, 'briefdescription')
- if brief_desc:
- for child in brief_desc.childNodes:
- doc_list.append(fmt_node_as_vimhelp(child))
-
- desc = find_first(group_parsed, 'detaileddescription')
- if desc:
- doc = fmt_node_as_vimhelp(desc)
-
- if doc:
- doc_list.append(doc)
-
- # Can't use '.' in @defgroup, so convert to '--'
- # "vim.json" => "vim-dot-json"
- groupname = groupname.replace('-dot-', '.')
-
- section_docs[groupname] = "\n".join(doc_list)
-
- return section_docs
-
-
-@dataclasses.dataclass
-class Section:
- """Represents a section. Includes section heading (defgroup)
- and all the FunctionDoc that belongs to this section."""
-
- name: str
- '''Name of the section. Usually derived from basename of lua/c src file.
- Example: "Autocmd".'''
-
- title: str
- '''Formatted section config. see config.section_fmt().
- Example: "Autocmd Functions". '''
-
- helptag: str
- '''see config.helptag_fmt(). Example: *api-autocmd*'''
-
- @property
- def id(self) -> str:
- '''section id: Module/Section id matched against @defgroup.
- e.g., "*api-autocmd*" => "api-autocmd"
- '''
- return self.helptag.strip('*')
-
- doc: str = ""
- '''Section heading docs extracted from @defgroup.'''
-
- # TODO: Do not carry rendered text, but handle FunctionDoc for better OOP
- functions_text: Docstring | None = None
- '''(Rendered) doc of all the functions that belong to this section.'''
-
- deprecated_functions_text: Docstring | None = None
- '''(Rendered) doc of all the deprecated functions that belong to this
- section.'''
-
- def __repr__(self):
- return f"Section(title='{self.title}', helptag='{self.helptag}')"
-
- @classmethod
- def make_from(cls, filename: str, config: Config,
- section_docs: Dict[SectionName, str],
- *,
- functions_text: Docstring,
- deprecated_functions_text: Docstring,
- ):
- # filename: e.g., 'autocmd.c'
- # name: e.g. 'autocmd'
- name = os.path.splitext(filename)[0].lower()
-
- # section name: e.g. "Autocmd"
- sectname: SectionName
- sectname = name.upper() if name == 'ui' else name.title()
- sectname = config.section_name.get(filename, sectname)
-
- # Formatted (this is what's going to be written in the vimdoc)
- # e.g., "Autocmd Functions"
- title: str = config.section_fmt(sectname)
-
- # section tag: e.g., "*api-autocmd*"
- section_tag: str = config.helptag_fmt(sectname)
-
- section = cls(name=sectname, title=title, helptag=section_tag,
- functions_text=functions_text,
- deprecated_functions_text=deprecated_functions_text,
- )
- section.doc = section_docs.get(section.id) or ''
- return section
-
- def render(self, add_header=True) -> str:
- """Render as vimdoc."""
- doc = ''
-
- if add_header:
- doc += SECTION_SEP
- doc += '\n{}{}'.format(
- self.title,
- self.helptag.rjust(text_width - len(self.title))
- )
-
- if self.doc:
- doc += '\n\n' + self.doc
-
- if self.functions_text:
- doc += '\n\n' + self.functions_text
-
- if INCLUDE_DEPRECATED and self.deprecated_functions_text:
- doc += f'\n\n\nDeprecated {self.name} Functions: ~\n\n'
- doc += self.deprecated_functions_text
-
- return doc
-
- def __bool__(self) -> bool:
- """Whether this section has contents. Used for skipping empty ones."""
- return bool(self.doc or self.functions_text or
- (INCLUDE_DEPRECATED and self.deprecated_functions_text))
-
-
-def main(doxygen_config, args):
- """Generates:
-
- 1. Vim :help docs
- 2. *.mpack files for use by API clients
-
- Doxygen is called and configured through stdin.
- """
- for target in CONFIG:
- if args.target is not None and target != args.target:
- continue
-
- config: Config = CONFIG[target]
-
- mpack_file = os.path.join(
- base_dir, 'runtime', 'doc',
- config.filename.replace('.txt', '.mpack'))
- if os.path.exists(mpack_file):
- os.remove(mpack_file)
-
- output_dir = out_dir.format(target=target)
- log.info("Generating documentation for %s in folder %s",
- target, output_dir)
- debug = args.log_level >= logging.DEBUG
- p = subprocess.Popen(
- ['doxygen', '-'],
- stdin=subprocess.PIPE,
- # silence warnings
- # runtime/lua/vim/lsp.lua:209: warning: argument 'foo' not found
- stderr=(subprocess.STDOUT if debug else subprocess.DEVNULL))
- p.communicate(
- doxygen_config.format(
- input=' '.join([f'"{file}"' for file in config.files]),
- output=output_dir,
- filter=filter_cmd,
- file_patterns=config.file_patterns)
- .encode('utf8')
- )
- if p.returncode:
- sys.exit(p.returncode)
-
- # Collects all functions as each module is processed.
- fn_map_full: Dict[FunctionName, FunctionDoc] = {}
- # key: filename (e.g. autocmd.c)
- sections: Dict[str, Section] = {}
-
- base = os.path.join(output_dir, 'xml')
- dom = minidom.parse(os.path.join(base, 'index.xml'))
-
- # Collect all @defgroups (section headings after the '===...' separator
- section_docs: Dict[SectionName, Docstring] = extract_defgroups(base, dom)
-
- # Generate docs for all functions in the current module.
- for compound in dom.getElementsByTagName('compound'):
- if compound.getAttribute('kind') != 'file':
- continue
-
- filename = get_text(find_first(compound, 'name'))
- if not (
- filename.endswith('.c') or
- filename.endswith('.lua')
- ):
- continue
-
- xmlfile = os.path.join(base, '{}.xml'.format(compound.getAttribute('refid')))
-
- # Extract unformatted (*.mpack).
- fn_map, _ = extract_from_xml(
- xmlfile, target, width=9999, fmt_vimhelp=False)
-
- # Extract formatted (:help).
- functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp(
- xmlfile, target)
-
- if not functions_text and not deprecated_text:
- continue
-
- filename = os.path.basename(filename)
-
- section: Section = Section.make_from(
- filename, config, section_docs,
- functions_text=functions_text,
- deprecated_functions_text=deprecated_text,
- )
-
- if section: # if not empty
- sections[filename] = section
- fn_map_full.update(fn_map)
- else:
- log.debug("Skipping empty section: %s", section)
-
- if len(sections) == 0:
- fail(f'no sections for target: {target} (look for errors near "Preprocessing" log lines above)')
- if len(sections) > len(config.section_order):
- raise RuntimeError(
- '{}: found new modules {}; '
- 'update the "section_order" map'.format(
- target,
- set(sections).difference(config.section_order))
- )
- first_section_tag = sections[config.section_order[0]].helptag
-
- docs = ''
-
- for filename in config.section_order:
- try:
- section: Section = sections.pop(filename)
- except KeyError:
- msg(f'warning: empty docs, skipping (target={target}): {filename}')
- msg(f' existing docs: {sections.keys()}')
- continue
-
- add_sep_and_header = filename not in config.append_only
- docs += section.render(add_header=add_sep_and_header)
- docs += '\n\n\n'
-
- docs = docs.rstrip() + '\n\n'
- docs += f' vim:tw=78:ts=8:sw={indentation}:sts={indentation}:et:ft=help:norl:\n'
-
- doc_file = os.path.join(base_dir, 'runtime', 'doc', config.filename)
-
- if os.path.exists(doc_file):
- delete_lines_below(doc_file, first_section_tag)
- with open(doc_file, 'ab') as fp:
- fp.write(docs.encode('utf8'))
-
- fn_map_full_exported = collections.OrderedDict(sorted(
- (name, fn_doc.export_mpack()) for (name, fn_doc) in fn_map_full.items()
- ))
- with open(mpack_file, 'wb') as fp:
- fp.write(msgpack.packb(fn_map_full_exported, use_bin_type=True)) # type: ignore
-
- if not args.keep_tmpfiles:
- shutil.rmtree(output_dir)
-
- msg_report()
-
-
-def filter_source(filename, keep_tmpfiles):
- output_dir = out_dir.format(target='lua2dox')
- name, extension = os.path.splitext(filename)
- if extension == '.lua':
- args = [str(nvim), '-l', lua2dox, filename] + (['--outdir', output_dir] if keep_tmpfiles else [])
- p = subprocess.run(args, stdout=subprocess.PIPE)
- op = ('?' if 0 != p.returncode else p.stdout.decode('utf-8'))
- print(op)
- else:
- """Filters the source to fix macros that confuse Doxygen."""
- with open(filename, 'rt') as fp:
- print(re.sub(r'^(ArrayOf|DictionaryOf|Dict)(\(.*?\))',
- lambda m: m.group(1)+'_'.join(
- re.split(r'[^\w]+', m.group(2))),
- fp.read(), flags=re.M))
-
-
-def parse_args():
- targets = ', '.join(CONFIG.keys())
- ap = argparse.ArgumentParser(
- description="Generate helpdoc from source code")
- ap.add_argument(
- "--log-level", "-l", choices=LOG_LEVELS.keys(),
- default=logging.getLevelName(logging.ERROR), help="Set log verbosity"
- )
- ap.add_argument('source_filter', nargs='*',
- help="Filter source file(s)")
- ap.add_argument('-k', '--keep-tmpfiles', action='store_true',
- help="Keep temporary files (tmp-xx-doc/ directories, including tmp-lua2dox-doc/ for lua2dox.lua quasi-C output)")
- ap.add_argument('-t', '--target',
- help=f'One of ({targets}), defaults to "all"')
- return ap.parse_args()
-
-
-Doxyfile = textwrap.dedent('''
- OUTPUT_DIRECTORY = {output}
- INPUT = {input}
- INPUT_ENCODING = UTF-8
- FILE_PATTERNS = {file_patterns}
- RECURSIVE = YES
- INPUT_FILTER = "{filter}"
- EXCLUDE =
- EXCLUDE_SYMLINKS = NO
- EXCLUDE_PATTERNS = */private/* */health.lua */_*.lua
- EXCLUDE_SYMBOLS =
- EXTENSION_MAPPING = lua=C
- EXTRACT_PRIVATE = NO
-
- GENERATE_HTML = NO
- GENERATE_DOCSET = NO
- GENERATE_HTMLHELP = NO
- GENERATE_QHP = NO
- GENERATE_TREEVIEW = NO
- GENERATE_LATEX = NO
- GENERATE_RTF = NO
- GENERATE_MAN = NO
- GENERATE_DOCBOOK = NO
- GENERATE_AUTOGEN_DEF = NO
-
- GENERATE_XML = YES
- XML_OUTPUT = xml
- XML_PROGRAMLISTING = NO
-
- ENABLE_PREPROCESSING = YES
- MACRO_EXPANSION = YES
- EXPAND_ONLY_PREDEF = NO
- MARKDOWN_SUPPORT = YES
-''')
-
-if __name__ == "__main__":
- args = parse_args()
- print("Setting log level to %s" % args.log_level)
- args.log_level = LOG_LEVELS[args.log_level]
- log.setLevel(args.log_level)
- log.addHandler(logging.StreamHandler())
-
- # When invoked as a filter, args won't be passed, so use an env var.
- if args.keep_tmpfiles:
- os.environ['NVIM_KEEP_TMPFILES'] = '1'
- keep_tmpfiles = ('NVIM_KEEP_TMPFILES' in os.environ)
-
- if len(args.source_filter) > 0:
- filter_source(args.source_filter[0], keep_tmpfiles)
- else:
- main(Doxyfile, args)
-
-# vim: set ft=python ts=4 sw=4 tw=79 et :
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
deleted file mode 100644
index 0b3daa59b2..0000000000
--- a/scripts/lua2dox.lua
+++ /dev/null
@@ -1,544 +0,0 @@
------------------------------------------------------------------------------
--- Copyright (C) 2012 by Simon Dales --
--- simon@purrsoft.co.uk --
--- --
--- This program is free software; you can redistribute it and/or modify --
--- it under the terms of the GNU General Public License as published by --
--- the Free Software Foundation; either version 2 of the License, or --
--- (at your option) any later version. --
--- --
--- This program is distributed in the hope that it will be useful, --
--- but WITHOUT ANY WARRANTY; without even the implied warranty of --
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
--- GNU General Public License for more details. --
--- --
--- You should have received a copy of the GNU General Public License --
--- along with this program; if not, write to the --
--- Free Software Foundation, Inc., --
--- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
------------------------------------------------------------------------------
-
---[[!
-Lua-to-Doxygen converter
-
-Partially from lua2dox
-http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm
-
-RUNNING
--------
-
-This script "lua2dox.lua" gets called by "gen_vimdoc.py".
-
-DEBUGGING/DEVELOPING
----------------------
-
-1. To debug, run gen_vimdoc.py with --keep-tmpfiles:
- python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles
-2. The filtered result will be written to ./tmp-lua2dox-doc/….lua.c
-
-Doxygen must be on your system. You can experiment like so:
-
-- Run "doxygen -g" to create a default Doxyfile.
-- Then alter it to let it recognise lua. Add the following line:
- FILE_PATTERNS = *.lua
-- Then run "doxygen".
-
-The core function reads the input file (filename or stdin) and outputs some pseudo C-ish language.
-It only has to be good enough for doxygen to see it as legal.
-
-One limitation is that each line is treated separately (except for long comments).
-The implication is that class and function declarations must be on the same line.
-
-There is hack that will insert the "missing" close paren.
-The effect is that you will get the function documented, but not with the parameter list you might expect.
-]]
-
-local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' }
-
-local luacats_parser = require('src/nvim/generators/luacats_grammar')
-
-local debug_outfile = nil --- @type string?
-local debug_output = {}
-
---- write to stdout
---- @param str? string
-local function write(str)
- if not str then
- return
- end
-
- io.write(str)
- if debug_outfile then
- table.insert(debug_output, str)
- end
-end
-
---- write to stdout
---- @param str? string
-local function writeln(str)
- write(str)
- write('\n')
-end
-
---- an input file buffer
---- @class StreamRead
---- @field currentLine string?
---- @field contentsLen integer
---- @field currentLineNo integer
---- @field filecontents string[]
-local StreamRead = {}
-
---- @return StreamRead
---- @param filename string
-function StreamRead.new(filename)
- assert(filename, ('invalid file: %s'):format(filename))
- -- get lines from file
- -- syphon lines to our table
- local filecontents = {} --- @type string[]
- for line in io.lines(filename) do
- filecontents[#filecontents + 1] = line
- end
-
- return setmetatable({
- filecontents = filecontents,
- contentsLen = #filecontents,
- currentLineNo = 1,
- }, { __index = StreamRead })
-end
-
--- get a line
-function StreamRead:getLine()
- if self.currentLine then
- self.currentLine = nil
- return self.currentLine
- end
-
- -- get line
- if self.currentLineNo <= self.contentsLen then
- local line = self.filecontents[self.currentLineNo]
- self.currentLineNo = self.currentLineNo + 1
- return line
- end
-
- return ''
-end
-
--- save line fragment
---- @param line_fragment string
-function StreamRead:ungetLine(line_fragment)
- self.currentLine = line_fragment
-end
-
--- is it eof?
-function StreamRead:eof()
- return not self.currentLine and self.currentLineNo > self.contentsLen
-end
-
--- input filter
---- @class Lua2DoxFilter
-local Lua2DoxFilter = {
- generics = {}, --- @type table<string,string>
- block_ignore = false, --- @type boolean
-}
-setmetatable(Lua2DoxFilter, { __index = Lua2DoxFilter })
-
-function Lua2DoxFilter:reset()
- self.generics = {}
- self.block_ignore = false
-end
-
---- trim comment off end of string
----
---- @param line string
---- @return string, string?
-local function removeCommentFromLine(line)
- local pos_comment = line:find('%-%-')
- if not pos_comment then
- return line
- end
- return line:sub(1, pos_comment - 1), line:sub(pos_comment)
-end
-
---- @param parsed luacats.Return
---- @return string
-local function get_return_type(parsed)
- local elems = {} --- @type string[]
- for _, v in ipairs(parsed) do
- local e = v.type --- @type string
- if v.name then
- e = e .. ' ' .. v.name --- @type string
- end
- elems[#elems + 1] = e
- end
- return '(' .. table.concat(elems, ', ') .. ')'
-end
-
---- @param name string
---- @return string
-local function process_name(name, optional)
- if optional then
- name = name:sub(1, -2) --- @type string
- end
- return name
-end
-
---- @param ty string
---- @param generics table<string,string>
---- @return string
-local function process_type(ty, generics, optional)
- -- replace generic types
- for k, v in pairs(generics) do
- ty = ty:gsub(k, v) --- @type string
- end
-
- -- strip parens
- ty = ty:gsub('^%((.*)%)$', '%1')
-
- if optional and not ty:find('nil') then
- ty = ty .. '?'
- end
-
- -- remove whitespace in unions
- ty = ty:gsub('%s*|%s*', '|')
-
- -- replace '|nil' with '?'
- ty = ty:gsub('|nil', '?')
- ty = ty:gsub('nil|(.*)', '%1?')
-
- return '(`' .. ty .. '`)'
-end
-
---- @param parsed luacats.Param
---- @param generics table<string,string>
---- @return string
-local function process_param(parsed, generics)
- local name, ty = parsed.name, parsed.type
- local optional = vim.endswith(name, '?')
-
- return table.concat({
- '/// @param',
- process_name(name, optional),
- process_type(ty, generics, optional),
- parsed.desc,
- }, ' ')
-end
-
---- @param parsed luacats.Return
---- @param generics table<string,string>
---- @return string
-local function process_return(parsed, generics)
- local ty, name --- @type string, string
- if #parsed == 1 then
- ty, name = parsed[1].type, parsed[1].name or ''
- else
- ty, name = get_return_type(parsed), ''
- end
-
- local optional = vim.endswith(name, '?')
-
- return table.concat({
- '/// @return',
- process_type(ty, generics, optional),
- process_name(name, optional),
- parsed.desc,
- }, ' ')
-end
-
---- Processes "@…" directives in a docstring line.
----
---- @param line string
---- @return string?
-function Lua2DoxFilter:process_magic(line)
- line = line:gsub('^%s+@', '@')
- line = line:gsub('@package', '@private')
- line = line:gsub('@nodoc', '@private')
-
- if self.block_ignore then
- return '// gg:" ' .. line .. '"'
- end
-
- if not vim.startswith(line, '@') then -- it's a magic comment
- return '/// ' .. line
- end
-
- local magic_split = vim.split(line, ' ', { plain = true })
- local directive = magic_split[1]
-
- if
- vim.list_contains({
- '@cast',
- '@diagnostic',
- '@overload',
- '@meta',
- '@type',
- }, directive)
- then
- -- Ignore LSP directives
- return '// gg:"' .. line .. '"'
- elseif directive == '@defgroup' or directive == '@addtogroup' then
- -- Can't use '.' in defgroup, so convert to '--'
- return '/// ' .. line:gsub('%.', '-dot-')
- end
-
- if directive == '@alias' then
- -- this contiguous block should be all ignored.
- self.block_ignore = true
- return '// gg:"' .. line .. '"'
- end
-
- -- preprocess line before parsing
- if directive == '@param' or directive == '@return' then
- for _, type in ipairs(TYPES) do
- line = line:gsub('^@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', '@param %1 %2')
- line = line:gsub('^@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', '@param %1 %2')
- line = line:gsub('^@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '%?)%)', '@param %1 %2')
-
- line = line:gsub('^@return%s+.*%((' .. type .. ')%)', '@return %1')
- line = line:gsub('^@return%s+.*%((' .. type .. '|nil)%)', '@return %1')
- line = line:gsub('^@return%s+.*%((' .. type .. '%?)%)', '@return %1')
- end
- end
-
- local parsed = luacats_parser:match(line)
-
- if not parsed then
- return '/// ' .. line
- end
-
- local kind = parsed.kind
-
- if kind == 'generic' then
- self.generics[parsed.name] = parsed.type or 'any'
- return
- elseif kind == 'param' then
- return process_param(parsed --[[@as luacats.Param]], self.generics)
- elseif kind == 'return' then
- return process_return(parsed --[[@as luacats.Return]], self.generics)
- end
-
- error(string.format('unhandled parsed line %q: %s', line, parsed))
-end
-
---- @param line string
---- @param in_stream StreamRead
---- @return string
-function Lua2DoxFilter:process_block_comment(line, in_stream)
- local comment_parts = {} --- @type string[]
- local done --- @type boolean?
-
- while not done and not in_stream:eof() do
- local thisComment --- @type string?
- local closeSquare = line:find(']]')
- if not closeSquare then -- need to look on another line
- thisComment = line .. '\n'
- line = in_stream:getLine()
- else
- thisComment = line:sub(1, closeSquare - 1)
- done = true
-
- -- unget the tail of the line
- -- in most cases it's empty. This may make us less efficient but
- -- easier to program
- in_stream:ungetLine(vim.trim(line:sub(closeSquare + 2)))
- end
- comment_parts[#comment_parts + 1] = thisComment
- end
-
- local comment = table.concat(comment_parts)
-
- if comment:sub(1, 1) == '@' then -- it's a long magic comment
- return '/*' .. comment .. '*/ '
- end
-
- -- discard
- return '/* zz:' .. comment .. '*/ '
-end
-
---- @param line string
---- @return string
-function Lua2DoxFilter:process_function_header(line)
- local pos_fn = assert(line:find('function'))
- -- we've got a function
- local fn = removeCommentFromLine(vim.trim(line:sub(pos_fn + 8)))
-
- if fn:sub(1, 1) == '(' then
- -- it's an anonymous function
- return '// ZZ: ' .. line
- end
- -- fn has a name, so is interesting
-
- -- want to fix for iffy declarations
- if fn:find('[%({]') then
- -- we might have a missing close paren
- if not fn:find('%)') then
- fn = fn .. ' ___MissingCloseParenHere___)'
- end
- end
-
- -- Big hax
- if fn:find(':') then
- fn = fn:gsub(':', '.', 1)
-
- local paren_start = fn:find('(', 1, true)
- local paren_finish = fn:find(')', 1, true)
-
- -- Nothing in between the parens
- local comma --- @type string
- if paren_finish == paren_start + 1 then
- comma = ''
- else
- comma = ', '
- end
-
- fn = fn:sub(1, paren_start) .. 'self' .. comma .. fn:sub(paren_start + 1)
- end
-
- if line:match('local') then
- -- Special: tell gen_vimdoc.py this is a local function.
- return 'local_function ' .. fn .. '{}'
- end
-
- -- add vanilla function
- return 'function ' .. fn .. '{}'
-end
-
---- @param line string
---- @param in_stream StreamRead
---- @return string?
-function Lua2DoxFilter:process_line(line, in_stream)
- local line_raw = line
- line = vim.trim(line)
-
- if vim.startswith(line, '---') then
- return Lua2DoxFilter:process_magic(line:sub(4))
- end
-
- if vim.startswith(line, '--' .. '[[') then -- it's a long comment
- return Lua2DoxFilter:process_block_comment(line:sub(5), in_stream)
- end
-
- -- Hax... I'm sorry
- -- M.fun = vim.memoize(function(...)
- -- ->
- -- function M.fun(...)
- line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)')
-
- if line:find('^function') or line:find('^local%s+function') then
- return Lua2DoxFilter:process_function_header(line)
- end
-
- if not line:match('^local') then
- local v = line_raw:match('^([A-Za-z][.a-zA-Z_]*)%s+%=')
- if v and v:match('%.') then
- -- Special: this lets gen_vimdoc.py handle tables.
- return 'table ' .. v .. '() {}'
- end
- end
-
- if #line > 0 then -- we don't know what this line means, so just comment it out
- return '// zz: ' .. line
- end
-
- return ''
-end
-
--- Processes the file and writes filtered output to stdout.
----@param filename string
-function Lua2DoxFilter:filter(filename)
- local in_stream = StreamRead.new(filename)
-
- local last_was_magic = false
-
- while not in_stream:eof() do
- local line = in_stream:getLine()
-
- local out_line = self:process_line(line, in_stream)
-
- if not vim.startswith(vim.trim(line), '---') then
- self:reset()
- end
-
- if out_line then
- -- Ensure all magic blocks associate with some object to prevent doxygen
- -- from getting confused.
- if vim.startswith(out_line, '///') then
- last_was_magic = true
- else
- if last_was_magic and out_line:match('^// zz: [^-]+') then
- writeln('local_function _ignore() {}')
- end
- last_was_magic = false
- end
- writeln(out_line)
- end
- end
-end
-
---- @class TApp
---- @field timestamp string|osdate
---- @field name string
---- @field version string
---- @field copyright string
---- this application
-local TApp = {
- timestamp = os.date('%c %Z', os.time()),
- name = 'Lua2DoX',
- version = '0.2 20130128',
- copyright = 'Copyright (c) Simon Dales 2012-13',
-}
-
-setmetatable(TApp, { __index = TApp })
-
-function TApp:getRunStamp()
- return self.name .. ' (' .. self.version .. ') ' .. self.timestamp
-end
-
-function TApp:getVersion()
- return self.name .. ' (' .. self.version .. ') '
-end
-
---main
-
-if arg[1] == '--help' then
- writeln(TApp:getVersion())
- writeln(TApp.copyright)
- writeln([[
- run as:
- nvim -l scripts/lua2dox.lua <param>
- --------------
- Param:
- <filename> : interprets filename
- --version : show version/copyright info
- --help : this help text]])
-elseif arg[1] == '--version' then
- writeln(TApp:getVersion())
- writeln(TApp.copyright)
-else -- It's a filter.
- local filename = arg[1]
-
- if arg[2] == '--outdir' then
- local outdir = arg[3]
- if
- type(outdir) ~= 'string'
- or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir))
- then
- error(('invalid --outdir: "%s"'):format(tostring(outdir)))
- end
- vim.fn.mkdir(outdir, 'p')
- debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename))
- end
-
- Lua2DoxFilter:filter(filename)
-
- -- output the tail
- writeln('// #######################')
- writeln('// app run:' .. TApp:getRunStamp())
- writeln('// #######################')
- writeln()
-
- if debug_outfile then
- local f = assert(io.open(debug_outfile, 'w'))
- f:write(table.concat(debug_output))
- f:close()
- end
-end
diff --git a/scripts/luacats_grammar.lua b/scripts/luacats_grammar.lua
new file mode 100644
index 0000000000..ee0f9d8e87
--- /dev/null
+++ b/scripts/luacats_grammar.lua
@@ -0,0 +1,218 @@
+--[[!
+LPEG grammar for LuaCATS
+]]
+
+local lpeg = vim.lpeg
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
+local Ct, Cg = lpeg.Ct, lpeg.Cg
+
+--- @param x vim.lpeg.Pattern
+local function rep(x)
+ return x ^ 0
+end
+
+--- @param x vim.lpeg.Pattern
+local function rep1(x)
+ return x ^ 1
+end
+
+--- @param x vim.lpeg.Pattern
+local function opt(x)
+ return x ^ -1
+end
+
+local nl = P('\r\n') + P('\n')
+local ws = rep1(S(' \t') + nl)
+local fill = opt(ws)
+
+local any = P(1) -- (consume one character)
+local letter = R('az', 'AZ') + S('_$')
+local num = R('09')
+local ident = letter * rep(letter + num + S '-.')
+local string_single = P "'" * rep(any - P "'") * P "'"
+local string_double = P '"' * rep(any - P '"') * P '"'
+
+local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true')
+
+local lname = (ident + P '...') * opt(P '?')
+
+--- @param x string
+local function Pf(x)
+ return fill * P(x) * fill
+end
+
+--- @param x string
+local function Sf(x)
+ return fill * S(x) * fill
+end
+
+--- @param x vim.lpeg.Pattern
+local function comma(x)
+ return x * rep(Pf ',' * x)
+end
+
+--- @param x vim.lpeg.Pattern
+local function parenOpt(x)
+ return (Pf('(') * x * fill * P(')')) + x
+end
+
+--- @type table<string,vim.lpeg.Pattern>
+local v = setmetatable({}, {
+ __index = function(_, k)
+ return lpeg.V(k)
+ end,
+})
+
+local desc_delim = Sf '#:' + ws
+
+--- @class nvim.luacats.Param
+--- @field kind 'param'
+--- @field name string
+--- @field type string
+--- @field desc? string
+
+--- @class nvim.luacats.Return
+--- @field kind 'return'
+--- @field [integer] { type: string, name?: string}
+--- @field desc? string
+
+--- @class nvim.luacats.Generic
+--- @field kind 'generic'
+--- @field name string
+--- @field type? string
+
+--- @class nvim.luacats.Class
+--- @field kind 'class'
+--- @field name string
+--- @field parent? string
+
+--- @class nvim.luacats.Field
+--- @field kind 'field'
+--- @field name string
+--- @field type string
+--- @field desc? string
+--- @field access? 'private'|'protected'|'package'
+
+--- @class nvim.luacats.Note
+--- @field desc? string
+
+--- @alias nvim.luacats.grammar.result
+--- | nvim.luacats.Param
+--- | nvim.luacats.Return
+--- | nvim.luacats.Generic
+--- | nvim.luacats.Class
+--- | nvim.luacats.Field
+--- | nvim.luacats.Note
+
+--- @class nvim.luacats.grammar
+--- @field match fun(self, input: string): nvim.luacats.grammar.result?
+
+local grammar = P {
+ rep1(P('@') * (v.ats + v.ext_ats)),
+
+ ats = v.at_param
+ + v.at_return
+ + v.at_type
+ + v.at_cast
+ + v.at_generic
+ + v.at_class
+ + v.at_field
+ + v.at_access
+ + v.at_deprecated
+ + v.at_alias
+ + v.at_enum
+ + v.at_see
+ + v.at_diagnostic
+ + v.at_overload
+ + v.at_meta,
+
+ ext_ats = v.ext_at_note + v.ext_at_since + v.ext_at_nodoc + v.ext_at_brief,
+
+ at_param = Ct(
+ Cg(P('param'), 'kind')
+ * ws
+ * Cg(lname, 'name')
+ * ws
+ * parenOpt(Cg(v.ltype, 'type'))
+ * opt(desc_delim * Cg(rep(any), 'desc'))
+ ),
+
+ at_return = Ct(
+ Cg(P('return'), 'kind')
+ * ws
+ * parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name')))))
+ * opt(desc_delim * Cg(rep(any), 'desc'))
+ ),
+
+ at_type = Ct(
+ Cg(P('type'), 'kind')
+ * ws
+ * parenOpt(comma(Ct(Cg(v.ltype, 'type'))))
+ * opt(desc_delim * Cg(rep(any), 'desc'))
+ ),
+
+ at_cast = Ct(
+ Cg(P('cast'), 'kind') * ws * Cg(lname, 'name') * ws * opt(Sf('+-')) * Cg(v.ltype, 'type')
+ ),
+
+ at_generic = Ct(
+ Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type'))
+ ),
+
+ at_class = Ct(
+ Cg(P('class'), 'kind')
+ * ws
+ * opt(P('(exact)') * ws)
+ * Cg(lname, 'name')
+ * opt(Pf(':') * Cg(lname, 'parent'))
+ ),
+
+ at_field = Ct(
+ Cg(P('field'), 'kind')
+ * ws
+ * opt(Cg(Pf('private') + Pf('package') + Pf('protected'), 'access'))
+ * Cg(lname, 'name')
+ * ws
+ * Cg(v.ltype, 'type')
+ * opt(desc_delim * Cg(rep(any), 'desc'))
+ ),
+
+ at_access = Ct(Cg(P('private') + P('protected') + P('package'), 'kind')),
+
+ at_deprecated = Ct(Cg(P('deprecated'), 'kind')),
+
+ -- Types may be provided on subsequent lines
+ at_alias = Ct(Cg(P('alias'), 'kind') * ws * Cg(lname, 'name') * opt(ws * Cg(v.ltype, 'type'))),
+
+ at_enum = Ct(Cg(P('enum'), 'kind') * ws * Cg(lname, 'name')),
+
+ at_see = Ct(Cg(P('see'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
+ at_diagnostic = Ct(Cg(P('diagnostic'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
+ at_overload = Ct(Cg(P('overload'), 'kind') * ws * Cg(v.ltype, 'type')),
+ at_meta = Ct(Cg(P('meta'), 'kind')),
+
+ --- Custom extensions
+ ext_at_note = Ct(Cg(P('note'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ -- TODO only consume 1 line
+ ext_at_since = Ct(Cg(P('since'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ ext_at_nodoc = Ct(Cg(P('nodoc'), 'kind')),
+ ext_at_brief = Ct(Cg(P('brief'), 'kind') * opt(ws * Cg(rep(any), 'desc'))),
+
+ ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')',
+
+ ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt),
+ ty = v.ty_fun + ident + v.ty_table + literal,
+ ty_param = Pf '<' * comma(v.ltype) * fill * P '>',
+ ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'),
+
+ table_key = (Pf '[' * literal * Pf ']') + lname,
+ table_elem = v.table_key * Pf ':' * v.ltype,
+ ty_table = Pf '{' * comma(v.table_elem) * Pf '}',
+
+ fun_param = lname * opt(Pf ':' * v.ltype),
+ ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * comma(v.ltype)),
+}
+
+return grammar --[[@as nvim.luacats.grammar]]
diff --git a/scripts/luacats_parser.lua b/scripts/luacats_parser.lua
new file mode 100644
index 0000000000..520272d1dc
--- /dev/null
+++ b/scripts/luacats_parser.lua
@@ -0,0 +1,521 @@
+local luacats_grammar = require('scripts.luacats_grammar')
+
+--- @class nvim.luacats.parser.param
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.luacats.parser.return
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.luacats.parser.note
+--- @field desc string
+
+--- @class nvim.luacats.parser.brief
+--- @field kind 'brief'
+--- @field desc string
+
+--- @class nvim.luacats.parser.alias
+--- @field kind 'alias'
+--- @field type string
+--- @field desc string
+
+--- @class nvim.luacats.parser.fun
+--- @field name string
+--- @field params nvim.luacats.parser.param[]
+--- @field returns nvim.luacats.parser.return[]
+--- @field desc string
+--- @field access? 'private'|'package'|'protected'
+--- @field class? string
+--- @field module? string
+--- @field modvar? string
+--- @field classvar? string
+--- @field deprecated? true
+--- @field since? string
+--- @field attrs? string[]
+--- @field nodoc? true
+--- @field generics? table<string,string>
+--- @field table? true
+--- @field notes? nvim.luacats.parser.note[]
+--- @field see? nvim.luacats.parser.note[]
+
+--- @class nvim.luacats.parser.field
+--- @field name string
+--- @field type string
+--- @field desc string
+--- @field access? 'private'|'package'|'protected'
+
+--- @class nvim.luacats.parser.class
+--- @field kind 'class'
+--- @field name string
+--- @field desc string
+--- @field fields nvim.luacats.parser.field[]
+--- @field notes? string[]
+
+--- @class nvim.luacats.parser.State
+--- @field doc_lines? string[]
+--- @field cur_obj? nvim.luacats.parser.obj
+--- @field last_doc_item? nvim.luacats.parser.param|nvim.luacats.parser.return|nvim.luacats.parser.note
+--- @field last_doc_item_indent? integer
+
+--- @alias nvim.luacats.parser.obj
+--- | nvim.luacats.parser.class
+--- | nvim.luacats.parser.fun
+--- | nvim.luacats.parser.brief
+
+-- Remove this when we document classes properly
+--- Some doc lines have the form:
+--- param name some.complex.type (table) description
+--- if so then transform the line to remove the complex type:
+--- param name (table) description
+--- @param line string
+local function use_type_alt(line)
+ for _, type in ipairs({ 'table', 'function' }) do
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', '@param %1 %2')
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', '@param %1 %2')
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '%?)%)', '@param %1 %2')
+
+ line = line:gsub('@return%s+.*%((' .. type .. ')%)', '@return %1')
+ line = line:gsub('@return%s+.*%((' .. type .. '|nil)%)', '@return %1')
+ line = line:gsub('@return%s+.*%((' .. type .. '%?)%)', '@return %1')
+ end
+ return line
+end
+
+--- If we collected any `---` lines. Add them to the existing (or new) object
+--- Used for function/class descriptions and multiline param descriptions.
+--- @param state nvim.luacats.parser.State
+local function add_doc_lines_to_obj(state)
+ if state.doc_lines then
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ local txt = table.concat(state.doc_lines, '\n')
+ if cur_obj.desc then
+ cur_obj.desc = cur_obj.desc .. '\n' .. txt
+ else
+ cur_obj.desc = txt
+ end
+ state.doc_lines = nil
+ end
+end
+
+--- @param line string
+--- @param state nvim.luacats.parser.State
+local function process_doc_line(line, state)
+ line = line:sub(4):gsub('^%s+@', '@')
+ line = use_type_alt(line)
+
+ local parsed = luacats_grammar:match(line)
+
+ if not parsed then
+ if line:match('^ ') then
+ line = line:sub(2)
+ end
+
+ if state.last_doc_item then
+ if not state.last_doc_item_indent then
+ state.last_doc_item_indent = #line:match('^%s*') + 1
+ end
+ state.last_doc_item.desc = (state.last_doc_item.desc or '')
+ .. '\n'
+ .. line:sub(state.last_doc_item_indent or 1)
+ else
+ state.doc_lines = state.doc_lines or {}
+ table.insert(state.doc_lines, line)
+ end
+ return
+ end
+
+ state.last_doc_item_indent = nil
+ state.last_doc_item = nil
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ local kind = parsed.kind
+
+ if kind == 'brief' then
+ state.cur_obj = {
+ kind = 'brief',
+ desc = parsed.desc,
+ }
+ elseif kind == 'class' then
+ --- @cast parsed nvim.luacats.Class
+ state.cur_obj = {
+ kind = 'class',
+ name = parsed.name,
+ parent = parsed.parent,
+ desc = '',
+ fields = {},
+ }
+ elseif kind == 'field' then
+ --- @cast parsed nvim.luacats.Field
+ if not parsed.access then
+ parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
+ if parsed.desc then
+ parsed.desc = vim.trim(parsed.desc)
+ end
+ table.insert(cur_obj.fields, parsed)
+ end
+ state.doc_lines = nil
+ elseif kind == 'param' then
+ state.last_doc_item_indent = nil
+ cur_obj.params = cur_obj.params or {}
+ if vim.endswith(parsed.name, '?') then
+ parsed.name = parsed.name:sub(1, -2)
+ parsed.type = parsed.type .. '?'
+ end
+ state.last_doc_item = {
+ name = parsed.name,
+ type = parsed.type,
+ desc = parsed.desc,
+ }
+ table.insert(cur_obj.params, state.last_doc_item)
+ elseif kind == 'return' then
+ cur_obj.returns = cur_obj.returns or {}
+ for _, t in ipairs(parsed) do
+ table.insert(cur_obj.returns, {
+ name = t.name,
+ type = t.type,
+ desc = parsed.desc,
+ })
+ end
+ state.last_doc_item_indent = nil
+ state.last_doc_item = cur_obj.returns[#cur_obj.returns]
+ elseif kind == 'private' then
+ cur_obj.access = 'private'
+ elseif kind == 'package' then
+ cur_obj.access = 'package'
+ elseif kind == 'protected' then
+ cur_obj.access = 'protected'
+ elseif kind == 'deprecated' then
+ cur_obj.deprecated = true
+ elseif kind == 'nodoc' then
+ cur_obj.nodoc = true
+ elseif kind == 'since' then
+ cur_obj.since = parsed.desc
+ elseif kind == 'see' then
+ cur_obj.see = cur_obj.see or {}
+ table.insert(cur_obj.see, { desc = parsed.desc })
+ elseif kind == 'note' then
+ state.last_doc_item_indent = nil
+ state.last_doc_item = {
+ desc = parsed.desc,
+ }
+ cur_obj.notes = cur_obj.notes or {}
+ table.insert(cur_obj.notes, state.last_doc_item)
+ elseif kind == 'type' then
+ cur_obj.desc = parsed.desc
+ parsed.desc = nil
+ parsed.kind = nil
+ cur_obj.type = parsed
+ elseif kind == 'alias' then
+ state.cur_obj = {
+ kind = 'alias',
+ desc = parsed.desc,
+ }
+ elseif kind == 'enum' then
+ -- TODO
+ state.doc_lines = nil
+ elseif
+ vim.tbl_contains({
+ 'diagnostic',
+ 'cast',
+ 'overload',
+ 'meta',
+ }, kind)
+ then
+ -- Ignore
+ return
+ elseif kind == 'generic' then
+ cur_obj.generics = cur_obj.generics or {}
+ cur_obj.generics[parsed.name] = parsed.type or 'any'
+ else
+ error('Unhandled' .. vim.inspect(parsed))
+ end
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @return nvim.luacats.parser.field
+local function fun2field(fun)
+ local parts = { 'fun(' }
+ for _, p in ipairs(fun.params or {}) do
+ parts[#parts + 1] = string.format('%s: %s', p.name, p.type)
+ end
+ parts[#parts + 1] = ')'
+ if fun.returns then
+ parts[#parts + 1] = ': '
+ local tys = {} --- @type string[]
+ for _, p in ipairs(fun.returns) do
+ tys[#tys + 1] = p.type
+ end
+ parts[#parts + 1] = table.concat(tys, ', ')
+ end
+
+ return {
+ name = fun.name,
+ type = table.concat(parts, ''),
+ access = fun.access,
+ desc = fun.desc,
+ }
+end
+
+--- Function to normalize known form for declaring functions and normalize into a more standard
+--- form.
+--- @param line string
+--- @return string
+local function filter_decl(line)
+ -- M.fun = vim._memoize(function(...)
+ -- ->
+ -- function M.fun(...)
+ line = line:gsub('^local (.+) = .*_memoize%([^,]+, function%((.*)%)$', 'local function %1(%2)')
+ line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)')
+ return line
+end
+
+--- @param line string
+--- @param state nvim.luacats.parser.State
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param classvars table<string,string>
+--- @param has_indent boolean
+local function process_lua_line(line, state, classes, classvars, has_indent)
+ line = filter_decl(line)
+
+ if state.cur_obj and state.cur_obj.kind == 'class' then
+ local nm = line:match('^local%s+([a-zA-Z0-9_]+)%s*=')
+ if nm then
+ classvars[nm] = state.cur_obj.name
+ end
+ return
+ end
+
+ do
+ local parent_tbl, sep, fun_or_meth_nm =
+ line:match('^function%s+([a-zA-Z0-9_]+)([.:])([a-zA-Z0-9_]+)%s*%(')
+ if parent_tbl then
+ -- Have a decl. Ensure cur_obj
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ -- Match `Class:foo` methods for defined classes
+ local class = classvars[parent_tbl]
+ if class then
+ --- @cast cur_obj nvim.luacats.parser.fun
+ cur_obj.name = fun_or_meth_nm
+ cur_obj.class = class
+ cur_obj.classvar = parent_tbl
+ -- Add self param to methods
+ if sep == ':' then
+ cur_obj.params = cur_obj.params or {}
+ table.insert(cur_obj.params, 1, {
+ name = 'self',
+ type = class,
+ })
+ end
+
+ -- Add method as the field to the class
+ table.insert(classes[class].fields, fun2field(cur_obj))
+ return
+ end
+
+ -- Match `M.foo`
+ if cur_obj and parent_tbl == cur_obj.modvar then
+ cur_obj.name = fun_or_meth_nm
+ return
+ end
+ end
+ end
+
+ do
+ -- Handle: `function A.B.C.foo(...)`
+ local fn_nm = line:match('^function%s+([.a-zA-Z0-9_]+)%s*%(')
+ if fn_nm then
+ state.cur_obj = state.cur_obj or {}
+ state.cur_obj.name = fn_nm
+ return
+ end
+ end
+
+ do
+ -- Handle: `M.foo = {...}` where `M` is the modvar
+ local parent_tbl, tbl_nm = line:match('([a-zA-Z_]+)%.([a-zA-Z0-9_]+)%s*=')
+ if state.cur_obj and parent_tbl and parent_tbl == state.cur_obj.modvar then
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ do
+ -- Handle: `foo = {...}`
+ local tbl_nm = line:match('^([a-zA-Z0-9_]+)%s*=')
+ if tbl_nm and not has_indent then
+ state.cur_obj = state.cur_obj or {}
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ do
+ -- Handle: `vim.foo = {...}`
+ local tbl_nm = line:match('^(vim%.[a-zA-Z0-9_]+)%s*=')
+ if state.cur_obj and tbl_nm and not has_indent then
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ if state.cur_obj then
+ if line:find('^%s*%-%- luacheck:') then
+ state.cur_obj = nil
+ elseif line:find('^%s*local%s+') then
+ state.cur_obj = nil
+ elseif line:find('^%s*return%s+') then
+ state.cur_obj = nil
+ elseif line:find('^%s*[a-zA-Z_.]+%(%s+') then
+ state.cur_obj = nil
+ end
+ end
+end
+
+--- Determine the table name used to export functions of a module
+--- Usually this is `M`.
+--- @param filename string
+--- @return string?
+local function determine_modvar(filename)
+ local modvar --- @type string?
+ for line in io.lines(filename) do
+ do
+ --- @type string?
+ local m = line:match('^return%s+([a-zA-Z_]+)')
+ if m then
+ modvar = m
+ end
+ end
+ do
+ --- @type string?
+ local m = line:match('^return%s+setmetatable%(([a-zA-Z_]+),')
+ if m then
+ modvar = m
+ end
+ end
+ end
+ return modvar
+end
+
+--- @param obj nvim.luacats.parser.obj
+--- @param funs nvim.luacats.parser.fun[]
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param briefs string[]
+--- @param uncommitted nvim.luacats.parser.obj[]
+local function commit_obj(obj, classes, funs, briefs, uncommitted)
+ local commit = false
+ if obj.kind == 'class' then
+ --- @cast obj nvim.luacats.parser.class
+ if not classes[obj.name] then
+ classes[obj.name] = obj
+ commit = true
+ end
+ elseif obj.kind == 'alias' then
+ -- Just pretend
+ commit = true
+ elseif obj.kind == 'brief' then
+ --- @cast obj nvim.luacats.parser.brief`
+ briefs[#briefs + 1] = obj.desc
+ commit = true
+ else
+ --- @cast obj nvim.luacats.parser.fun`
+ if obj.name then
+ funs[#funs + 1] = obj
+ commit = true
+ end
+ end
+ if not commit then
+ table.insert(uncommitted, obj)
+ end
+ return commit
+end
+
+--- @param filename string
+--- @param uncommitted nvim.luacats.parser.obj[]
+-- luacheck: no unused
+local function dump_uncommitted(filename, uncommitted)
+ local out_path = 'luacats-uncommited/' .. filename:gsub('/', '%%') .. '.txt'
+ if #uncommitted > 0 then
+ print(string.format('Could not commit %d objects in %s', #uncommitted, filename))
+ vim.fn.mkdir(assert(vim.fs.dirname(out_path)), 'p')
+ local f = assert(io.open(out_path, 'w'))
+ for i, x in ipairs(uncommitted) do
+ f:write(i)
+ f:write(': ')
+ f:write(vim.inspect(x))
+ f:write('\n')
+ end
+ f:close()
+ else
+ vim.fn.delete(out_path)
+ end
+end
+
+local M = {}
+
+--- @param filename string
+--- @return table<string,nvim.luacats.parser.class> classes
+--- @return nvim.luacats.parser.fun[] funs
+--- @return string[] briefs
+--- @return nvim.luacats.parser.obj[]
+function M.parse(filename)
+ local funs = {} --- @type nvim.luacats.parser.fun[]
+ local classes = {} --- @type table<string,nvim.luacats.parser.class>
+ local briefs = {} --- @type string[]
+
+ local mod_return = determine_modvar(filename)
+
+ --- @type string
+ local module = filename:match('.*/lua/([a-z_][a-z0-9_/]+)%.lua') or filename
+ module = module:gsub('/', '.')
+
+ local classvars = {} --- @type table<string,string>
+
+ local state = {} --- @type nvim.luacats.parser.State
+
+ -- Keep track of any partial objects we don't commit
+ local uncommitted = {} --- @type nvim.luacats.parser.obj[]
+
+ for line in io.lines(filename) do
+ local has_indent = line:match('^%s+') ~= nil
+ line = vim.trim(line)
+ if vim.startswith(line, '---') then
+ process_doc_line(line, state)
+ else
+ add_doc_lines_to_obj(state)
+
+ if state.cur_obj then
+ state.cur_obj.modvar = mod_return
+ state.cur_obj.module = module
+ end
+
+ process_lua_line(line, state, classes, classvars, has_indent)
+
+ -- Commit the object
+ local cur_obj = state.cur_obj
+ if cur_obj then
+ if not commit_obj(cur_obj, classes, funs, briefs, uncommitted) then
+ --- @diagnostic disable-next-line:inject-field
+ cur_obj.line = line
+ end
+ end
+
+ state = {}
+ end
+ end
+
+ -- dump_uncommitted(filename, uncommitted)
+
+ return classes, funs, briefs, uncommitted
+end
+
+return M
diff --git a/scripts/text_utils.lua b/scripts/text_utils.lua
new file mode 100644
index 0000000000..5167ec42f2
--- /dev/null
+++ b/scripts/text_utils.lua
@@ -0,0 +1,239 @@
+local fmt = string.format
+
+--- @class nvim.text_utils.MDNode
+--- @field [integer] nvim.text_utils.MDNode
+--- @field type string
+--- @field text? string
+
+local INDENTATION = 4
+
+local M = {}
+
+local function contains(t, xs)
+ return vim.tbl_contains(xs, t)
+end
+
+--- @param text string
+--- @return nvim.text_utils.MDNode
+local function parse_md(text)
+ local parser = vim.treesitter.languagetree.new(text, 'markdown', {
+ injections = { markdown = '' },
+ })
+
+ local root = parser:parse(true)[1]:root()
+
+ local EXCLUDE_TEXT_TYPE = {
+ list = true,
+ list_item = true,
+ section = true,
+ document = true,
+ fenced_code_block = true,
+ fenced_code_block_delimiter = true,
+ }
+
+ --- @param node TSNode
+ --- @return nvim.text_utils.MDNode?
+ local function extract(node)
+ local ntype = node:type()
+
+ if ntype:match('^%p$') or contains(ntype, { 'block_continuation' }) then
+ return
+ end
+
+ --- @type table<any,any>
+ local ret = { type = ntype }
+
+ if not EXCLUDE_TEXT_TYPE[ntype] then
+ ret.text = vim.treesitter.get_node_text(node, text)
+ end
+
+ for child, child_field in node:iter_children() do
+ local e = extract(child)
+ if child_field then
+ ret[child_field] = e
+ else
+ table.insert(ret, e)
+ end
+ end
+
+ return ret
+ end
+
+ return extract(root) or {}
+end
+
+--- @param x string
+--- @param start_indent integer
+--- @param indent integer
+--- @param text_width integer
+--- @return string
+function M.wrap(x, start_indent, indent, text_width)
+ local words = vim.split(vim.trim(x), '%s+')
+ local parts = { string.rep(' ', start_indent) } --- @type string[]
+ local count = indent
+
+ for i, w in ipairs(words) do
+ if count > indent and count + #w > text_width - 1 then
+ parts[#parts + 1] = '\n'
+ parts[#parts + 1] = string.rep(' ', indent)
+ count = indent
+ elseif i ~= 1 then
+ parts[#parts + 1] = ' '
+ count = count + 1
+ end
+ count = count + #w
+ parts[#parts + 1] = w
+ end
+
+ return (table.concat(parts):gsub('%s+\n', '\n'):gsub('\n+$', ''))
+end
+
+--- @param node nvim.text_utils.MDNode
+--- @param start_indent integer
+--- @param indent integer
+--- @param text_width integer
+--- @param level integer
+--- @return string[]
+local function render_md(node, start_indent, indent, text_width, level, is_list)
+ local parts = {} --- @type string[]
+
+ -- For debugging
+ local add_tag = false
+ -- local add_tag = true
+
+ if add_tag then
+ parts[#parts + 1] = '<' .. node.type .. '>'
+ end
+
+ if node.type == 'paragraph' then
+ local text = assert(node.text)
+ text = text:gsub('(%s)%*(%w+)%*(%s)', '%1%2%3')
+ text = text:gsub('(%s)_(%w+)_(%s)', '%1%2%3')
+ text = text:gsub('\\|', '|')
+ text = text:gsub('\\%*', '*')
+ text = text:gsub('\\_', '_')
+ parts[#parts + 1] = M.wrap(text, start_indent, indent, text_width)
+ parts[#parts + 1] = '\n'
+ elseif node.type == 'code_fence_content' then
+ local lines = vim.split(node.text:gsub('\n%s*$', ''), '\n')
+
+ local cindent = indent + INDENTATION
+ if level > 3 then
+ -- The tree-sitter markdown parser doesn't parse the code blocks indents
+ -- correctly in lists. Fudge it!
+ lines[1] = ' ' .. lines[1] -- ¯\_(ツ)_/¯
+ cindent = indent - level
+ local _, initial_indent = lines[1]:find('^%s*')
+ initial_indent = initial_indent + cindent
+ if initial_indent < indent then
+ cindent = indent - INDENTATION
+ end
+ end
+
+ for _, l in ipairs(lines) do
+ if #l > 0 then
+ parts[#parts + 1] = string.rep(' ', cindent)
+ parts[#parts + 1] = l
+ end
+ parts[#parts + 1] = '\n'
+ end
+ elseif node.type == 'fenced_code_block' then
+ parts[#parts + 1] = '>'
+ for _, child in ipairs(node) do
+ if child.type == 'info_string' then
+ parts[#parts + 1] = child.text
+ break
+ end
+ end
+ parts[#parts + 1] = '\n'
+ for _, child in ipairs(node) do
+ if child.type ~= 'info_string' then
+ vim.list_extend(parts, render_md(child, start_indent, indent, text_width, level + 1))
+ end
+ end
+ parts[#parts + 1] = '<\n'
+ elseif node.type == 'html_block' then
+ local text = node.text:gsub('^<pre>help', '')
+ text = text:gsub('</pre>%s*$', '')
+ parts[#parts + 1] = text
+ elseif node.type == 'list_marker_dot' then
+ parts[#parts + 1] = node.text
+ elseif contains(node.type, { 'list_marker_minus', 'list_marker_star' }) then
+ parts[#parts + 1] = '• '
+ elseif node.type == 'list_item' then
+ parts[#parts + 1] = string.rep(' ', indent)
+ local offset = node[1].type == 'list_marker_dot' and 3 or 2
+ for i, child in ipairs(node) do
+ local sindent = i <= 2 and 0 or (indent + offset)
+ vim.list_extend(
+ parts,
+ render_md(child, sindent, indent + offset, text_width, level + 1, true)
+ )
+ end
+ else
+ if node.text then
+ error(fmt('cannot render:\n%s', vim.inspect(node)))
+ end
+ for i, child in ipairs(node) do
+ vim.list_extend(parts, render_md(child, start_indent, indent, text_width, level + 1, is_list))
+ if node.type ~= 'list' and i ~= #node then
+ if (node[i + 1] or {}).type ~= 'list' then
+ parts[#parts + 1] = '\n'
+ end
+ end
+ end
+ end
+
+ if add_tag then
+ parts[#parts + 1] = '</' .. node.type .. '>'
+ end
+
+ return parts
+end
+
+--- @param text_width integer
+local function align_tags(text_width)
+ --- @param line string
+ --- @return string
+ return function(line)
+ local tag_pat = '%s+(%*[^ ]+%*)%s*$'
+ local tags = {}
+ for m in line:gmatch(tag_pat) do
+ table.insert(tags, m)
+ end
+
+ if #tags > 0 then
+ line = line:gsub(tag_pat, '')
+ local tags_str = ' ' .. table.concat(tags, ' ')
+ local pad = string.rep(' ', text_width - #line - #tags_str)
+ return line .. pad .. tags_str
+ end
+
+ return line
+ end
+end
+
+--- @param text string
+--- @param start_indent integer
+--- @param indent integer
+--- @param is_list? boolean
+--- @return string
+function M.md_to_vimdoc(text, start_indent, indent, text_width, is_list)
+ -- Add an extra newline so the parser can properly capture ending ```
+ local parsed = parse_md(text .. '\n')
+ local ret = render_md(parsed, start_indent, indent, text_width, 0, is_list)
+
+ local lines = vim.split(table.concat(ret), '\n')
+
+ lines = vim.tbl_map(align_tags(text_width), lines)
+
+ local s = table.concat(lines, '\n')
+
+ -- Reduce whitespace in code-blocks
+ s = s:gsub('\n+%s*>([a-z]+)\n?\n', ' >%1\n')
+ s = s:gsub('\n+%s*>\n?\n', ' >\n')
+
+ return s
+end
+
+return M
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 54ad43e8f3..5ec0e4d9ec 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -902,14 +902,6 @@ set(VIMDOC_FILES
${NVIM_RUNTIME_DIR}/doc/treesitter.txt
)
-set(MPACK_FILES
- ${NVIM_RUNTIME_DIR}/doc/api.mpack
- ${NVIM_RUNTIME_DIR}/doc/diagnostic.mpack
- ${NVIM_RUNTIME_DIR}/doc/lsp.mpack
- ${NVIM_RUNTIME_DIR}/doc/lua.mpack
- ${NVIM_RUNTIME_DIR}/doc/treesitter.mpack
-)
-
file(GLOB API_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/nvim/api/*.c)
file(GLOB LUA_SOURCES CONFIGURE_DEPENDS
@@ -921,25 +913,25 @@ file(GLOB LUA_SOURCES CONFIGURE_DEPENDS
)
add_custom_command(
- OUTPUT ${MPACK_FILES}
- COMMAND ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.py
+ OUTPUT ${VIMDOC_FILES}
+ COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
+ $<TARGET_FILE:nvim_bin> -l scripts/gen_vimdoc.lua
DEPENDS
- nvim_bin
+ nvim
${API_SOURCES}
${LUA_SOURCES}
- ${VIMDOC_FILES}
- ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.py
- ${PROJECT_SOURCE_DIR}/scripts/lua2dox.lua
+ ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.lua
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
add_custom_command(
OUTPUT ${GEN_EVAL_TOUCH}
COMMAND ${CMAKE_COMMAND} -E touch ${GEN_EVAL_TOUCH}
- COMMAND $<TARGET_FILE:nvim_bin> -l ${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
+ COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
+ $<TARGET_FILE:nvim_bin> -l ${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
DEPENDS
+ nvim
${API_METADATA}
- ${NVIM_RUNTIME_DIR}/doc/api.mpack
${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
${PROJECT_SOURCE_DIR}/src/nvim/eval.lua
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 7e33a77d24..06f21919f9 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -75,7 +75,7 @@ static int64_t next_autocmd_id = 1;
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern}
/// @return Array of autocommands matching the criteria, with each item
-/// containing the following fields:
+/// containing the following fields:
/// - id (number): the autocommand id (only when defined with the API).
/// - group (integer): the autocommand group id.
/// - group_name (string): the autocommand group name.
@@ -83,10 +83,10 @@ static int64_t next_autocmd_id = 1;
/// - event (string): the autocommand event.
/// - command (string): the autocommand command. Note: this will be empty if a callback is set.
/// - callback (function|string|nil): Lua function or name of a Vim script function
-/// which is executed when this autocommand is triggered.
+/// which is executed when this autocommand is triggered.
/// - once (boolean): whether the autocommand is only run once.
/// - pattern (string): the autocommand pattern.
-/// If the autocommand is buffer local |autocmd-buffer-local|:
+/// If the autocommand is buffer local |autocmd-buffer-local|:
/// - buflocal (boolean): true if the autocommand is buffer local.
/// - buffer (number): the buffer number.
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
@@ -536,9 +536,9 @@ void nvim_del_autocmd(Integer id, Error *err)
/// @param opts Parameters
/// - event: (string|table)
/// Examples:
-/// - event: "pat1"
-/// - event: { "pat1" }
-/// - event: { "pat1", "pat2", "pat3" }
+/// - event: "pat1"
+/// - event: { "pat1" }
+/// - event: { "pat1", "pat2", "pat3" }
/// - pattern: (string|table)
/// - pattern or patterns to match exactly.
/// - For example, if you have `*.py` as that pattern for the autocmd,
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 41a3743895..7f195de959 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -50,9 +50,8 @@
# include "api/buffer.c.generated.h"
#endif
-/// \defgroup api-buffer
-///
-/// \brief For more information on buffers, see |buffers|
+/// @brief <pre>help
+/// For more information on buffers, see |buffers|.
///
/// Unloaded Buffers: ~
///
@@ -64,6 +63,7 @@
///
/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
/// whether a buffer is loaded.
+/// </pre>
/// Returns the number of lines in the given buffer.
///
@@ -229,6 +229,7 @@ Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err)
return true;
}
+/// @nodoc
void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -875,8 +876,8 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// Gets a list of buffer-local |mapping| definitions.
///
-/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param buffer Buffer handle, or 0 for current buffer
+/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param[out] err Error details, if any
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle.
@@ -1223,6 +1224,7 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
return res;
}
+/// @nodoc
Dictionary nvim__buf_stats(Buffer buffer, Arena *arena, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index f2d5342a5f..e08035b0eb 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -67,7 +67,7 @@
/// - file: (boolean) The command expands filenames. Which means characters such as "%",
/// "#" and wildcards are expanded.
/// - bar: (boolean) The "|" character is treated as a command separator and the double
-/// quote character (\") is treated as the start of a comment.
+/// quote character (") is treated as the start of a comment.
/// - mods: (dictionary) |:command-modifiers|.
/// - filter: (dictionary) |:filter|.
/// - pattern: (string) Filter pattern. Empty string if there is no filter.
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 166b04adf0..6254e9fbd8 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -61,8 +61,7 @@ Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
/// Gets the buffer number
///
-/// @deprecated The buffer number now is equal to the object id,
-/// so there is no need to use this function.
+/// @deprecated The buffer number now is equal to the object id
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
@@ -100,8 +99,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
/// Set the virtual text (annotation) for a buffer line.
///
-/// @deprecated use nvim_buf_set_extmark to use full virtual text
-/// functionality.
+/// @deprecated use nvim_buf_set_extmark to use full virtual text functionality.
///
/// The text will be placed after the buffer text. Virtual text will never
/// cause reflow, rather virtual text will be truncated at the end of the screen
@@ -119,7 +117,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
/// virtual text, the allocated id is then returned.
///
/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace to use or 0 to create a namespace,
+/// @param src_id Namespace to use or 0 to create a namespace,
/// or -1 for a ungrouped annotation
/// @param line Line to annotate with virtual text (zero-indexed)
/// @param chunks A list of [text, hl_group] arrays, each representing a
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 653140a7ae..e35840915f 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -1205,6 +1205,7 @@ free_exit:
return virt_text;
}
+/// @nodoc
String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error *err)
FUNC_API_SINCE(7) FUNC_API_RET_ALLOC
{
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 7deadb8eb5..d9bc0ccc92 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -272,21 +272,21 @@ Dictionary nvim_get_all_options_info(Arena *arena, Error *err)
/// Gets the option information for one option from arbitrary buffer or window
///
/// Resulting dictionary has keys:
-/// - name: Name of the option (like 'filetype')
-/// - shortname: Shortened name of the option (like 'ft')
-/// - type: type of option ("string", "number" or "boolean")
-/// - default: The default value for the option
-/// - was_set: Whether the option was set.
+/// - name: Name of the option (like 'filetype')
+/// - shortname: Shortened name of the option (like 'ft')
+/// - type: type of option ("string", "number" or "boolean")
+/// - default: The default value for the option
+/// - was_set: Whether the option was set.
///
-/// - last_set_sid: Last set script id (if any)
-/// - last_set_linenr: line number where option was set
-/// - last_set_chan: Channel where option was set (0 for local)
+/// - last_set_sid: Last set script id (if any)
+/// - last_set_linenr: line number where option was set
+/// - last_set_chan: Channel where option was set (0 for local)
///
-/// - scope: one of "global", "win", or "buf"
-/// - global_local: whether win or buf option has a global value
+/// - scope: one of "global", "win", or "buf"
+/// - global_local: whether win or buf option has a global value
///
-/// - commalist: List of comma separated values
-/// - flaglist: List of single char flags
+/// - commalist: List of comma separated values
+/// - flaglist: List of single char flags
///
/// When {scope} is not provided, the last set information applies to the local
/// value in the current buffer or window if it is available, otherwise the
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index d5843caa96..0f016d2f29 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -165,7 +165,7 @@ void remote_ui_wait_for_attach(bool only_stdio)
/// Activates UI events on the channel.
///
-/// Entry point of all UI clients. Allows |\-\-embed| to continue startup.
+/// Entry point of all UI clients. Allows |--embed| to continue startup.
/// Implies that the client is ready to show the UI. Adds the client to the
/// list of UIs. |nvim_list_uis()|
///
@@ -541,7 +541,7 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
///
/// @param channel_id
/// @param event Event name
-/// @param payload Event payload
+/// @param value Event payload
/// @param[out] err Error details, if any.
void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err)
FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index b3d38cde69..54bf290e6b 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -123,7 +123,7 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
///
/// @note Unlike the `:highlight` command which can update a highlight group,
/// this function completely replaces the definition. For example:
-/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group
+/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group
/// 'Visual'.
///
/// @note The fg and bg keys also accept the string values `"fg"` or `"bg"`
@@ -549,6 +549,7 @@ ArrayOf(String) nvim_list_runtime_paths(Arena *arena, Error *err)
return nvim_get_runtime_file(NULL_STRING, true, arena, err);
}
+/// @nodoc
Array nvim__runtime_inspect(Arena *arena)
{
return runtime_inspect(arena);
@@ -600,6 +601,7 @@ static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *c)
return num_fnames > 0;
}
+/// @nodoc
String nvim__get_lib_dir(void)
FUNC_API_RET_ALLOC
{
@@ -1547,14 +1549,14 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// @param channel_id
/// @param name Short name for the connected client
/// @param version Dictionary describing the version, with these
-/// (optional) keys:
+/// (optional) keys:
/// - "major" major version (defaults to 0 if not set, for no release yet)
/// - "minor" minor version
/// - "patch" patch number
/// - "prerelease" string describing a prerelease, like "dev" or "beta1"
/// - "commit" hash or similar identifier of commit
/// @param type Must be one of the following values. Client libraries should
-/// default to "remote" unless overridden by the user.
+/// default to "remote" unless overridden by the user.
/// - "remote" remote client connected "Nvim flavored" MessagePack-RPC (responses
/// must be in reverse order of requests). |msgpack-rpc|
/// - "msgpack-rpc" remote client connected to Nvim via fully MessagePack-RPC
@@ -1565,12 +1567,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// - "host" plugin host, typically started by nvim
/// - "plugin" single plugin, started by nvim
/// @param methods Builtin methods in the client. For a host, this does not
-/// include plugin methods which will be discovered later.
-/// The key should be the method name, the values are dicts with
-/// these (optional) keys (more keys may be added in future
-/// versions of Nvim, thus unknown keys are ignored. Clients
-/// must only use keys defined in this or later versions of
-/// Nvim):
+/// include plugin methods which will be discovered later.
+/// The key should be the method name, the values are dicts with
+/// these (optional) keys (more keys may be added in future
+/// versions of Nvim, thus unknown keys are ignored. Clients
+/// must only use keys defined in this or later versions of
+/// Nvim):
/// - "async" if true, send as a notification. If false or unspecified,
/// use a blocking request
/// - "nargs" Number of arguments. Could be a single integer or an array
@@ -1979,7 +1981,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di
pum_ext_select_item((int)item, insert, finish);
}
-/// NB: if your UI doesn't use hlstate, this will not return hlstate first time
+/// NB: if your UI doesn't use hlstate, this will not return hlstate first time.
Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err)
{
Array ret = ARRAY_DICT_INIT;
@@ -2015,6 +2017,7 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E
return ret;
}
+/// @nodoc
void nvim__screenshot(String path)
FUNC_API_FAST
{
@@ -2029,6 +2032,7 @@ void nvim__invalidate_glyph_cache(void)
must_redraw = UPD_CLEAR;
}
+/// @nodoc
Object nvim__unpack(String str, Arena *arena, Error *err)
FUNC_API_FAST
{
@@ -2319,6 +2323,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena *
return result;
}
+/// @nodoc
void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
FUNC_API_REMOTE_ONLY
{
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 7239971c21..8f57e61c76 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -351,9 +351,7 @@ typedef struct {
Object *ret_node_p;
} ExprASTConvStackItem;
-/// @cond DOXYGEN_NOT_A_FUNCTION
typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
-/// @endcond
/// Parse a Vimscript expression.
///
@@ -387,8 +385,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "arg": String, error message argument.
/// - "len": Amount of bytes successfully parsed. With flags equal to ""
/// that should be equal to the length of expr string.
-/// (“Successfully parsed” here means “participated in AST
-/// creation”, not “till the first error”.)
+/// ("Successfully parsed" here means "participated in AST
+/// creation", not "till the first error".)
/// - "ast": AST, either nil or a dictionary with these keys:
/// - "type": node type, one of the value names from ExprASTNodeType
/// stringified without "kExprNode" prefix.
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index e76db82c61..3cc520dc78 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -116,12 +116,12 @@
/// - width: Window width (in character cells). Minimum of 1.
/// - height: Window height (in character cells). Minimum of 1.
/// - bufpos: Places float relative to buffer text (only when
-/// relative="win"). Takes a tuple of zero-indexed [line, column].
-/// `row` and `col` if given are applied relative to this
-/// position, else they default to:
-/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
-/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
-/// (thus like a tooltip near the buffer text).
+/// relative="win"). Takes a tuple of zero-indexed [line, column].
+/// `row` and `col` if given are applied relative to this
+/// position, else they default to:
+/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
+/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
+/// (thus like a tooltip near the buffer text).
/// - row: Row position in units of "screen cell height", may be fractional.
/// - col: Column position in units of "screen cell width", may be
/// fractional.
@@ -153,7 +153,7 @@
/// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: Style of (optional) window border. This can either be a string
-/// or an array. The string values are
+/// or an array. The string values are
/// - "none": No border (default).
/// - "single": A single line box.
/// - "double": A double line box.
@@ -161,21 +161,31 @@
/// - "solid": Adds padding by a single whitespace cell.
/// - "shadow": A drop shadow effect by blending with the background.
/// - If it is an array, it should have a length of eight or any divisor of
-/// eight. The array will specify the eight chars building up the border
-/// in a clockwise fashion starting with the top-left corner. As an
-/// example, the double box style could be specified as
+/// eight. The array will specify the eight chars building up the border
+/// in a clockwise fashion starting with the top-left corner. As an
+/// example, the double box style could be specified as:
+/// ```
/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
-/// If the number of chars are less than eight, they will be repeated. Thus
-/// an ASCII border could be specified as
+/// ```
+/// If the number of chars are less than eight, they will be repeated. Thus
+/// an ASCII border could be specified as
+/// ```
/// [ "/", "-", \"\\\\\", "|" ],
-/// or all chars the same as
+/// ```
+/// or all chars the same as
+/// ```
/// [ "x" ].
+/// ```
/// An empty string can be used to turn off a specific border, for instance,
+/// ```
/// [ "", "", "", ">", "", "", "", "<" ]
+/// ```
/// will only make vertical borders but not horizontal ones.
/// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
/// when not defined. It could also be specified by character:
+/// ```
/// [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+/// ```
/// - title: Title (optional) in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, the default highlight group is `FloatTitle`.
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index c41c5d4b07..ed51eedf1b 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -452,6 +452,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
///
/// This takes precedence over the 'winhighlight' option.
///
+/// @param window
/// @param ns_id the namespace to use
/// @param[out] err Error details, if any
void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err)
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index 8a3e70990a..9ce9f3d7a6 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -6,46 +6,74 @@ local lpeg = vim.lpeg
local P, R, S = lpeg.P, lpeg.R, lpeg.S
local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg
+--- @param pat vim.lpeg.Pattern
+local function rep(pat)
+ return pat ^ 0
+end
+
+--- @param pat vim.lpeg.Pattern
+local function rep1(pat)
+ return pat ^ 1
+end
+
+--- @param pat vim.lpeg.Pattern
+local function opt(pat)
+ return pat ^ -1
+end
+
local any = P(1) -- (consume one character)
local letter = R('az', 'AZ') + S('_$')
local num = R('09')
local alpha = letter + num
local nl = P('\r\n') + P('\n')
local not_nl = any - nl
-local ws = S(' \t') + nl
-local fill = ws ^ 0
-local c_comment = P('//') * (not_nl ^ 0)
-local c_preproc = P('#') * (not_nl ^ 0)
-local dllexport = P('DLLEXPORT') * (ws ^ 1)
-local typed_container = (P('ArrayOf(') + P('DictionaryOf(') + P('Dict('))
- * ((any - P(')')) ^ 1)
+local space = S(' \t')
+local ws = space + nl
+local fill = rep(ws)
+local c_comment = P('//') * rep(not_nl)
+local cdoc_comment = P('///') * opt(Ct(Cg(rep(space) * rep(not_nl), 'comment')))
+local c_preproc = P('#') * rep(not_nl)
+local dllexport = P('DLLEXPORT') * rep1(ws)
+
+local typed_container = (
+ (P('ArrayOf(') + P('DictionaryOf(') + P('Dict('))
+ * rep1(any - P(')'))
* P(')')
-local c_id = (typed_container + (letter * (alpha ^ 0)))
+)
+
+local c_id = (typed_container + (letter * rep(alpha)))
local c_void = P('void')
+
local c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error'))
+ ((P('Arena') * fill * P('*') * fill) * Cc('arena'))
+ ((P('lua_State') * fill * P('*') * fill) * Cc('lstate'))
- + C((P('const ') ^ -1) * c_id * (ws ^ 1) * P('*'))
- + (C(c_id) * (ws ^ 1))
+ + C(opt(P('const ')) * c_id * rep1(ws) * rep1(P('*')))
+ + (C(c_id) * rep1(ws))
)
+
local c_type = (C(c_void) * (ws ^ 1)) + c_param_type
local c_param = Ct(c_param_type * C(c_id))
local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0)
local c_params = Ct(c_void + c_param_list)
+
+local impl_line = (any - P('}')) * opt(rep(not_nl)) * nl
+
+local ignore_line = rep1(not_nl) * nl
+
+local empty_line = Ct(Cc('empty') * nl * nl)
+
local c_proto = Ct(
- (dllexport ^ -1)
+ Cc('proto')
+ * opt(dllexport)
+ * opt(Cg(P('static') * fill * Cc(true), 'static'))
* Cg(c_type, 'return_type')
* Cg(c_id, 'name')
* fill
- * P('(')
- * fill
- * Cg(c_params, 'parameters')
- * fill
- * P(')')
+ * (P('(') * fill * Cg(c_params, 'parameters') * fill * P(')'))
* Cg(Cc(false), 'fast')
- * (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1)
- * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), 'deprecated_since') ^ -1)
+ * (fill * Cg((P('FUNC_API_SINCE(') * C(rep1(num))) * P(')'), 'since') ^ -1)
+ * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(rep1(num))) * P(')'), 'deprecated_since') ^ -1)
* (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1)
* (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1)
* (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1)
@@ -60,7 +88,7 @@ local c_proto = Ct(
* (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1)
* (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1)
* fill
- * P(';')
+ * (P(';') + (P('{') * nl + (impl_line ^ 0) * P('}')))
)
local c_field = Ct(Cg(c_id, 'type') * ws * Cg(c_id, 'name') * fill * P(';') * fill)
@@ -83,5 +111,7 @@ local c_keyset = Ct(
* P(';')
)
-local grammar = Ct((c_proto + c_comment + c_preproc + ws + c_keyset) ^ 1)
+local grammar = Ct(
+ rep1(empty_line + c_proto + cdoc_comment + c_comment + c_preproc + ws + c_keyset + ignore_line)
+)
return { grammar = grammar, typed_container = typed_container }
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index c3fc5aa0a3..56331e4162 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -23,9 +23,7 @@ local function_names = {}
local c_grammar = require('generators.c_grammar')
-local function startswith(String, Start)
- return string.sub(String, 1, string.len(Start)) == Start
-end
+local startswith = vim.startswith
local function add_function(fn)
local public = startswith(fn.name, 'nvim_') or fn.deprecated_since
@@ -112,10 +110,12 @@ for i = 6, #arg do
local tmp = c_grammar.grammar:match(input:read('*all'))
for j = 1, #tmp do
local val = tmp[j]
- if val.keyset_name then
- add_keyset(val)
- else
- add_function(val)
+ if val[1] ~= 'empty' then
+ if val.keyset_name then
+ add_keyset(val)
+ else
+ add_function(val)
+ end
end
end
input:close()
diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua
index 89f8c654f4..697626b793 100644
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -93,6 +93,10 @@ local function call_ui_event_method(output, ev)
output:write('}\n\n')
end
+events = vim.tbl_filter(function(ev)
+ return ev[1] ~= 'empty'
+end, events)
+
for i = 1, #events do
local ev = events[i]
assert(ev.return_type == 'void')
diff --git a/src/nvim/generators/luacats_grammar.lua b/src/nvim/generators/luacats_grammar.lua
deleted file mode 100644
index dcccd028ce..0000000000
--- a/src/nvim/generators/luacats_grammar.lua
+++ /dev/null
@@ -1,136 +0,0 @@
---[[!
-LPEG grammar for LuaCATS
-
-Currently only partially supports:
-- @param
-- @return
-]]
-
-local lpeg = vim.lpeg
-local P, R, S = lpeg.P, lpeg.R, lpeg.S
-local Ct, Cg = lpeg.Ct, lpeg.Cg
-
---- @param x vim.lpeg.Pattern
-local function rep(x)
- return x ^ 0
-end
-
---- @param x vim.lpeg.Pattern
-local function rep1(x)
- return x ^ 1
-end
-
---- @param x vim.lpeg.Pattern
-local function opt(x)
- return x ^ -1
-end
-
-local nl = P('\r\n') + P('\n')
-local ws = rep1(S(' \t') + nl)
-local fill = opt(ws)
-
-local any = P(1) -- (consume one character)
-local letter = R('az', 'AZ') + S('_$')
-local num = R('09')
-local ident = letter * rep(letter + num + S '-.')
-local string_single = P "'" * rep(any - P "'") * P "'"
-local string_double = P '"' * rep(any - P '"') * P '"'
-
-local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true')
-
-local lname = (ident + P '...') * opt(P '?')
-
---- @param x string
-local function Pf(x)
- return fill * P(x) * fill
-end
-
---- @param x string
-local function Sf(x)
- return fill * S(x) * fill
-end
-
---- @param x vim.lpeg.Pattern
-local function comma(x)
- return x * rep(Pf ',' * x)
-end
-
---- @param x vim.lpeg.Pattern
-local function parenOpt(x)
- return (Pf('(') * x ^ -1 * fill * P(')')) + x ^ -1
-end
-
---- @type table<string,vim.lpeg.Pattern>
-local v = setmetatable({}, {
- __index = function(_, k)
- return lpeg.V(k)
- end,
-})
-
-local desc_delim = Sf '#:' + ws
-
---- @class luacats.Param
---- @field kind 'param'
---- @field name string
---- @field type string
---- @field desc? string
-
---- @class luacats.Return
---- @field kind 'return'
---- @field [integer] { type: string, name?: string}
---- @field desc? string
-
---- @class luacats.Generic
---- @field kind 'generic'
---- @field name string
---- @field type? string
-
---- @alias luacats.grammar.result
---- | luacats.Param
---- | luacats.Return
---- | luacats.Generic
-
---- @class luacats.grammar
---- @field match fun(self, input: string): luacats.grammar.result?
-
-local grammar = P {
- rep1(P('@') * v.ats),
-
- ats = (v.at_param + v.at_return + v.at_generic),
-
- at_param = Ct(
- Cg(P('param'), 'kind')
- * ws
- * Cg(lname, 'name')
- * ws
- * Cg(v.ltype, 'type')
- * opt(desc_delim * Cg(rep(any), 'desc'))
- ),
-
- at_return = Ct(
- Cg(P('return'), 'kind')
- * ws
- * parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name')))))
- * opt(desc_delim * Cg(rep(any), 'desc'))
- ),
-
- at_generic = Ct(
- Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type'))
- ),
-
- ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')',
-
- ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt),
- ty = v.ty_fun + ident + v.ty_table + literal,
- ty_param = Pf '<' * comma(v.ltype) * fill * P '>',
- ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'),
-
- table_key = (Pf '[' * literal * Pf ']') + lname,
- table_elem = v.table_key * Pf ':' * v.ltype,
- ty_table = Pf '{' * comma(v.table_elem) * Pf '}',
-
- fun_param = lname * opt(Pf ':' * v.ltype),
- ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * v.ltype),
-}
-
-return grammar --[[@as luacats.grammar]]
diff --git a/test/functional/luacats_grammar_spec.lua b/test/functional/script/luacats_grammar_spec.lua
index 5671848709..931fe42dd0 100644
--- a/test/functional/luacats_grammar_spec.lua
+++ b/test/functional/script/luacats_grammar_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
-local grammar = require('src/nvim/generators/luacats_grammar')
+local grammar = require('scripts/luacats_grammar')
describe('luacats grammar', function()
--- @param text string
@@ -85,7 +85,7 @@ describe('luacats grammar', function()
test('@param level (integer|string) desc', {
kind = 'param',
name = 'level',
- type = '(integer|string)',
+ type = 'integer|string',
desc = 'desc',
})
diff --git a/test/functional/script/text_utils_spec.lua b/test/functional/script/text_utils_spec.lua
new file mode 100644
index 0000000000..c429d306d5
--- /dev/null
+++ b/test/functional/script/text_utils_spec.lua
@@ -0,0 +1,39 @@
+local helpers = require('test.functional.helpers')(after_each)
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+
+local function md_to_vimdoc(text)
+ return exec_lua(
+ [[
+ local text_utils = require('scripts/text_utils')
+ return text_utils.md_to_vimdoc(table.concat(..., '\n'), 0, 0, 70)
+ ]],
+ text
+ )
+end
+
+local function test(act, exp)
+ eq(table.concat(exp, '\n'), md_to_vimdoc(act))
+end
+
+describe('md_to_vimdoc', function()
+ before_each(function()
+ helpers.clear()
+ end)
+
+ it('can render para after fenced code', function()
+ test({
+ '- Para1',
+ ' ```',
+ ' code',
+ ' ```',
+ ' Para2',
+ }, {
+ '• Para1 >',
+ ' code',
+ '<',
+ ' Para2',
+ '',
+ })
+ end)
+end)