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).
This commit is contained in:
Lewis Russell 2024-02-15 17:16:04 +00:00 committed by Lewis Russell
parent 7ad2e3c645
commit 9beb40a4db
71 changed files with 3701 additions and 3849 deletions

View File

@ -20,10 +20,6 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./.github/actions/setup - uses: ./.github/actions/setup
- name: Install dependencies
run: |
sudo apt-get install -y doxygen python3-msgpack
- name: Generate docs - name: Generate docs
run: | run: |
make doc make doc

View File

@ -272,11 +272,16 @@ make lintdoc
``` ```
If you need to modify or debug the documentation flow, these are the main files: If you need to modify or debug the documentation flow, these are the main files:
- `./scripts/gen_vimdoc.py`: - `./scripts/gen_vimdoc.lua`:
Main doc generator. Drives doxygen to generate xml files, and scrapes those Main doc generator. Parses C and Lua files to render vimdoc files.
xml files to render vimdoc files. - `./scripts/luacats_parser.lua`:
- `./scripts/lua2dox.lua`: Documentation parser for Lua files.
Used by `gen_vimdoc.py` to transform Lua files into a format compatible with doxygen. - `./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`: - `./scripts/gen_eval_files.lua`:
Generates documentation and Lua type files from metadata files: Generates documentation and Lua type files from metadata files:
``` ```

View File

@ -140,7 +140,6 @@
include-what-you-use # for scripts/check-includes.py include-what-you-use # for scripts/check-includes.py
jq # jq for scripts/vim-patch.sh -r jq # jq for scripts/vim-patch.sh -r
shellcheck # for `make shlint` shellcheck # for `make shlint`
doxygen # for script/gen_vimdoc.py
]; ];
nativeBuildInputs = with pkgs; nativeBuildInputs = with pkgs;

View File

@ -55,9 +55,3 @@
# DEPS_CMAKE_FLAGS += -DUSE_BUNDLED=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED=OFF
# .DEFAULT_GOAL := nvim # .DEFAULT_GOAL := nvim
#
# Run doxygen over the source code.
# Output will be in build/doxygen
#
# doxygen:
# doxygen src/Doxyfile

View File

@ -579,7 +579,7 @@ created for extmark changes.
============================================================================== ==============================================================================
Global Functions *api-global* 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 Find files in runtime directories
Attributes: ~ Attributes: ~
@ -700,7 +700,7 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()*
• {chan} id of the channel • {chan} id of the channel
• {data} data to write. 8-bit clean: can contain NUL bytes. • {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 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 window, then the window and buffer ids are returned for further
customization. If the text was not shown, an empty dict is returned. customization. If the text was not shown, an empty dict is returned.
@ -766,7 +766,7 @@ nvim_del_var({name}) *nvim_del_var()*
Parameters: ~ Parameters: ~
• {name} Variable name • {name} Variable name
nvim_echo({chunks}, {history}, {*opts}) *nvim_echo()* nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
Echo a message. Echo a message.
Parameters: ~ Parameters: ~
@ -797,7 +797,7 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
See also: ~ See also: ~
• nvim_err_write() • nvim_err_write()
nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* nvim_eval_statusline({str}, {opts}) *nvim_eval_statusline()*
Evaluates statusline string. Evaluates statusline string.
Attributes: ~ 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 Returns a 2-tuple (Array), where item 0 is the current channel id and item
1 is the |api-metadata| map (Dictionary). 1 is the |api-metadata| map (Dictionary).
Return: ~
2-tuple [{channel-id}, {api-metadata}]
Attributes: ~ Attributes: ~
|api-fast| |api-fast|
|RPC| only |RPC| only
Return: ~
2-tuple [{channel-id}, {api-metadata}]
nvim_get_chan_info({chan}) *nvim_get_chan_info()* nvim_get_chan_info({chan}) *nvim_get_chan_info()*
Gets information about a channel. Gets information about a channel.
@ -900,12 +900,10 @@ nvim_get_chan_info({chan}) *nvim_get_chan_info()*
• "stderr" stderr of this Nvim instance • "stderr" stderr of this Nvim instance
• "socket" TCP/IP socket or named pipe • "socket" TCP/IP socket or named pipe
• "job" Job with communication over its stdio. • "job" Job with communication over its stdio.
• "mode" How data received on the channel is interpreted. • "mode" How data received on the channel is interpreted.
• "bytes" Send and receive raw bytes. • "bytes" Send and receive raw bytes.
• "terminal" |terminal| instance interprets ASCII sequences. • "terminal" |terminal| instance interprets ASCII sequences.
• "rpc" |RPC| communication on the channel is active. • "rpc" |RPC| communication on the channel is active.
• "pty" (optional) Name of pseudoterminal. On a POSIX system this is a • "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 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). 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: ~ Return: ~
Map of color names and RGB values. 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. Gets a map of the current editor state.
Parameters: ~ Parameters: ~
@ -972,7 +970,7 @@ nvim_get_current_win() *nvim_get_current_win()*
Return: ~ Return: ~
Window handle 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. Gets all or specific highlight groups in a namespace.
Note: ~ 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. 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. Gets the active highlight namespace.
Parameters: ~ Parameters: ~
@ -1024,7 +1022,7 @@ nvim_get_keymap({mode}) *nvim_get_keymap()*
Array of |maparg()|-like dictionaries describing mappings. The Array of |maparg()|-like dictionaries describing mappings. The
"buffer" key is always zero. "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 Returns a `(row, col, buffer, buffername)` tuple representing the position
of the uppercase/file named mark. "End of line" column position is of the uppercase/file named mark. "End of line" column position is
returned as |v:maxcol| (big number). See |mark-motions|. 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 Gets the current mode. |mode()| "blocking" is true if Nvim is waiting for
input. input.
Return: ~
Dictionary { "mode": String, "blocking": Boolean }
Attributes: ~ Attributes: ~
|api-fast| |api-fast|
Return: ~
Dictionary { "mode": String, "blocking": Boolean }
nvim_get_proc({pid}) *nvim_get_proc()* nvim_get_proc({pid}) *nvim_get_proc()*
Gets info describing process `pid`. Gets info describing process `pid`.
@ -1222,7 +1220,7 @@ nvim_notify({msg}, {log_level}, {opts}) *nvim_notify()*
• {log_level} The log level • {log_level} The log level
• {opts} Reserved for future use. • {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 Open a terminal instance in a buffer
By default (and currently the only option) the terminal will not be 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). • {data} Multiline input. May be binary (containing NUL bytes).
• {crlf} Also break lines at CR and CRLF. • {crlf} Also break lines at CR and CRLF.
• {phase} -1: paste in a single call (i.e. without streaming). To • {phase} -1: paste in a single call (i.e. without streaming). To
"stream" a paste, call `nvim_paste` sequentially "stream" a paste, call `nvim_paste` sequentially with these
with these `phase` values: `phase` values:
• 1: starts the paste (exactly once) • 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times) • 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once) • 3: ends the paste (exactly once)
Return: ~ Return: ~
• true: Client may continue pasting. • true: Client may continue pasting.
• false: Client must cancel the paste. • false: Client must cancel the paste.
@ -1326,7 +1323,7 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special})
• cpoptions • cpoptions
*nvim_select_popupmenu_item()* *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. Selects an item in the completion popup menu.
If neither |ins-completion| nor |cmdline-completion| popup menu is active 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: ~ Parameters: ~
• {window} Window handle • {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. Sets a highlight group.
Note: ~ Note: ~
• Unlike the `:highlight` command which can update a highlight group, this • Unlike the `:highlight` command which can update a highlight group,
function completely replaces the definition. For example: 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'. 'Visual'.
• The fg and bg keys also accept the string values `"fg"` or `"bg"` which • The fg and bg keys also accept the string values `"fg"` or `"bg"`
act as aliases to the corresponding foreground and background values which act as aliases to the corresponding foreground and background
of the Normal group. If the Normal group has not been defined, using values of the Normal group. If the Normal group has not been defined,
these values results in an error. using these values results in an error.
• If `link` is used in combination with other attributes; only the `link` • If `link` is used in combination with other attributes; only the
will take effect (see |:hi-link|). `link` will take effect (see |:hi-link|).
Parameters: ~ Parameters: ~
• {ns_id} Namespace id for this highlight |nvim_create_namespace()|. • {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: ~ Parameters: ~
• {ns_id} the namespace to activate • {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. Sets a global |mapping| for the given mode.
To set a buffer-local mapping, use |nvim_buf_set_keymap()|. 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: ~ Parameters: ~
• {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …) or • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …)
"!" for |:map!|, or empty string for |:map|. "ia", "ca" or or "!" for |:map!|, or empty string for |:map|. "ia", "ca" or
"!a" for abbreviation in Insert mode, Cmdline mode, or both, "!a" for abbreviation in Insert mode, Cmdline mode, or both,
respectively respectively
• {lhs} Left-hand-side |{lhs}| of the mapping. • {lhs} Left-hand-side |{lhs}| of the mapping.
@ -1651,7 +1648,7 @@ nvim_eval({expr}) *nvim_eval()*
Return: ~ Return: ~
Evaluation result or expanded object 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 Executes Vimscript (multiline block of Ex commands), like anonymous
|:source|. |:source|.
@ -1704,18 +1701,16 @@ nvim_parse_expression({expr}, {flags}, {highlight})
region [start_col, end_col)). region [start_col, end_col)).
Return: ~ Return: ~
• AST: top-level dictionary with these keys: • AST: top-level dictionary with these keys:
• "error": Dictionary with error, present only if parser saw some • "error": Dictionary with error, present only if parser saw some
error. Contains the following keys: error. Contains the following keys:
• "message": String, error message in printf format, translated. • "message": String, error message in printf format, translated.
Must contain exactly one "%.*s". Must contain exactly one "%.*s".
• "arg": String, error message argument. • "arg": String, error message argument.
• "len": Amount of bytes successfully parsed. With flags equal to "" • "len": Amount of bytes successfully parsed. With flags equal to ""
that should be equal to the length of expr string. (Successfully that should be equal to the length of expr string. ("Successfully
parsed” here means “participated in AST creation”, not “till the parsed" here means "participated in AST creation", not "till the
first error.) first error".)
• "ast": AST, either nil or a dictionary with these keys: • "ast": AST, either nil or a dictionary with these keys:
• "type": node type, one of the value names from ExprASTNodeType • "type": node type, one of the value names from ExprASTNodeType
stringified without "kExprNode" prefix. 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 is zero, one or two children, key will not be present if node
has no children. Maximum number of children may be found in has no children. Maximum number of children may be found in
node_maxchildren array. node_maxchildren array.
• Local values (present only for certain nodes): • Local values (present only for certain nodes):
• "scope": a single Integer, specifies scope for "Option" and • "scope": a single Integer, specifies scope for "Option" and
"PlainIdentifier" nodes. For "Option" it is one of ExprOptScope "PlainIdentifier" nodes. For "Option" it is one of ExprOptScope
@ -1760,11 +1754,11 @@ nvim_parse_expression({expr}, {flags}, {highlight})
Command Functions *api-command* Command Functions *api-command*
*nvim_buf_create_user_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|. Creates a buffer-local command |user-commands|.
Parameters: ~ Parameters: ~
• {buffer} Buffer handle, or 0 for current buffer. • {buffer} Buffer handle, or 0 for current buffer.
See also: ~ See also: ~
• nvim_create_user_command • nvim_create_user_command
@ -1780,7 +1774,7 @@ nvim_buf_del_user_command({buffer}, {name})
• {buffer} Buffer handle, or 0 for current buffer. • {buffer} Buffer handle, or 0 for current buffer.
• {name} Name of the command to delete. • {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|. Gets a map of buffer-local |user-commands|.
Parameters: ~ Parameters: ~
@ -1790,7 +1784,7 @@ nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
Return: ~ Return: ~
Map of maps describing commands. Map of maps describing commands.
nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* nvim_cmd({cmd}, {opts}) *nvim_cmd()*
Executes an Ex command. Executes an Ex command.
Unlike |nvim_command()| this command takes a structured Dictionary instead Unlike |nvim_command()| this command takes a structured Dictionary instead
@ -1825,7 +1819,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
• |nvim_command()| • |nvim_command()|
*nvim_create_user_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. Creates a global |user-commands| command.
For Lua usage see |lua-guide-commands-create|. For Lua usage see |lua-guide-commands-create|.
@ -1885,7 +1879,7 @@ nvim_del_user_command({name}) *nvim_del_user_command()*
Parameters: ~ Parameters: ~
• {name} Name of the command to delete. • {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. Gets a map of global (non-buffer-local) Ex commands.
Currently only |user-commands| are supported, not builtin 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: ~ See also: ~
• |nvim_get_all_options_info()| • |nvim_get_all_options_info()|
nvim_parse_cmd({str}, {*opts}) *nvim_parse_cmd()* nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
Parse command line. Parse command line.
Doesn't check the validity of command arguments. 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 • bar: (boolean) The "|" character is treated as a command separator
and the double quote character (") is treated as the start of a and the double quote character (") is treated as the start of a
comment. comment.
• mods: (dictionary) |:command-modifiers|. • mods: (dictionary) |:command-modifiers|.
• filter: (dictionary) |:filter|. • filter: (dictionary) |:filter|.
• pattern: (string) Filter pattern. Empty string if there is no • pattern: (string) Filter pattern. Empty string if there is no
filter. filter.
• force: (boolean) Whether filter is inverted or not. • force: (boolean) Whether filter is inverted or not.
• silent: (boolean) |:silent|. • silent: (boolean) |:silent|.
• emsg_silent: (boolean) |:silent!|. • emsg_silent: (boolean) |:silent!|.
• unsilent: (boolean) |:unsilent|. • unsilent: (boolean) |:unsilent|.
@ -1986,7 +1978,7 @@ nvim_get_all_options_info() *nvim_get_all_options_info()*
See also: ~ See also: ~
• |nvim_get_commands()| • |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 Gets the option information for one option from arbitrary buffer or window
Resulting dictionary has keys: Resulting dictionary has keys:
@ -2020,7 +2012,7 @@ nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
Return: ~ Return: ~
Option Information 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 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, |:set|: the local value of an option is returned if it exists; otherwise,
the global value is returned. Local values always correspond to the 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 Option value
*nvim_set_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 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 |:set|: for global-local options, both the global and local value are set
unless otherwise specified with {scope}. unless otherwise specified with {scope}.
@ -2069,16 +2061,16 @@ For more information on buffers, see |buffers|.
Unloaded Buffers: ~ Unloaded Buffers: ~
Buffers may be unloaded by the |:bunload| command or the buffer's Buffers may be unloaded by the |:bunload| command or the buffer's
|'bufhidden'| option. When a buffer is unloaded its file contents are |'bufhidden'| option. When a buffer is unloaded its file contents are freed
freed from memory and vim cannot operate on the buffer lines until it is from memory and vim cannot operate on the buffer lines until it is reloaded
reloaded (usually by opening the buffer again in a new window). API (usually by opening the buffer again in a new window). API methods such as
methods such as |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be affected.
affected.
You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
whether a buffer is loaded. 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. Activates buffer-update events on a channel, or as Lua callbacks.
Example (Lua): capture buffer updates in a global `events` variable (use 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. callbacks.
• {opts} Optional parameters. • {opts} Optional parameters.
• on_lines: Lua callback invoked on change. Return a • on_lines: Lua callback invoked on change. Return a
truthy value (not `false` or `nil`) truthy value (not `false` or `nil`) to detach. Args:
to detach. Args:
• the string "lines" • the string "lines"
• buffer handle • buffer handle
• b:changedtick • b:changedtick
@ -2111,12 +2102,10 @@ nvim_buf_attach({buffer}, {send_buffer}, {*opts}) *nvim_buf_attach()*
• byte count of previous contents • byte count of previous contents
• deleted_codepoints (if `utf_sizes` is true) • deleted_codepoints (if `utf_sizes` is true)
• deleted_codeunits (if `utf_sizes` is true) • deleted_codeunits (if `utf_sizes` is true)
• on_bytes: Lua callback invoked on change. This • on_bytes: Lua callback invoked on change. This
callback receives more granular information about the callback receives more granular information about the
change compared to on_lines. Return a truthy value change compared to on_lines. Return a truthy value
(not `false` or `nil`) to (not `false` or `nil`) to detach. Args:
detach. Args:
• the string "bytes" • the string "bytes"
• buffer handle • buffer handle
• b:changedtick • 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 • new end column of the changed text (if new end row
= 0, offset from start column) = 0, offset from start column)
• new end byte length of the changed text • new end byte length of the changed text
• on_changedtick: Lua callback invoked on changedtick • on_changedtick: Lua callback invoked on changedtick
increment without text change. Args: increment without text change. Args:
• the string "changedtick" • the string "changedtick"
• buffer handle • buffer handle
• b:changedtick • b:changedtick
• on_detach: Lua callback invoked on detach. Args: • on_detach: Lua callback invoked on detach. Args:
• the string "detach" • the string "detach"
• buffer handle • buffer handle
• on_reload: Lua callback invoked on reload. The entire • on_reload: Lua callback invoked on reload. The entire
buffer content should be considered changed. Args: buffer content should be considered changed. Args:
• the string "reload" • the string "reload"
• buffer handle • buffer handle
• utf_sizes: include UTF-32 and UTF-16 size of the • utf_sizes: include UTF-32 and UTF-16 size of the
replaced region, as args to `on_lines`. replaced region, as args to `on_lines`.
• preview: also attach to command preview (i.e. • 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 • {buffer} Buffer handle, or 0 for current buffer
• {name} Variable name • {name} Variable name
nvim_buf_delete({buffer}, {*opts}) *nvim_buf_delete()* nvim_buf_delete({buffer}, {opts}) *nvim_buf_delete()*
Deletes the buffer. See |:bwipeout| Deletes the buffer. See |:bwipeout|
Attributes: ~ Attributes: ~
@ -2263,8 +2248,8 @@ nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()*
Gets a list of buffer-local |mapping| definitions. Gets a list of buffer-local |mapping| definitions.
Parameters: ~ Parameters: ~
• {mode} Mode short-name ("n", "i", "v", ...)
• {buffer} Buffer handle, or 0 for current buffer • {buffer} Buffer handle, or 0 for current buffer
• {mode} Mode short-name ("n", "i", "v", ...)
Return: ~ Return: ~
Array of |maparg()|-like dictionaries describing mappings. The 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()*
nvim_buf_get_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col}, nvim_buf_get_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
{*opts}) {opts})
Gets a range from the buffer. Gets a range from the buffer.
This differs from |nvim_buf_get_lines()| in that it allows retrieving only 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| Line count, or 0 for unloaded buffer. |api-buffer|
*nvim_buf_set_keymap()* *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. Sets a buffer-local |mapping| for the given mode.
Parameters: ~ Parameters: ~
@ -2440,7 +2425,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
• |nvim_buf_set_text()| • |nvim_buf_set_text()|
*nvim_buf_set_mark()* *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 Sets a named mark in the given buffer, all marks are allowed
file/uppercase, visual, last change, etc. See |mark-motions|. 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 true if the extmark was found, else false
*nvim_buf_get_extmark_by_id()* *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|. Gets the position (0-indexed) of an |extmark|.
Parameters: ~ 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 0-indexed (row, col) tuple or empty list () if extmark id was absent
*nvim_buf_get_extmarks()* *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 Gets |extmarks| in "traversal order" from a |charwise| region defined by
buffer positions (inclusive, 0-indexed |api-indexing|). 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". List of [extmark_id, row, col] tuples in "traversal order".
*nvim_buf_set_extmark()* *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|. Creates or updates an |extmark|.
By default a new extmark is created when no id is passed in, but it is 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. • "right_align": display right aligned in the window.
• "inline": display at the specified column, and shift the • "inline": display at the specified column, and shift the
buffer text to the right as needed. buffer text to the right as needed.
• virt_text_win_col : position the virtual text at a fixed • virt_text_win_col : position the virtual text at a fixed
window column (starting from the first text column of the window column (starting from the first text column of the
screen line) instead of "virt_text_pos". screen line) instead of "virt_text_pos".
@ -2715,14 +2699,12 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
wrapped lines. wrapped lines.
• hl_mode : control how highlights are combined with the • hl_mode : control how highlights are combined with the
highlights of the text. Currently only affects virt_text highlights of the text. Currently only affects virt_text
highlights, but might affect `hl_group` in highlights, but might affect `hl_group` in later versions.
later versions.
• "replace": only show the virt_text color. This is the • "replace": only show the virt_text color. This is the
default. default.
• "combine": combine with background text color. • "combine": combine with background text color.
• "blend": blend with background text color. Not supported • "blend": blend with background text color. Not supported
for "inline" virt_text. for "inline" virt_text.
• virt_lines : virtual lines to add next to this mark This • virt_lines : virtual lines to add next to this mark This
should be an array over lines, where each line in turn is should be an array over lines, where each line in turn is
an array over [text, highlight] tuples. In general, buffer 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. dict that maps from names to namespace ids.
*nvim_set_decoration_provider()* *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| Set or change decoration provider for a |namespace|
This is a very general purpose interface for having Lua callbacks being 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. This takes precedence over the 'winhighlight' option.
Parameters: ~ Parameters: ~
• {ns_id} the namespace to use • {ns_id} the namespace to use
nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()* nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()*
Sets a window-scoped (w:) variable 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 • {window} Window handle, or 0 for current window
• {width} Width as a count of columns • {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 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. 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, 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. 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. window.
• "cursor" Cursor position in current window. • "cursor" Cursor position in current window.
• "mouse" Mouse position • "mouse" Mouse position
• win: |window-ID| window to split, or relative window when • win: |window-ID| window to split, or relative window when
creating a float (relative="win"). creating a float (relative="win").
• anchor: Decides which corner of the float to place at • 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 • "NE" northeast
• "SW" southwest • "SW" southwest
• "SE" southeast • "SE" southeast
• width: Window width (in character cells). Minimum of 1. • width: Window width (in character cells). Minimum of 1.
• height: Window height (in character cells). Minimum of 1. • height: Window height (in character cells). Minimum of 1.
• bufpos: Places float relative to buffer text (only when • bufpos: Places float relative to buffer text (only when
relative="win"). Takes a tuple of zero-indexed [line, relative="win"). Takes a tuple of zero-indexed [line,
column]. `row` and `col` if given are column]. `row` and `col` if given are applied relative to
applied relative to this position, else they default to: this position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or "NE" • `row=1` and `col=0` if `anchor` is "NW" or "NE"
• `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
like a tooltip near the buffer text). like a tooltip near the buffer text).
• row: Row position in units of "screen cell height", may be • row: Row position in units of "screen cell height", may be
fractional. fractional.
• col: Column position in units of "screen cell width", may • 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. wildoptions+=pum) The default value for floats are 50.
In general, values below 100 are recommended, unless In general, values below 100 are recommended, unless
there is a good reason to overshadow builtin elements. there is a good reason to overshadow builtin elements.
• style: (optional) Configure the appearance of the window. • style: (optional) Configure the appearance of the window.
Currently only supports one value: Currently only supports one value:
• "minimal" Nvim will display the window with many UI • "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 empty. The end-of-buffer region is hidden by setting
`eob` flag of 'fillchars' to a space char, and clearing `eob` flag of 'fillchars' to a space char, and clearing
the |hl-EndOfBuffer| region in 'winhighlight'. the |hl-EndOfBuffer| region in 'winhighlight'.
• border: Style of (optional) window border. This can either • border: Style of (optional) window border. This can either
be a string or an array. The string values are be a string or an array. The string values are
• "none": No border (default). • "none": No border (default).
• "single": A single line box. • "single": A single line box.
• "double": A double line box. • "double": A double line box.
• "rounded": Like "single", but with rounded corners ("╭" • "rounded": Like "single", but with rounded corners
etc.). ("╭" etc.).
• "solid": Adds padding by a single whitespace cell. • "solid": Adds padding by a single whitespace cell.
• "shadow": A drop shadow effect by blending with the • "shadow": A drop shadow effect by blending with the
background. background.
@ -3256,19 +3233,26 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
any divisor of eight. The array will specify the eight any divisor of eight. The array will specify the eight
chars building up the border in a clockwise fashion chars building up the border in a clockwise fashion
starting with the top-left corner. As an example, the starting with the top-left corner. As an example, the
double box style could be specified as [ "╔", "═" ,"╗", 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 If the number of chars are less than eight, they will be
all chars the same as [ "x" ]. An empty string can be repeated. Thus an ASCII border could be specified as >
used to turn off a specific border, for instance, [ "", [ "/", "-", \"\\\\\", "|" ],
"", "", ">", "", "", "", "<" ] will only make vertical <
borders but not horizontal ones. By default, or all chars the same as >
`FloatBorder` highlight is used, which links to [ "x" ].
`WinSeparator` when not defined. It could also be <
specified by character: [ ["+", "MyCorner"], ["x", An empty string can be used to turn off a specific border,
"MyBorder"] ]. 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. • title: Title (optional) in window border, string or list.
List should consist of `[text, highlight]` tuples. If List should consist of `[text, highlight]` tuples. If
string, the default highlight group is `FloatTitle`. string, the default highlight group is `FloatTitle`.
@ -3306,7 +3290,7 @@ nvim_win_get_config({window}) *nvim_win_get_config()*
Return: ~ Return: ~
Map defining the window configuration, see |nvim_open_win()| 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 Configures window layout. Currently only for floating and external windows
(including changing a split window to those layouts). (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* 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 Clears all autocommands selected by {opts}. To delete autocmds see
|nvim_del_autocmd()|. |nvim_del_autocmd()|.
@ -3407,25 +3391,21 @@ nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()*
• event: "pat1" • event: "pat1"
• event: { "pat1" } • event: { "pat1" }
• event: { "pat1", "pat2", "pat3" } • event: { "pat1", "pat2", "pat3" }
• pattern: (string|table) • pattern: (string|table)
• pattern or patterns to match exactly. • pattern or patterns to match exactly.
• For example, if you have `*.py` as that pattern for the • For example, if you have `*.py` as that pattern for the
autocmd, you must pass `*.py` exactly to clear it. autocmd, you must pass `*.py` exactly to clear it.
`test.py` will not match the pattern. `test.py` will not match the pattern.
• defaults to clearing all patterns. • defaults to clearing all patterns.
• NOTE: Cannot be used with {buffer} • NOTE: Cannot be used with {buffer}
• buffer: (bufnr) • buffer: (bufnr)
• clear only |autocmd-buflocal| autocommands. • clear only |autocmd-buflocal| autocommands.
• NOTE: Cannot be used with {pattern} • NOTE: Cannot be used with {pattern}
• group: (string|int) The augroup name or id. • group: (string|int) The augroup name or id.
• NOTE: If not passed, will only delete autocmds not in any • NOTE: If not passed, will only delete autocmds not in any
group. 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|. Create or get an autocommand group |autocmd-groups|.
To get an existing group id, do: >lua To get an existing group id, do: >lua
@ -3446,9 +3426,10 @@ nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
See also: ~ See also: ~
• |autocmd-groups| • |autocmd-groups|
nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()* nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()*
Creates an |autocommand| event handler, defined by `callback` (Lua function Creates an |autocommand| event handler, defined by `callback` (Lua
or Vimscript function name string) or `command` (Ex command string). function or Vimscript function name string) or `command` (Ex command
string).
Example using Lua callback: >lua Example using Lua callback: >lua
vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, { 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 • callback (function|string) optional: Lua function (or
Vimscript function name, if string) called when the Vimscript function name, if string) called when the
event(s) is triggered. Lua callback can return a truthy event(s) is triggered. Lua callback can return a truthy
value (not `false` or `nil`) to delete the value (not `false` or `nil`) to delete the autocommand.
autocommand. Receives a table argument with these keys: Receives a table argument with these keys:
• id: (number) autocommand id • id: (number) autocommand id
• event: (string) name of the triggered event • event: (string) name of the triggered event
|autocmd-events| |autocmd-events|
@ -3498,7 +3479,6 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
• file: (string) expanded value of |<afile>| • file: (string) expanded value of |<afile>|
• data: (any) arbitrary data passed from • data: (any) arbitrary data passed from
|nvim_exec_autocmds()| |nvim_exec_autocmds()|
• command (string) optional: Vim command to execute on event. • command (string) optional: Vim command to execute on event.
Cannot be used with {callback} Cannot be used with {callback}
• once (boolean) optional: defaults to false. Run the • once (boolean) optional: defaults to false. Run the
@ -3548,7 +3528,7 @@ nvim_del_autocmd({id}) *nvim_del_autocmd()*
Parameters: ~ Parameters: ~
• {id} Integer Autocommand id returned by |nvim_create_autocmd()| • {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} Execute all autocommands for {event} that match the corresponding {opts}
|autocmd-execute|. |autocmd-execute|.
@ -3569,7 +3549,7 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
See also: ~ See also: ~
• |:doautocmd| • |:doautocmd|
nvim_get_autocmds({*opts}) *nvim_get_autocmds()* nvim_get_autocmds({opts}) *nvim_get_autocmds()*
Get all autocommands that match the corresponding {opts}. Get all autocommands that match the corresponding {opts}.
These examples will get autocommands matching ALL the given criteria: >lua 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. • {height} Popupmenu height, must be greater than zero.
nvim_ui_set_focus({gained}) *nvim_ui_set_focus()* 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: ~ Attributes: ~
|RPC| only |RPC| only
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
TODO: Documentation
Attributes: ~ Attributes: ~
|RPC| only |RPC| only
@ -3698,7 +3677,6 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
Tells Nvim when a terminal event has occurred Tells Nvim when a terminal event has occurred
The following terminal events are supported: The following terminal events are supported:
• "termresponse": The terminal sent an OSC or DCS response sequence to • "termresponse": The terminal sent an OSC or DCS response sequence to
Nvim. The payload is the received response. Sets |v:termresponse| and Nvim. The payload is the received response. Sets |v:termresponse| and
fires |TermResponse|. fires |TermResponse|.
@ -3707,11 +3685,10 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
|RPC| only |RPC| only
Parameters: ~ Parameters: ~
• {event} Event name • {event} Event name
• {payload} Event payload • {value} Event payload
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()* nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
TODO: Documentation
Attributes: ~ Attributes: ~
|RPC| only |RPC| only
@ -3731,4 +3708,5 @@ nvim_ui_try_resize_grid({grid}, {width}, {height})
• {width} The new requested width. • {width} The new requested width.
• {height} The new requested height. • {height} The new requested height.
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@ -397,7 +397,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
diagnostics. Options: diagnostics. Options:
• severity: Only underline diagnostics matching the • severity: Only underline diagnostics matching the
given severity |diagnostic-severity| given severity |diagnostic-severity|
• virtual_text: (default true) Use virtual text for • virtual_text: (default true) Use virtual text for
diagnostics. If multiple diagnostics are set for a diagnostics. If multiple diagnostics are set for a
namespace, one prefix per diagnostic + the last 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 • format: (function) A function that takes a diagnostic
as input and returns a string. The return value is as input and returns a string. The return value is
the text used to display the diagnostic. Example: >lua the text used to display the diagnostic. Example: >lua
function(diagnostic) function(diagnostic)
if diagnostic.severity == vim.diagnostic.severity.ERROR then if diagnostic.severity == vim.diagnostic.severity.ERROR then
return string.format("E: %s", diagnostic.message) return string.format("E: %s", diagnostic.message)
@ -438,7 +436,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
return diagnostic.message return diagnostic.message
end end
< <
• signs: (default true) Use signs for diagnostics • signs: (default true) Use signs for diagnostics
|diagnostic-signs|. Options: |diagnostic-signs|. Options:
• severity: Only show signs for diagnostics matching • 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, default is to use "E", "W", "I", and "H" for errors,
warnings, information, and hints, respectively. warnings, information, and hints, respectively.
Example: >lua Example: >lua
vim.diagnostic.config({ vim.diagnostic.config({
signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
}) })
@ -463,7 +459,6 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
• linehl: (table) A table mapping |diagnostic-severity| • linehl: (table) A table mapping |diagnostic-severity|
to the highlight group used for the whole line the to the highlight group used for the whole line the
sign is placed in. sign is placed in.
• float: Options for floating windows. See • float: Options for floating windows. See
|vim.diagnostic.open_float()|. |vim.diagnostic.open_float()|.
• update_in_insert: (default false) Update diagnostics in • update_in_insert: (default false) Update diagnostics in
@ -542,8 +537,8 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Return: ~ Return: ~
(`vim.Diagnostic[]`) table A list of diagnostic items (`vim.Diagnostic[]`) table A list of diagnostic items
|diagnostic-structure|. Keys `bufnr` , `end_lnum` , `end_col` , and `severity` are |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and
guaranteed to be present. `severity` are guaranteed to be present.
get_namespace({namespace}) *vim.diagnostic.get_namespace()* get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata. Get namespace metadata.
@ -685,7 +680,7 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
(`vim.Diagnostic?`) |diagnostic-structure| or `nil` if {pat} fails to (`vim.Diagnostic?`) |diagnostic-structure| or `nil` if {pat} fails to
match {str}. match {str}.
open_float({opts}, {...}) *vim.diagnostic.open_float()* open_float({opts}) *vim.diagnostic.open_float()*
Show diagnostics in a floating window. Show diagnostics in a floating window.
Parameters: ~ Parameters: ~
@ -738,8 +733,9 @@ open_float({opts}, {...}) *vim.diagnostic.open_float()*
diagnostic instead of prepending it. Overrides the setting diagnostic instead of prepending it. Overrides the setting
from |vim.diagnostic.config()|. from |vim.diagnostic.config()|.
Return: ~ Return (multiple): ~
(`integer?, integer?`) ({float_bufnr}, {win_id}) (`integer?`) float_bufnr
(`integer?`) win_id
reset({namespace}, {bufnr}) *vim.diagnostic.reset()* reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
Remove all diagnostics from the given namespace. Remove all diagnostics from the given namespace.
@ -823,4 +819,5 @@ toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Return: ~ Return: ~
(`table[]`) of quickfix list items |setqflist-what| (`table[]`) of quickfix list items |setqflist-what|
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@ -712,10 +712,9 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
(`string?`) err On timeout, cancel, or error, `err` is a string (`string?`) err On timeout, cancel, or error, `err` is a string
describing the failure reason, and `result` is nil. 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 LSP client object. You can get an active client object via
|vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|. |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
• Methods: • Methods:
• request(method, params, [handler], bufnr) Sends a request to the • request(method, params, [handler], bufnr) Sends a request to the
server. This is a thin wrapper around {client.rpc.request} with some 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] given method. Always returns true for unknown off-spec methods. [opts]
is a optional `{bufnr?: integer}` table. Some language server is a optional `{bufnr?: integer}` table. Some language server
capabilities can be file specific. capabilities can be file specific.
• Members • 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 • {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 See |vim.lsp.start_client()| for all available options. The most important
are: are:
• `name` arbitrary name for the LSP client. Should be unique per language • `name` arbitrary name for the LSP client. Should be unique per language
server. server.
• `cmd` command string[] or function, described at • `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 • cmd_env: (table) Environment flags to pass to the LSP on
spawn. Must be specified using a table. Non-string values spawn. Must be specified using a table. Non-string values
are coerced to string. Example: > 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 • detached: (boolean, default true) Daemonize the server
process so that it runs in a separate process group from 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. make_client_capabilities() and modify its result.
• Note: To send an empty dictionary use • Note: To send an empty dictionary use
|vim.empty_dict()|, else it will be encoded as an array. |vim.empty_dict()|, else it will be encoded as an array.
• handlers: Map of language server method names to • handlers: Map of language server method names to
|lsp-handler| |lsp-handler|
• settings: Map with language server specific settings. • 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 • signal: number describing the signal used to terminate
(if any) (if any)
• client_id: client handle • client_id: client handle
• on_attach: Callback (client, bufnr) invoked when client • on_attach: Callback (client, bufnr) invoked when client
attaches to a buffer. attaches to a buffer.
• trace: ("off" | "messages" | "verbose" | nil) passed • 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. sending the "shutdown" request before sending kill -15.
If set to false, nvim exits immediately after sending If set to false, nvim exits immediately after sending
the "shutdown" request to the server. the "shutdown" request to the server.
• root_dir: (string) Directory where the LSP server will • root_dir: (string) Directory where the LSP server will
base its workspaceFolders, rootUri, and rootPath on base its workspaceFolders, rootUri, and rootPath on
initialization. initialization.
@ -1124,6 +1117,9 @@ add_workspace_folder({workspace_folder})
Add the folder at path to the workspace folders. If {path} is not Add the folder at path to the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|. provided, the user will be prompted for a path using |input()|.
Parameters: ~
• {workspace_folder} (`string?`)
clear_references() *vim.lsp.buf.clear_references()* clear_references() *vim.lsp.buf.clear_references()*
Removes document highlights from current buffer. Removes document highlights from current buffer.
@ -1133,8 +1129,8 @@ code_action({options}) *vim.lsp.buf.code_action()*
Parameters: ~ Parameters: ~
• {options} (`table?`) Optional table which holds the following • {options} (`table?`) Optional table which holds the following
optional fields: optional fields:
• context: (table|nil) Corresponds to `CodeActionContext` of • context: (table|nil) Corresponds to `CodeActionContext`
the LSP specification: of the LSP specification:
• diagnostics (table|nil): LSP `Diagnostic[]`. Inferred • diagnostics (table|nil): LSP `Diagnostic[]`. Inferred
from the current position if not provided. from the current position if not provided.
• only (table|nil): List of LSP `CodeActionKind`s used to • 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`. values like `refactor` or `quickfix`.
• triggerKind (number|nil): The reason why code actions • triggerKind (number|nil): The reason why code actions
were requested. were requested.
• filter: (function|nil) Predicate taking an `CodeAction` • filter: (function|nil) Predicate taking an `CodeAction`
and returning a boolean. and returning a boolean.
• apply: (boolean|nil) When set to `true`, and there is • apply: (boolean|nil) When set to `true`, and there is
@ -1235,7 +1230,8 @@ format({options}) *vim.lsp.buf.format()*
optional fields: optional fields:
• formatting_options (table|nil): Can be used to specify • formatting_options (table|nil): Can be used to specify
FormattingOptions. Some unspecified options will be 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 • timeout_ms (integer|nil, default 1000): Time in
milliseconds to block for formatting requests. No effect milliseconds to block for formatting requests. No effect
if async=true if async=true
@ -1245,7 +1241,6 @@ format({options}) *vim.lsp.buf.format()*
• filter (function|nil): Predicate used to filter clients. • filter (function|nil): Predicate used to filter clients.
Receives a client as argument and must return a boolean. Receives a client as argument and must return a boolean.
Clients matching the predicate are included. Example: >lua Clients matching the predicate are included. Example: >lua
-- Never request typescript-language-server for formatting -- Never request typescript-language-server for formatting
vim.lsp.buf.format { vim.lsp.buf.format {
filter = function(client) return client.name ~= "tsserver" end 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 Remove the folder at path from the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|. provided, the user will be prompted for a path using |input()|.
Parameters: ~
• {workspace_folder} (`string?`)
rename({new_name}, {options}) *vim.lsp.buf.rename()* rename({new_name}, {options}) *vim.lsp.buf.rename()*
Renames all references to the symbol under the cursor. Renames all references to the symbol under the cursor.
@ -1454,12 +1452,13 @@ get({bufnr}) *vim.lsp.codelens.get()*
Return: ~ Return: ~
(`lsp.CodeLens[]`) (`lsp.CodeLens[]`)
*vim.lsp.codelens.on_codelens()* on_codelens({err}, {result}, {ctx}) *vim.lsp.codelens.on_codelens()*
on_codelens({err}, {result}, {ctx}, {_})
|lsp-handler| for the method `textDocument/codeLens` |lsp-handler| for the method `textDocument/codeLens`
Parameters: ~ Parameters: ~
• {ctx} (`lsp.HandlerContext`) • {err} (`lsp.ResponseError?`)
• {result} (`lsp.CodeLens[]`)
• {ctx} (`lsp.HandlerContext`)
refresh({opts}) *vim.lsp.codelens.refresh()* refresh({opts}) *vim.lsp.codelens.refresh()*
Refresh the lenses. Refresh the lenses.
@ -1499,7 +1498,7 @@ enable({bufnr}, {enable}) *vim.lsp.inlay_hint.enable()*
< <
Note: ~ Note: ~
This API is pre-release (unstable). This API is pre-release (unstable).
Parameters: ~ Parameters: ~
• {bufnr} (`integer?`) Buffer handle, or 0 or nil for current • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
@ -1523,7 +1522,7 @@ get({filter}) *vim.lsp.inlay_hint.get()*
< <
Note: ~ Note: ~
This API is pre-release (unstable). This API is pre-release (unstable).
Parameters: ~ Parameters: ~
• {filter} (`vim.lsp.inlay_hint.get.filter?`) Optional filters • {filter} (`vim.lsp.inlay_hint.get.filter?`) Optional filters
@ -1539,8 +1538,9 @@ get({filter}) *vim.lsp.inlay_hint.get()*
• inlay_hint (lsp.InlayHint) • inlay_hint (lsp.InlayHint)
is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()* is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()*
Note: ~ Note: ~
This API is pre-release (unstable). This API is pre-release (unstable).
Parameters: ~ Parameters: ~
• {bufnr} (`integer?`) Buffer handle, or 0 or nil for current • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
@ -1653,6 +1653,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
< <
Parameters: ~ Parameters: ~
• {result} (`lsp.Hover`)
• {ctx} (`lsp.HandlerContext`) • {ctx} (`lsp.HandlerContext`)
• {config} (`table`) Configuration table. • {config} (`table`) Configuration table.
• border: (default=nil) • border: (default=nil)
@ -1674,7 +1675,7 @@ signature_help({_}, {result}, {ctx}, {config})
< <
Parameters: ~ Parameters: ~
• {result} (`table`) Response from the language server • {result} (`lsp.SignatureHelp`) Response from the language server
• {ctx} (`lsp.HandlerContext`) Client context • {ctx} (`lsp.HandlerContext`) Client context
• {config} (`table`) Configuration table. • {config} (`table`) Configuration table.
• border: (default=nil) • border: (default=nil)
@ -1695,6 +1696,7 @@ apply_text_document_edit({text_document_edit}, {index}, {offset_encoding})
• {text_document_edit} (`table`) a `TextDocumentEdit` object • {text_document_edit} (`table`) a `TextDocumentEdit` object
• {index} (`integer`) Optional index of the edit, if from • {index} (`integer`) Optional index of the edit, if from
a list of edits (or nil, if not from a list) a list of edits (or nil, if not from a list)
• {offset_encoding} (`string?`)
See also: ~ See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit • 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` • {workspace_edit} (`table`) `WorkspaceEdit`
• {offset_encoding} (`string`) utf-8|utf-16|utf-32 (required) • {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()* buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer. Removes document highlights from a buffer.
@ -1994,6 +1999,7 @@ preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
Parameters: ~ Parameters: ~
• {location} (`table`) a single `Location` or `LocationLink` • {location} (`table`) a single `Location` or `LocationLink`
• {opts} (`table`)
Return (multiple): ~ Return (multiple): ~
(`integer?`) buffer id of float window (`integer?`) buffer id of float window
@ -2038,6 +2044,7 @@ stylize_markdown({bufnr}, {contents}, {opts})
`open_floating_preview` instead `open_floating_preview` instead
Parameters: ~ Parameters: ~
• {bufnr} (`integer`)
• {contents} (`table`) of lines to show in window • {contents} (`table`) of lines to show in window
• {opts} (`table`) with optional fields • {opts} (`table`) with optional fields
• height of floating window • height of floating window
@ -2055,6 +2062,7 @@ symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()*
Parameters: ~ Parameters: ~
• {symbols} (`table`) DocumentSymbol[] or SymbolInformation[] • {symbols} (`table`) DocumentSymbol[] or SymbolInformation[]
• {bufnr} (`integer`)
============================================================================== ==============================================================================
@ -2092,7 +2100,7 @@ should_log({level}) *vim.lsp.log.should_log()*
• {level} (`integer`) log level • {level} (`integer`) log level
Return: ~ 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 • {port} (`integer`) port to connect to
Return: ~ 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()* *vim.lsp.rpc.domain_socket_connect()*
domain_socket_connect({pipe_path}) domain_socket_connect({pipe_path})
@ -2126,7 +2135,8 @@ domain_socket_connect({pipe_path})
of the named pipe (Windows) to connect to of the named pipe (Windows) to connect to
Return: ~ 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()* format_rpc_error({err}) *vim.lsp.rpc.format_rpc_error()*
Constructs an error message from an LSP error object. Constructs an error message from an LSP error object.
@ -2241,4 +2251,5 @@ resolve_capabilities({server_capabilities})
Return: ~ Return: ~
(`lsp.ServerCapabilities?`) Normalized table of capabilities (`lsp.ServerCapabilities?`) Normalized table of capabilities
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@ -582,25 +582,21 @@ A subset of the `vim.*` API is available in threads. This includes:
============================================================================== ==============================================================================
VIM.HIGHLIGHT *vim.highlight* VIM.HIGHLIGHT *vim.highlight*
Nvim includes a function for highlighting a selection on yank. Nvim includes a function for highlighting a selection on yank.
To enable it, add the following to your `init.vim`: >vim To enable it, add the following to your `init.vim`: >vim
au TextYankPost * silent! lua vim.highlight.on_yank() au TextYankPost * silent! lua vim.highlight.on_yank()
< <
You can customize the highlight group and the duration of the highlight You can customize the highlight group and the duration of the highlight via: >vim
via: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=150} 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 If you want to exclude visual selections from highlighting on yank, use: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false} au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
< <
vim.highlight.on_yank({opts}) *vim.highlight.on_yank()* vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
Highlight the yanked text Highlight the yanked text
@ -678,12 +674,10 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
• `count_a` (integer): Hunk size in {a}. • `count_a` (integer): Hunk size in {a}.
• `start_b` (integer): Start line of hunk in {b}. • `start_b` (integer): Start line of hunk in {b}.
• `count_b` (integer): Hunk size in {b}. • `count_b` (integer): Hunk size in {b}.
• `result_type` (string): Form of the returned diff: • `result_type` (string): Form of the returned diff:
• "unified": (default) String in unified format. • "unified": (default) String in unified format.
• "indices": Array of hunk locations. Note: This option is • "indices": Array of hunk locations. Note: This option is
ignored if `on_hunk` is used. ignored if `on_hunk` is used.
• `linematch` (boolean|integer): Run linematch on the • `linematch` (boolean|integer): Run linematch on the
resulting hunks from xdiff. When integer, only hunks upto resulting hunks from xdiff. When integer, only hunks upto
this size in lines are run through linematch. Requires this size in lines are run through linematch. Requires
@ -694,7 +688,6 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
possible diff possible diff
• "patience" patience diff algorithm • "patience" patience diff algorithm
• "histogram" histogram diff algorithm • "histogram" histogram diff algorithm
• `ctxlen` (integer): Context length • `ctxlen` (integer): Context length
• `interhunkctxlen` (integer): Inter hunk context length • `interhunkctxlen` (integer): Inter hunk context length
• `ignore_whitespace` (boolean): Ignore whitespace • `ignore_whitespace` (boolean): Ignore whitespace
@ -716,30 +709,38 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
============================================================================== ==============================================================================
VIM.MPACK *vim.mpack* VIM.MPACK *vim.mpack*
This module provides encoding and decoding of Lua objects to and from This module provides encoding and decoding of Lua objects to and from
msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
vim.mpack.decode({str}) *vim.mpack.decode()* vim.mpack.decode({str}) *vim.mpack.decode()*
Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object. Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
Parameters: ~ Parameters: ~
• {str} (`string`) • {str} (`string`)
Return: ~
(`any`)
vim.mpack.encode({obj}) *vim.mpack.encode()* vim.mpack.encode({obj}) *vim.mpack.encode()*
Encodes (or "packs") Lua object {obj} as msgpack in a Lua string. Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
Parameters: ~
• {obj} (`any`)
Return: ~
(`string`)
============================================================================== ==============================================================================
VIM.JSON *vim.json* VIM.JSON *vim.json*
This module provides encoding and decoding of Lua objects to and from This module provides encoding and decoding of Lua objects to and from
JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
vim.json.decode({str}, {opts}) *vim.json.decode()* vim.json.decode({str}, {opts}) *vim.json.decode()*
Decodes (or "unpacks") the JSON-encoded {str} to a Lua object. Decodes (or "unpacks") the JSON-encoded {str} to a Lua object.
• Decodes JSON "null" as |vim.NIL| (controllable by {opts}, see below). • Decodes JSON "null" as |vim.NIL| (controllable by {opts}, see below).
• Decodes empty object as |vim.empty_dict()|. • Decodes empty object as |vim.empty_dict()|.
• Decodes empty array as `{}` (empty Lua table). • Decodes empty array as `{}` (empty Lua table).
@ -829,24 +830,24 @@ vim.spell.check({str}) *vim.spell.check()*
VIM *vim.builtin* VIM *vim.builtin*
vim.api.{func}({...}) *vim.api* vim.api.{func}({...}) *vim.api*
Invokes Nvim |API| function {func} with arguments {...}. Invokes Nvim |API| function {func} with arguments {...}.
Example: call the "nvim_get_current_line()" API function: >lua Example: call the "nvim_get_current_line()" API function: >lua
print(tostring(vim.api.nvim_get_current_line())) 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 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 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 table representing a Dictionary or Array, because it is treated as
missing: `{"foo", nil}` is the same as `{"foo"}`. 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 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 |vim.types| allows typing the empty table (it is unclear whether empty Lua
table represents empty list or empty array) and forcing integral numbers table represents empty list or empty array) and forcing integral numbers
to be |Float|. See |lua-special-tbl| for more details. 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 Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >lua 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|. < 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 Table with possible values for |vim.type_idx|. Contains two sets of
key-value pairs: first maps possible values for |vim.type_idx| to key-value pairs: first maps possible values for |vim.type_idx| to
human-readable strings, second maps human-readable type names to values 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.WARN
vim.log.levels.OFF vim.log.levels.OFF
vim.empty_dict() *vim.empty_dict()* vim.empty_dict() *vim.empty_dict()*
Creates a special empty table (marked with a metatable), which Nvim Creates a special empty table (marked with a metatable), which Nvim
converts to an empty dictionary when translating Lua values to Vimscript 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 • {fast_only} (`boolean?`) If true, only |api-fast| events will be
processed. processed.
Return: ~ Return (multiple): ~
(`boolean, -1|-2?`) (`boolean`)
(`-1|-2?`)
• If {callback} returns `true` during the {time}: `true, nil` • If {callback} returns `true` during the {time}: `true, nil`
• If {callback} never returns `true` during the {time}: `false, -1` • If {callback} never returns `true` during the {time}: `false, -1`
• If {callback} is interrupted during the {time}: `false, -2` • 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* LUA-VIMSCRIPT BRIDGE *lua-vimscript*
Nvim Lua provides an interface or "bridge" to Vimscript variables and Nvim Lua provides an interface or "bridge" to Vimscript variables and
functions, and editor commands and options. functions, and editor commands and options.
Objects passed over this bridge are COPIED (marshalled): there are no Objects passed over this bridge are COPIED (marshalled): there are no
"references". |lua-guide-variables| For example, using `vim.fn.remove()` "references". |lua-guide-variables| For example, using `vim.fn.remove()` on a
on a Lua list copies the list object to Vimscript and does NOT modify the Lua list copies the list object to Vimscript and does NOT modify the Lua list: >lua
Lua list: >lua
local list = { 1, 2, 3 } local list = { 1, 2, 3 }
vim.fn.remove(list, 0) vim.fn.remove(list, 0)
vim.print(list) --> "{ 1, 2, 3 }" vim.print(list) --> "{ 1, 2, 3 }"
< <
vim.call({func}, {...}) *vim.call()* vim.call({func}, {...}) *vim.call()*
@ -1240,7 +1241,7 @@ vim.v *vim.v*
|v:| variables. |v:| variables.
Invalid or unset key returns `nil`. Invalid or unset key returns `nil`.
` ` *lua-options* *lua-options*
*lua-vim-options* *lua-vim-options*
*lua-vim-set* *lua-vim-set*
*lua-vim-setlocal* *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 |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
global value of a |global-local| option, see |:setglobal|. global value of a |global-local| option, see |:setglobal|.
` ` *vim.opt_local* *vim.opt_local*
*vim.opt_global* *vim.opt_global*
*vim.opt* *vim.opt*
A special interface |vim.opt| exists for conveniently interacting with list- 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 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_local`. Additionally, to replicate the behavior of |:setglobal|, use
`vim.opt_global`. `vim.opt_global`.
Option:append({value}) *vim.opt:append()* Option:append({value}) *vim.opt:append()*
Append a value to string-style options. See |:set+=| Append a value to string-style options. See |:set+=|
@ -1478,7 +1481,7 @@ vim.wo *vim.wo*
============================================================================== ==============================================================================
Lua module: vim *lua-vim* Lua module: vim *lua-vim*
vim.cmd *vim.cmd()* vim.cmd({command}) *vim.cmd()*
Executes Vim script commands. Executes Vim script commands.
Note that `vim.cmd` can be indexed with a command name to return a 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: ~ Return: ~
(`string?`) Deprecated message, or nil if no message was shown. (`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. Gets a human-readable representation of the given object.
Return: ~ Return: ~
@ -1580,12 +1583,15 @@ vim.keycode({str}) *vim.keycode()*
See also: ~ See also: ~
• |nvim_replace_termcodes()| • |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, Omnifunc for completing Lua values from the runtime Lua interpreter,
similar to the builtin completion for the `:lua` command. similar to the builtin completion for the `:lua` command.
Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer. 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()* vim.notify({msg}, {level}, {opts}) *vim.notify()*
Displays a notification to the user. 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. • {lines} (`string[]`) |readfile()|-style list of lines to paste.
|channel-lines| |channel-lines|
• {phase} (`-1|1|2|3`) -1: "non-streaming" paste: the call contains all • {phase} (`-1|1|2|3`) -1: "non-streaming" paste: the call contains all
lines. If paste is "streamed", `phase` indicates lines. If paste is "streamed", `phase` indicates the stream
the stream state: state:
• 1: starts the paste (exactly once) • 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times) • 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once) • 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' })) local hl_normal = vim.print(vim.api.nvim_get_hl(0, { name = 'Normal' }))
< <
Parameters: ~
• {...} (`any`)
Return: ~ Return: ~
(`any`) given arguments. (`any`) given arguments.
@ -1799,7 +1808,6 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
• signal: (integer) • signal: (integer)
• stdout: (string), nil if stdout argument is passed • stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed • stderr: (string), nil if stderr argument is passed
• kill (fun(signal: integer|string)) • kill (fun(signal: integer|string))
• write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to • write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to
close the stream. 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()* vim.deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality Deep compare values for equality
Tables are compared recursively unless they both provide the `eq` metamethod. Tables are compared recursively unless they both provide the `eq`
All other types are compared using the equality `==` operator. metamethod. All other types are compared using the equality `==` operator.
Parameters: ~ Parameters: ~
• {a} (`any`) First value • {a} (`any`) First value
@ -1999,12 +2028,12 @@ vim.list_slice({list}, {start}, {finish}) *vim.list_slice()*
(inclusive) (inclusive)
Parameters: ~ Parameters: ~
• {list} (`list`) Table • {list} (`any[]`) Table
• {start} (`integer?`) Start range of slice • {start} (`integer?`) Start range of slice
• {finish} (`integer?`) End range of slice • {finish} (`integer?`) End range of slice
Return: ~ 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()* vim.pesc({s}) *vim.pesc()*
Escapes magic chars in |lua-patterns|. Escapes magic chars in |lua-patterns|.
@ -2037,7 +2066,6 @@ vim.ringbuf({size}) *vim.ringbuf()*
< <
Returns a Ringbuf instance with the following methods: Returns a Ringbuf instance with the following methods:
• |Ringbuf:push()| • |Ringbuf:push()|
• |Ringbuf:pop()| • |Ringbuf:pop()|
• |Ringbuf:peek()| • |Ringbuf:peek()|
@ -2049,27 +2077,6 @@ vim.ringbuf({size}) *vim.ringbuf()*
Return: ~ Return: ~
(`table`) (`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()* vim.spairs({t}) *vim.spairs()*
Enumerates key-value pairs of a table, ordered by key. 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 (`function`) |for-in| iterator over sorted keys and their values
See also: ~ 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()* vim.split({s}, {sep}, {opts}) *vim.split()*
Splits a string at each instance of a separator and returns the result as 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. Merges recursively two or more tables.
Parameters: ~ Parameters: ~
• {behavior} (`string`) Decides what to do if a key is found in more • {behavior} (`"error"|"keep"|"force"`) (string) Decides what to do if
than one map: a key is found in more than one map:
• "error": raise an error • "error": raise an error
• "keep": use value from the leftmost map • "keep": use value from the leftmost map
• "force": use value from the rightmost map • "force": use value from the rightmost map
@ -2209,7 +2217,7 @@ vim.tbl_filter({func}, {t}) *vim.tbl_filter()*
• {t} (`table`) Table • {t} (`table`) Table
Return: ~ Return: ~
(`table`) Table of filtered values (`any[]`) Table of filtered values
vim.tbl_flatten({t}) *vim.tbl_flatten()* vim.tbl_flatten({t}) *vim.tbl_flatten()*
Creates a copy of a list-like table such that any nested tables are 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 (`table`) Flattened copy of the given list-like table
See also: ~ 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()* vim.tbl_get({o}, {...}) *vim.tbl_get()*
Index into a table (first argument) via string keys passed as subsequent 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 • {t} (`table`) Table
Return: ~ Return: ~
(`list`) List of keys (`any[]`) List of keys
See also: ~ 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()* vim.tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table. Apply a function to all values of a table.
@ -2321,7 +2331,7 @@ vim.tbl_values({t}) *vim.tbl_values()*
• {t} (`table`) Table • {t} (`table`) Table
Return: ~ Return: ~
(`list`) List of values (`any[]`) List of values
vim.trim({s}) *vim.trim()* vim.trim({s}) *vim.trim()*
Trim whitespace (Lua pattern "%s") from both sides of a string. 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", "string", "s", "number", "n", "boolean", "b", "function",
"f", "nil", "thread", "userdata") or list of them. "f", "nil", "thread", "userdata") or list of them.
• optional: (optional) boolean, if true, `nil` is valid • optional: (optional) boolean, if true, `nil` is valid
2. (arg_value, fn, msg) 2. (arg_value, fn, msg)
• arg_value: argument value • arg_value: argument value
• fn: any function accepting one argument, returns true if • 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`) first one (defaults to `false`)
Return: ~ 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 • modpath: (string) the path to the module
• modname: (string) the name of the module • modname: (string) the name of the module
• stat: (table|nil) the fs_stat of the module path. Won't be returned • 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', ['/etc/foo/config'] = 'toml',
}, },
pattern = { pattern = {
['.*&zwj;/etc/foo/.*'] = 'fooscript', ['.*/etc/foo/.*'] = 'fooscript',
-- Using an optional priority -- Using an optional priority
['.*&zwj;/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } }, ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
-- A pattern containing an environment variable -- A pattern containing an environment variable
['${XDG_CONFIG_HOME}/foo/git'] = 'git', ['${XDG_CONFIG_HOME}/foo/git'] = 'git',
['README.(%a+)$'] = function(path, bufnr, ext) ['README.(%a+)$'] = function(path, bufnr, ext)
@ -2756,9 +2765,11 @@ vim.keymap.del({modes}, {lhs}, {opts}) *vim.keymap.del()*
< <
Parameters: ~ Parameters: ~
• {opts} (`table?`) A table of optional arguments: • {modes} (`string|string[]`)
• "buffer": (integer|boolean) Remove a mapping from the given • {lhs} (`string`)
buffer. When `0` or `true`, use the current buffer. • {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: ~ See also: ~
• |vim.keymap.set()| • |vim.keymap.set()|
@ -2789,7 +2800,6 @@ vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
• Same as |nvim_set_keymap()| {opts}, except: • Same as |nvim_set_keymap()| {opts}, except:
• "replace_keycodes" defaults to `true` if "expr" is `true`. • "replace_keycodes" defaults to `true` if "expr" is `true`.
• "noremap": inverse of "remap" (see below). • "noremap": inverse of "remap" (see below).
• Also accepts: • Also accepts:
• "buffer": (integer|boolean) Creates buffer-local mapping, • "buffer": (integer|boolean) Creates buffer-local mapping,
`0` or `true` for current buffer. `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()* vim.glob.to_lpeg({pattern}) *vim.glob.to_lpeg()*
Parses a raw glob into an |lua-lpeg| pattern. 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: Glob patterns can have the following syntax:
• `*` to match one or more characters in a path segment • `*` 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| In addition, its regex-like interface is available as |vim.re|
(https://www.inf.puc-rio.br/~roberto/lpeg/re.html). (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()* vim.lpeg.B({pattern}) *vim.lpeg.B()*
Returns a pattern that matches only if the input string at the current Returns a pattern that matches only if the input string at the current
position is preceded by `patt`. Pattern `patt` must match only strings 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()* vim.lpeg.Carg({n}) *vim.lpeg.Carg()*
Creates an argument capture. This pattern matches the empty string and 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: ~ Parameters: ~
• {n} (`integer`) • {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. the group name as its key. The captured value is only the table.
Parameters: ~ Parameters: ~
• {patt} (vim.lpeg.Pattern |' `) @return (` vim.lpeg.Capture`) • {patt} (`vim.lpeg.Pattern|''`)
vim.lpeg.lpeg *vim.lpeg()* Return: ~
LPeg is a new pattern-matching library for Lua, based on Parsing Expression (`vim.lpeg.Capture`)
Grammars (PEGs).
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()* vim.lpeg.match({pattern}, {subject}, {init}) *vim.lpeg.match()*
Matches the given `pattern` against the `subject` string. If the match Matches the given `pattern` against the `subject` string. If the match
@ -3252,33 +3322,6 @@ vim.lpeg.P({value}) *vim.lpeg.P()*
Return: ~ Return: ~
(`vim.lpeg.Pattern`) (`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()* vim.lpeg.R({...}) *vim.lpeg.R()*
Returns a pattern that matches any single character belonging to one of 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 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()* vim.lpeg.S({string}) *vim.lpeg.S()*
Returns a pattern that matches any single character that appears in the Returns a pattern that matches any single character that appears in the
given string (the `S` stands for Set). As an example, the pattern given string (the `S` stands for Set). As an example, the pattern
`lpeg.S("+-*&zwj;/")` matches any arithmetic operator. Note that, if `s` `lpeg.S("+-*/")` matches any arithmetic operator. Note that, if `s` is a
is a character (that is, a string of length 1), then `lpeg.P(s)` is character (that is, a string of length 1), then `lpeg.P(s)` is equivalent
equivalent to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also that both
that both `lpeg.S("")` and `lpeg.R()` are patterns that always fail. `lpeg.S("")` and `lpeg.R()` are patterns that always fail.
Parameters: ~ Parameters: ~
• {string} (`string`) • {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 Returns the string `"pattern"` if the given value is a pattern, otherwise
`nil`. `nil`.
Parameters: ~
• {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~ Return: ~
(`"pattern"?`) (`"pattern"?`)
@ -3357,13 +3403,13 @@ vim.lpeg.version() *vim.lpeg.version()*
============================================================================== ==============================================================================
VIM.RE *vim.re* VIM.RE *vim.re*
The `vim.re` module provides a conventional regex-like syntax for pattern
The `vim.re` module provides a conventional regex-like syntax for pattern usage usage within LPeg |vim.lpeg|.
within LPeg |vim.lpeg|.
See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
documentation including regex syntax and more concrete examples. documentation including regex syntax and more concrete examples.
vim.re.compile({string}, {defs}) *vim.re.compile()* vim.re.compile({string}, {defs}) *vim.re.compile()*
Compiles the given {string} and returns an equivalent LPeg pattern. The Compiles the given {string} and returns an equivalent LPeg pattern. The
given string may define either an expression or a grammar. The optional 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: ~ See also: ~
• vim.lpeg.match() • vim.lpeg.match()
vim.re.updatelocale() *vim.re.updatelocale()*
Updates the pre-defined character classes to the current locale.
============================================================================== ==============================================================================
VIM.REGEX *vim.regex* 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()* *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} Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and {end}
are supplied, match only this byte index range. Otherwise see are supplied, match only this byte index range. Otherwise see
|regex:match_str()|. If {start} is used, then the returned byte indices |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?`) • {start} (`integer?`)
• {end_} (`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 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 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 there is no match, `nil` is returned. Because any integer is "truthy",
be directly used as a condition in an if-statement. `regex:match_str()` can be directly used as a condition in an
if-statement.
Parameters: ~ Parameters: ~
• {str} (`string`) • {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* Lua module: vim.secure *vim.secure*
@ -3508,29 +3557,23 @@ vim.secure.trust({opts}) *vim.secure.trust()*
============================================================================== ==============================================================================
Lua module: vim.version *vim.version* Lua module: vim.version *vim.version*
The `vim.version` module provides functions for comparing versions and ranges
The `vim.version` module provides functions for comparing versions and conforming to the https://semver.org spec. Plugins, and plugin managers, can
ranges conforming to the use this to check available tools and dependencies on the current system.
https://semver.org
spec. Plugins, and plugin managers, can use this to check available tools
and dependencies on the current system.
Example: >lua Example: >lua
local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false}) local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
if vim.version.gt(v, {3, 2, 0}) then if vim.version.gt(v, {3, 2, 0}) then
-- ... -- ...
end 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 A version "range spec" defines a semantic version range which can be tested
tested against a version, using |vim.version.range()|. against a version, using |vim.version.range()|.
Supported range specs are shown in the following table. Note: suffixed Supported range specs are shown in the following table. Note: suffixed
versions (1.2.3-rc1) are not matched. > 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). Partial left: missing pieces treated as 0 (1.2 => 1.2.0).
1.2 - 2.3.0 is 1.2.0 - 2.3.0 1.2 - 2.3.0 is 1.2.0 - 2.3.0
< <
vim.version.cmp({v1}, {v2}) *vim.version.cmp()* vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parses and compares two version objects (the result of Parses and compares two version objects (the result of
|vim.version.parse()|, or specified literally as a `{major, minor, patch}` |vim.version.parse()|, or specified literally as a `{major, minor, patch}`
@ -3586,14 +3629,14 @@ vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parameters: ~ Parameters: ~
• {v1} (`Version|number[]|string`) Version object. • {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: ~ Return: ~
(`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`. (`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
vim.version.eq({v1}, {v2}) *vim.version.eq()* vim.version.eq({v1}, {v2}) *vim.version.eq()*
Returns `true` if the given versions are equal. See |vim.version.cmp()| for Returns `true` if the given versions are equal. See |vim.version.cmp()|
usage. for usage.
Parameters: ~ Parameters: ~
• {v1} (`Version|number[]|string`) • {v1} (`Version|number[]|string`)
@ -3603,7 +3646,7 @@ vim.version.eq({v1}, {v2}) *vim.version.eq()*
(`boolean`) (`boolean`)
vim.version.ge({v1}, {v2}) *vim.version.ge()* 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: ~ Parameters: ~
• {v1} (`Version|number[]|string`) • {v1} (`Version|number[]|string`)
@ -3613,7 +3656,7 @@ vim.version.ge({v1}, {v2}) *vim.version.ge()*
(`boolean`) (`boolean`)
vim.version.gt({v1}, {v2}) *vim.version.gt()* 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: ~ Parameters: ~
• {v1} (`Version|number[]|string`) • {v1} (`Version|number[]|string`)
@ -3632,7 +3675,7 @@ vim.version.last({versions}) *vim.version.last()*
(`Version?`) (`Version?`)
vim.version.le({v1}, {v2}) *vim.version.le()* 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: ~ Parameters: ~
• {v1} (`Version|number[]|string`) • {v1} (`Version|number[]|string`)
@ -3642,7 +3685,7 @@ vim.version.le({v1}, {v2}) *vim.version.le()*
(`boolean`) (`boolean`)
vim.version.lt({v1}, {v2}) *vim.version.lt()* 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: ~ Parameters: ~
• {v1} (`Version|number[]|string`) • {v1} (`Version|number[]|string`)
@ -3671,7 +3714,7 @@ vim.version.parse({version}, {opts}) *vim.version.parse()*
invalid. invalid.
See also: ~ 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()* vim.version.range({spec}) *vim.version.range()*
Parses a semver |version-range| "spec" and returns a range object: > 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" • {spec} (`string`) Version range "spec"
See also: ~ See also: ~
# https://github.com/npm/node-semver#ranges • https://github.com/npm/node-semver#ranges
============================================================================== ==============================================================================
Lua module: vim.iter *vim.iter* Lua module: vim.iter *vim.iter*
*vim.iter()* is an interface for |iterable|s: it wraps a table or function *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 argument into an *Iter* object with methods (such as |Iter:filter()| and
|Iter:map()|) that transform the underlying source data. These methods can |Iter:map()|) that transform the underlying source data. These methods can be
be chained to create iterator "pipelines": the output of each pipeline chained to create iterator "pipelines": the output of each pipeline stage is
stage is input to the next stage. The first stage depends on the type input to the next stage. The first stage depends on the type passed to
passed to `vim.iter()`: `vim.iter()`:
• List tables (arrays, |lua-list|) yield only the value of each element. • List tables (arrays, |lua-list|) yield only the value of each element.
• Use |Iter:enumerate()| to also pass the index to the next stage. • Use |Iter:enumerate()| to also pass the index to the next stage.
• Or initialize with ipairs(): `vim.iter(ipairs(…))`. • Or initialize with ipairs(): `vim.iter(ipairs(…))`.
• Non-list tables (|lua-dict|) yield both the key and value of each element.
• Non-list tables (|lua-dict|) yield both the key and value of each • Function |iterator|s yield all values returned by the underlying function.
element.
• Function |iterator|s yield all values returned by the underlying
function.
• Tables with a |__call()| metamethod are treated as function iterators. • Tables with a |__call()| metamethod are treated as function iterators.
The iterator pipeline terminates when the underlying |iterable| is The iterator pipeline terminates when the underlying |iterable| is exhausted
exhausted (for function iterators this means it returned nil). (for function iterators this means it returned nil).
Note: `vim.iter()` scans table input to decide if it is a list or a dict; Note: `vim.iter()` scans table input to decide if it is a list or a dict; to
to avoid this cost you can wrap the table with an iterator e.g. avoid this cost you can wrap the table with an iterator e.g.
`vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator| `vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator|
operations such as |Iter:rev()|). operations such as |Iter:rev()|).
@ -3771,13 +3809,13 @@ Examples: >lua
rb:push("b") rb:push("b")
vim.iter(rb):totable() vim.iter(rb):totable()
-- { "a", "b" } -- { "a", "b" }
< <
In addition to the |vim.iter()| function, the |vim.iter| module provides In addition to the |vim.iter()| function, the |vim.iter| module provides
convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. 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 Filters a table or other |iterable|. >lua
-- Equivalent to: -- Equivalent to:
vim.iter(src):filter(f):totable() vim.iter(src):filter(f):totable()
@ -3839,11 +3877,11 @@ Iter:enumerate() *Iter:enumerate()*
Example: >lua Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate() local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next() it:next()
-- 1 'a' -- 1 'a'
it:next() it:next()
-- 2 'b' -- 2 'b'
it:next() it:next()
-- 3 'c' -- 3 'c'
< <
Return: ~ Return: ~
@ -3884,6 +3922,9 @@ Iter:find({f}) *Iter:find()*
-- 12 -- 12
< <
Parameters: ~
• {f} (`any`)
Return: ~ Return: ~
(`any`) (`any`)
@ -3926,7 +3967,7 @@ Iter:fold({init}, {f}) *Iter:fold()*
Parameters: ~ Parameters: ~
• {init} (`any`) Initial value of the accumulator. • {init} (`any`) Initial value of the accumulator.
• {f} (`fun(acc:any, ...):any`) Accumulation function. • {f} (`fun(acc:A, ...):A`) Accumulation function.
Return: ~ Return: ~
(`any`) (`any`)
@ -4105,11 +4146,14 @@ Iter:rfind({f}) *Iter:rfind()*
Examples: >lua Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate() local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1) it:rfind(1)
-- 5 1 -- 5 1
it:rfind(1) it:rfind(1)
-- 1 1 -- 1 1
< <
Parameters: ~
• {f} (`any`)
Return: ~ Return: ~
(`any`) (`any`)
@ -4205,7 +4249,7 @@ Iter:totable() *Iter:totable()*
Return: ~ Return: ~
(`table`) (`table`)
map({f}, {src}, {...}) *vim.iter.map()* map({f}, {src}) *vim.iter.map()*
Maps a table or other |iterable|. >lua Maps a table or other |iterable|. >lua
-- Equivalent to: -- Equivalent to:
vim.iter(src):map(f):totable() vim.iter(src):map(f):totable()
@ -4223,7 +4267,7 @@ map({f}, {src}, {...}) *vim.iter.map()*
See also: ~ See also: ~
• |Iter:map()| • |Iter:map()|
totable({f}, {...}) *vim.iter.totable()* totable({f}) *vim.iter.totable()*
Collects an |iterable| into a table. >lua Collects an |iterable| into a table. >lua
-- Equivalent to: -- Equivalent to:
vim.iter(f):totable() vim.iter(f):totable()
@ -4249,8 +4293,9 @@ vim.snippet.exit() *vim.snippet.exit()*
Exits the current snippet. Exits the current snippet.
vim.snippet.expand({input}) *vim.snippet.expand()* 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 Expands the given snippet text. Refer to
the specification of valid input. https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax
for the specification of valid input.
Tabstops are highlighted with hl-SnippetTabstop. Tabstops are highlighted with hl-SnippetTabstop.
@ -4317,4 +4362,5 @@ vim.text.hexencode({str}) *vim.text.hexencode()*
Return: ~ Return: ~
(`string`) Hex encoded string (`string`) Hex encoded string
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@ -933,6 +933,7 @@ get_filetypes({lang}) *vim.treesitter.language.get_filetypes()*
(`string[]`) filetypes (`string[]`) filetypes
get_lang({filetype}) *vim.treesitter.language.get_lang()* get_lang({filetype}) *vim.treesitter.language.get_lang()*
Parameters: ~ Parameters: ~
• {filetype} (`string`) • {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} Use |treesitter-parsers| in runtimepath to check the query file in {buf}
for errors: for errors:
• verify that used nodes are valid identifiers in the grammar. • verify that used nodes are valid identifiers in the grammar.
• verify that predicates and directives are valid. • verify that predicates and directives are valid.
• verify that top-level s-expressions are valid. • verify that top-level s-expressions are valid.
The found diagnostics are reported using |diagnostic-api|. By default, the The found diagnostics are reported using |diagnostic-api|. By default, the
parser used for verification is determined by the containing folder of 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. for the `lua` language will be used.
Parameters: ~ Parameters: ~
@ -1093,6 +1093,10 @@ omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()*
vim.bo.omnifunc = 'v:lua.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({lang}, {query}) *vim.treesitter.query.parse()*
Parse {query} as a string. (If the query is in a file, the caller should Parse {query} as a string. (If the query is in a file, the caller should
read the contents into a string before calling). 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* 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 To create a LanguageTree (parser object) for a given buffer and language, use: >lua
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
local parser = vim.treesitter.get_parser(bufnr, lang) local parser = vim.treesitter.get_parser(bufnr, lang)
< <
(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. (where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. Note:
Note: currently the parser is retained for the lifetime of a buffer but currently the parser is retained for the lifetime of a buffer but this may
this may change; a plugin should keep a reference to the parser object if change; a plugin should keep a reference to the parser object if it wants
it wants incremental updates. incremental updates.
Whenever you need to access the current syntax tree, parse the buffer: >lua Whenever you need to access the current syntax tree, parse the buffer: >lua
local tree = parser:parse({ start_row, end_row }) local tree = parser:parse({ start_row, end_row })
< <
This returns a table of immutable |treesitter-tree| objects representing This returns a table of immutable |treesitter-tree| objects representing the
the current state of the buffer. When the plugin wants to access the state current state of the buffer. When the plugin wants to access the state after a
after a (possible) edit it must call `parse()` again. If the buffer wasn't (possible) edit it must call `parse()` again. If the buffer wasn't edited, the
edited, the same tree will be returned again without extra work. If the same tree will be returned again without extra work. If the buffer was parsed
buffer was parsed before, incremental parsing will be done of the changed before, incremental parsing will be done of the changed parts.
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()* LanguageTree:children() *LanguageTree:children()*
Returns a map of language to child tree. 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)`) • {fn} (`fun(tree: TSTree, ltree: LanguageTree)`)
LanguageTree:included_regions() *LanguageTree:included_regions()* 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 different from the regions set by injection query, because a partial
|LanguageTree:parse()| drops the regions outside the requested range. |LanguageTree:parse()| drops the regions outside the requested range.
@ -1405,4 +1403,5 @@ LanguageTree:trees() *LanguageTree:trees()*
Return: ~ Return: ~
(`table<integer, TSTree>`) (`table<integer, TSTree>`)
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@ -127,10 +127,10 @@ vim.log = {
--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot --- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
--- be called in |api-fast|. --- be called in |api-fast|.
--- - SystemCompleted is an object with the fields: --- - SystemCompleted is an object with the fields:
--- - code: (integer) --- - code: (integer)
--- - signal: (integer) --- - signal: (integer)
--- - stdout: (string), nil if stdout argument is passed --- - stdout: (string), nil if stdout argument is passed
--- - stderr: (string), nil if stderr argument is passed --- - stderr: (string), nil if stderr argument is passed
--- - kill (fun(signal: integer|string)) --- - kill (fun(signal: integer|string))
--- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream. --- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream.
--- - is_closing (fun(): boolean) --- - is_closing (fun(): boolean)
@ -706,8 +706,8 @@ end
--- Generates a list of possible completions for the string. --- Generates a list of possible completions for the string.
--- String has the pattern. --- String has the pattern.
--- ---
--- 1. Can we get it to just return things in the global namespace with that name prefix --- 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. --- 2. Can we get it to return things from global namespace even with `print(` in front.
--- ---
--- @param pat string --- @param pat string
function vim._expand_pat(pat, env) function vim._expand_pat(pat, env)
@ -885,6 +885,7 @@ do
--- similar to the builtin completion for the `:lua` command. --- similar to the builtin completion for the `:lua` command.
--- ---
--- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer. --- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer.
--- @param find_start 1|0
function vim.lua_omnifunc(find_start, _) function vim.lua_omnifunc(find_start, _)
if find_start == 1 then if find_start == 1 then
local line = vim.api.nvim_get_current_line() local line = vim.api.nvim_get_current_line()
@ -914,6 +915,7 @@ end
--- ---
--- @see |vim.inspect()| --- @see |vim.inspect()|
--- @see |:=| --- @see |:=|
--- @param ... any
--- @return any # given arguments. --- @return any # given arguments.
function vim.print(...) function vim.print(...)
if vim.in_fast_event() then if vim.in_fast_event() then

View File

@ -17,7 +17,7 @@ local defaults = {
---@param bufnr? integer defaults to the current buffer ---@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 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 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) --- - syntax (boolean): include syntax based highlight groups (defaults to true)
--- - treesitter (boolean): include treesitter 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) --- - 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 bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@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 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) function vim.show_pos(bufnr, row, col, filter)
local items = vim.inspect_pos(bufnr, row, col, filter) local items = vim.inspect_pos(bufnr, row, col, filter)

File diff suppressed because it is too large Load Diff

View File

@ -3,65 +3,63 @@
error('Cannot require a meta file') 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()))
--- ---
---@brief <pre>help --- vim.NIL *vim.NIL*
---vim.api.{func}({...}) *vim.api* --- Special value representing NIL in |RPC| and |v:null| in Vimscript
--- Invokes Nvim |API| function {func} with arguments {...}. --- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
--- Example: call the "nvim_get_current_line()" API function: >lua --- table representing a Dictionary or Array, because it is treated as
--- print(tostring(vim.api.nvim_get_current_line())) --- missing: `{"foo", nil}` is the same as `{"foo"}`.
--- ---
---vim.NIL *vim.NIL* --- vim.type_idx *vim.type_idx*
--- Special value representing NIL in |RPC| and |v:null| in Vimscript --- Type index for use in |lua-special-tbl|. Specifying one of the values from
--- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua --- |vim.types| allows typing the empty table (it is unclear whether empty Lua
--- table representing a Dictionary or Array, because it is treated as --- table represents empty list or empty array) and forcing integral numbers
--- missing: `{"foo", nil}` is the same as `{"foo"}`. --- to be |Float|. See |lua-special-tbl| for more details.
--- ---
---vim.type_idx *vim.type_idx* --- vim.val_idx *vim.val_idx*
--- Type index for use in |lua-special-tbl|. Specifying one of the values from --- Value index for tables representing |Float|s. A table representing
--- |vim.types| allows typing the empty table (it is unclear whether empty Lua --- floating-point value 1.0 looks like this: >lua
--- table represents empty list or empty array) and forcing integral numbers --- {
--- to be |Float|. See |lua-special-tbl| for more details. --- [vim.type_idx] = vim.types.float,
--- [vim.val_idx] = 1.0,
--- }
--- < See also |vim.type_idx| and |lua-special-tbl|.
--- ---
---vim.val_idx *vim.val_idx* --- vim.types *vim.types*
--- Value index for tables representing |Float|s. A table representing --- Table with possible values for |vim.type_idx|. Contains two sets of
--- floating-point value 1.0 looks like this: >lua --- key-value pairs: first maps possible values for |vim.type_idx| to
--- { --- human-readable strings, second maps human-readable type names to values
--- [vim.type_idx] = vim.types.float, --- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
--- [vim.val_idx] = 1.0, --- `dictionary` types.
--- }
---< See also |vim.type_idx| and |lua-special-tbl|.
--- ---
---vim.types *vim.types* --- Note: One must expect that values corresponding to `vim.types.float`,
--- Table with possible values for |vim.type_idx|. Contains two sets of --- `vim.types.array` and `vim.types.dictionary` fall under only two following
--- key-value pairs: first maps possible values for |vim.type_idx| to --- assumptions:
--- human-readable strings, second maps human-readable type names to values --- 1. Value may serve both as a key and as a value in a table. Given the
--- for |vim.type_idx|. Currently contains pairs for `float`, `array` and --- properties of Lua tables this basically means “value is not `nil`”.
--- `dictionary` types. --- 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.
--- ---
--- Note: One must expect that values corresponding to `vim.types.float`, --- *log_levels* *vim.log.levels*
--- `vim.types.array` and `vim.types.dictionary` fall under only two following --- Log levels are one of the values defined in `vim.log.levels`:
--- 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* --- vim.log.levels.DEBUG
---Log levels are one of the values defined in `vim.log.levels`: --- vim.log.levels.ERROR
--- vim.log.levels.INFO
--- vim.log.levels.TRACE
--- vim.log.levels.WARN
--- vim.log.levels.OFF
--- ---
--- vim.log.levels.DEBUG --- </pre>
--- vim.log.levels.ERROR
--- vim.log.levels.INFO
--- vim.log.levels.TRACE
--- vim.log.levels.WARN
--- vim.log.levels.OFF
---
---</pre>
---@class vim.NIL ---@class vim.NIL

View File

@ -5,7 +5,7 @@ vim.json = {}
-- luacheck: no unused args -- luacheck: no unused args
---@defgroup vim.json ---@brief
--- ---
--- This module provides encoding and decoding of Lua objects to and --- This module provides encoding and decoding of Lua objects to and
--- from JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. --- from JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.

View File

@ -5,22 +5,20 @@ error('Cannot require a meta file')
-- (based on revision 4aded588f9531d89555566bb1de27490354b91c7) -- (based on revision 4aded588f9531d89555566bb1de27490354b91c7)
-- with types being renamed to include the vim namespace and with some descriptions made less verbose. -- with types being renamed to include the vim namespace and with some descriptions made less verbose.
---@defgroup vim.lpeg --- @brief <pre>help
---<pre>help --- LPeg is a pattern-matching library for Lua, based on
---LPeg is a pattern-matching library for Lua, based on --- Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
---Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
--- ---
--- *lua-lpeg* --- *lua-lpeg*
--- *vim.lpeg.Pattern* --- *vim.lpeg.Pattern*
---The LPeg library for parsing expression grammars is included as `vim.lpeg` --- The LPeg library for parsing expression grammars is included as `vim.lpeg`
---(https://www.inf.puc-rio.br/~roberto/lpeg/). --- (https://www.inf.puc-rio.br/~roberto/lpeg/).
--- ---
---In addition, its regex-like interface is available as |vim.re| --- In addition, its regex-like interface is available as |vim.re|
---(https://www.inf.puc-rio.br/~roberto/lpeg/re.html). --- (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 = {} vim.lpeg = {}
--- @class vim.lpeg.Pattern --- @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`. --- 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 --- @return "pattern"|nil
function vim.lpeg.type(value) end function vim.lpeg.type(value) end

View File

@ -2,14 +2,17 @@
-- luacheck: no unused args -- luacheck: no unused args
--- @defgroup vim.mpack --- @brief
--- ---
--- This module provides encoding and decoding of Lua objects to and --- This module provides encoding and decoding of Lua objects to and
--- from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|. --- from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
--- Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object. --- Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
--- @param str string --- @param str string
--- @return any
function vim.mpack.decode(str) end function vim.mpack.decode(str) end
--- Encodes (or "packs") Lua object {obj} as msgpack in a Lua string. --- Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
--- @param obj any
--- @return string
function vim.mpack.encode(obj) end function vim.mpack.encode(obj) end

View File

@ -7,15 +7,12 @@ error('Cannot require a meta file')
-- Copyright © 2007-2023 Lua.org, PUC-Rio. -- Copyright © 2007-2023 Lua.org, PUC-Rio.
-- See 'lpeg.html' for license -- See 'lpeg.html' for license
--- @defgroup vim.re --- @brief
---<pre>help --- The `vim.re` module provides a conventional regex-like syntax for pattern usage
---The `vim.re` module provides a conventional regex-like syntax for pattern usage --- within LPeg |vim.lpeg|.
---within LPeg |vim.lpeg|.
--- ---
---See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original --- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
---documentation including regex syntax and more concrete examples. --- documentation including regex syntax and more concrete examples.
---
---</pre>
--- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define --- 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 --- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used

View File

@ -2,8 +2,6 @@
-- luacheck: no unused args -- luacheck: no unused args
--- @defgroup vim.regex
---
--- @brief Vim regexes can be used directly from Lua. Currently they only allow --- @brief Vim regexes can be used directly from Lua. Currently they only allow
--- matching within a single line. --- matching within a single line.

View File

@ -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 --- Objects passed over this bridge are COPIED (marshalled): there are no
---functions, and editor commands and options. --- "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
---Objects passed over this bridge are COPIED (marshalled): there are no --- list:
---"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 --- ```lua
--- local list = { 1, 2, 3 } --- local list = { 1, 2, 3 }
@ -14,86 +12,85 @@
--- vim.print(list) --> "{ 1, 2, 3 }" --- vim.print(list) --> "{ 1, 2, 3 }"
--- ``` --- ```
---@addtogroup lua-vimscript --- @brief <pre>help
---@brief <pre>help --- vim.call({func}, {...}) *vim.call()*
---vim.call({func}, {...}) *vim.call()* --- Invokes |vim-function| or |user-function| {func} with arguments {...}.
--- Invokes |vim-function| or |user-function| {func} with arguments {...}. --- See also |vim.fn|.
--- See also |vim.fn|. --- Equivalent to: >lua
--- Equivalent to: >lua --- vim.fn[func]({...})
--- vim.fn[func]({...}) --- <
---< --- vim.cmd({command})
---vim.cmd({command}) --- See |vim.cmd()|.
--- See |vim.cmd()|.
--- ---
---vim.fn.{func}({...}) *vim.fn* --- vim.fn.{func}({...}) *vim.fn*
--- Invokes |vim-function| or |user-function| {func} with arguments {...}. --- Invokes |vim-function| or |user-function| {func} with arguments {...}.
--- To call autoload functions, use the syntax: >lua --- To call autoload functions, use the syntax: >lua
--- vim.fn['some\#function']({...}) --- vim.fn['some#function']({...})
---< --- <
--- Unlike vim.api.|nvim_call_function()| this converts directly between Vim --- 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 --- 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 --- represented directly as a Lua number. Empty lists and dictionaries both
--- are represented by an empty table. --- are represented by an empty table.
--- ---
--- Note: |v:null| values as part of the return value is represented as --- Note: |v:null| values as part of the return value is represented as
--- |vim.NIL| special value --- |vim.NIL| special value
--- ---
--- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only --- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
--- enumerates functions that were called at least once. --- enumerates functions that were called at least once.
--- ---
--- Note: The majority of functions cannot run in |api-fast| callbacks with some --- Note: The majority of functions cannot run in |api-fast| callbacks with some
--- undocumented exceptions which are allowed. --- undocumented exceptions which are allowed.
--- ---
--- *lua-vim-variables* --- *lua-vim-variables*
---The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed --- The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
---from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables --- from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
---described below. In this way you can easily read and modify global Vimscript --- described below. In this way you can easily read and modify global Vimscript
---variables from Lua. --- variables from Lua.
--- ---
---Example: >lua --- Example: >lua
--- ---
--- vim.g.foo = 5 -- Set the g:foo Vimscript variable. --- vim.g.foo = 5 -- Set the g:foo Vimscript variable.
--- print(vim.g.foo) -- Get and print 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.g.foo = nil -- Delete (:unlet) the Vimscript variable.
--- vim.b[2].foo = 6 -- Set b:foo for buffer 2 --- vim.b[2].foo = 6 -- Set b:foo for buffer 2
---< --- <
--- ---
---Note that setting dictionary fields directly will not write them back into --- 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. --- 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 --- Instead the whole dictionary must be written as one. This can be achieved by
---creating a short-lived temporary. --- creating a short-lived temporary.
--- ---
---Example: >lua --- Example: >lua
--- ---
--- vim.g.my_dict.field1 = 'value' -- Does not work --- vim.g.my_dict.field1 = 'value' -- Does not work
--- ---
--- local my_dict = vim.g.my_dict -- --- local my_dict = vim.g.my_dict --
--- my_dict.field1 = 'value' -- Instead do --- my_dict.field1 = 'value' -- Instead do
--- vim.g.my_dict = my_dict -- --- vim.g.my_dict = my_dict --
--- ---
---vim.g *vim.g* --- vim.g *vim.g*
--- Global (|g:|) editor variables. --- Global (|g:|) editor variables.
--- Key with no value returns `nil`. --- Key with no value returns `nil`.
--- ---
---vim.b *vim.b* --- vim.b *vim.b*
--- Buffer-scoped (|b:|) variables for the current buffer. --- Buffer-scoped (|b:|) variables for the current buffer.
--- Invalid or unset key returns `nil`. Can be indexed with --- Invalid or unset key returns `nil`. Can be indexed with
--- an integer to access variables for a specific buffer. --- an integer to access variables for a specific buffer.
--- ---
---vim.w *vim.w* --- vim.w *vim.w*
--- Window-scoped (|w:|) variables for the current window. --- Window-scoped (|w:|) variables for the current window.
--- Invalid or unset key returns `nil`. Can be indexed with --- Invalid or unset key returns `nil`. Can be indexed with
--- an integer to access variables for a specific window. --- an integer to access variables for a specific window.
--- ---
---vim.t *vim.t* --- vim.t *vim.t*
--- Tabpage-scoped (|t:|) variables for the current tabpage. --- Tabpage-scoped (|t:|) variables for the current tabpage.
--- Invalid or unset key returns `nil`. Can be indexed with --- Invalid or unset key returns `nil`. Can be indexed with
--- an integer to access variables for a specific tabpage. --- an integer to access variables for a specific tabpage.
--- ---
---vim.v *vim.v* --- vim.v *vim.v*
--- |v:| variables. --- |v:| variables.
--- Invalid or unset key returns `nil`. --- Invalid or unset key returns `nil`.
---</pre> --- </pre>
local api = vim.api local api = vim.api
@ -142,7 +139,6 @@ end
--- vim.env.FOO = 'bar' --- vim.env.FOO = 'bar'
--- print(vim.env.TERM) --- print(vim.env.TERM)
--- ``` --- ```
---
---@param var string ---@param var string
vim.env = setmetatable({}, { vim.env = setmetatable({}, {
__index = function(_, k) __index = function(_, k)
@ -205,31 +201,30 @@ local function new_win_opt_accessor(winid, bufnr)
}) })
end end
---@addtogroup lua-vimscript --- @brief <pre>help
---@brief <pre>help --- *lua-options*
---` ` *lua-options* --- *lua-vim-options*
--- *lua-vim-options* --- *lua-vim-set*
--- *lua-vim-set* --- *lua-vim-setlocal*
--- *lua-vim-setlocal*
--- ---
---Vim options can be accessed through |vim.o|, which behaves like Vimscript --- Vim options can be accessed through |vim.o|, which behaves like Vimscript
---|:set|. --- |:set|.
--- ---
--- Examples: ~ --- Examples: ~
--- ---
--- To set a boolean toggle: --- To set a boolean toggle:
--- Vimscript: `set number` --- Vimscript: `set number`
--- Lua: `vim.o.number = true` --- Lua: `vim.o.number = true`
--- ---
--- To set a string value: --- To set a string value:
--- Vimscript: `set wildignore=*.o,*.a,__pycache__` --- Vimscript: `set wildignore=*.o,*.a,__pycache__`
--- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'` --- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
--- ---
---Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and --- Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
---window-scoped options. Note that this must NOT be confused with --- window-scoped options. Note that this must NOT be confused with
---|local-options| and |:setlocal|. There is also |vim.go| that only accesses the --- |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
---global value of a |global-local| option, see |:setglobal|. --- global value of a |global-local| option, see |:setglobal|.
---</pre> --- </pre>
--- Get or set |options|. Like `:set`. Invalid key is an error. --- 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() vim.wo = new_win_opt_accessor()
---@brief [[
--- vim.opt, vim.opt_local and vim.opt_global implementation --- vim.opt, vim.opt_local and vim.opt_global implementation
--- ---
--- To be used as helpers for working with options within neovim. --- To be used as helpers for working with options within neovim.
--- For information on how to use, see :help vim.opt --- For information on how to use, see :help vim.opt
---
---@brief ]]
--- Preserves the order and does not mutate the original list --- Preserves the order and does not mutate the original list
local function remove_duplicate_values(t) local function remove_duplicate_values(t)
@ -739,74 +731,73 @@ local function create_option_accessor(scope)
}) })
end end
---@addtogroup lua-vimscript --- @brief <pre>help
---@brief <pre>help --- *vim.opt_local*
---` ` *vim.opt_local* --- *vim.opt_global*
--- *vim.opt_global* --- *vim.opt*
--- *vim.opt*
--- ---
--- ---
---A special interface |vim.opt| exists for conveniently interacting with list- --- 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 --- and map-style option from Lua: It allows accessing them as Lua tables and
---offers object-oriented method for adding and removing entries. --- offers object-oriented method for adding and removing entries.
--- ---
--- Examples: ~ --- Examples: ~
--- ---
--- The following methods of setting a list-style option are equivalent: --- The following methods of setting a list-style option are equivalent:
--- In Vimscript: >vim --- In Vimscript: >vim
--- set wildignore=*.o,*.a,__pycache__ --- set wildignore=*.o,*.a,__pycache__
---< --- <
--- In Lua using `vim.o`: >lua --- In Lua using `vim.o`: >lua
--- vim.o.wildignore = '*.o,*.a,__pycache__' --- vim.o.wildignore = '*.o,*.a,__pycache__'
---< --- <
--- In Lua using `vim.opt`: >lua --- In Lua using `vim.opt`: >lua
--- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' } --- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
---< --- <
--- To replicate the behavior of |:set+=|, use: >lua --- To replicate the behavior of |:set+=|, use: >lua
--- ---
--- vim.opt.wildignore:append { "*.pyc", "node_modules" } --- vim.opt.wildignore:append { "*.pyc", "node_modules" }
---< --- <
--- To replicate the behavior of |:set^=|, use: >lua --- To replicate the behavior of |:set^=|, use: >lua
--- ---
--- vim.opt.wildignore:prepend { "new_first_value" } --- vim.opt.wildignore:prepend { "new_first_value" }
---< --- <
--- To replicate the behavior of |:set-=|, use: >lua --- To replicate the behavior of |:set-=|, use: >lua
--- ---
--- vim.opt.wildignore:remove { "node_modules" } --- vim.opt.wildignore:remove { "node_modules" }
---< --- <
--- The following methods of setting a map-style option are equivalent: --- The following methods of setting a map-style option are equivalent:
--- In Vimscript: >vim --- In Vimscript: >vim
--- set listchars=space:_,tab:>~ --- set listchars=space:_,tab:>~
---< --- <
--- In Lua using `vim.o`: >lua --- In Lua using `vim.o`: >lua
--- vim.o.listchars = 'space:_,tab:>~' --- vim.o.listchars = 'space:_,tab:>~'
---< --- <
--- In Lua using `vim.opt`: >lua --- In Lua using `vim.opt`: >lua
--- vim.opt.listchars = { space = '_', tab = '>~' } --- vim.opt.listchars = { space = '_', tab = '>~' }
---< --- <
--- ---
---Note that |vim.opt| returns an `Option` object, not the value of the option, --- Note that |vim.opt| returns an `Option` object, not the value of the option,
---which is accessed through |vim.opt:get()|: --- which is accessed through |vim.opt:get()|:
--- ---
--- Examples: ~ --- Examples: ~
--- ---
--- The following methods of getting a list-style option are equivalent: --- The following methods of getting a list-style option are equivalent:
--- In Vimscript: >vim --- In Vimscript: >vim
--- echo wildignore --- echo wildignore
---< --- <
--- In Lua using `vim.o`: >lua --- In Lua using `vim.o`: >lua
--- print(vim.o.wildignore) --- print(vim.o.wildignore)
---< --- <
--- In Lua using `vim.opt`: >lua --- In Lua using `vim.opt`: >lua
--- vim.print(vim.opt.wildignore:get()) --- vim.print(vim.opt.wildignore:get())
---< --- <
--- ---
---In any of the above examples, to replicate the behavior |:setlocal|, use --- 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_local`. Additionally, to replicate the behavior of |:setglobal|, use
---`vim.opt_global`. --- `vim.opt_global`.
---</pre> --- </pre>
--- @diagnostic disable-next-line:unused-local used for gen_vimdoc --- @class vim.Option
local Option = {} -- luacheck: no unused local Option = {} -- luacheck: no unused
--- Returns a Lua-representation of the option. Boolean, number and string --- Returns a Lua-representation of the option. Boolean, number and string
@ -856,9 +847,7 @@ local Option = {} -- luacheck: no unused
--- print("J is enabled!") --- print("J is enabled!")
--- end --- end
--- ``` --- ```
---
---@return string|integer|boolean|nil value of option ---@return string|integer|boolean|nil value of option
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:get() end function Option:get() end
--- Append a value to string-style options. See |:set+=| --- 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:append('j')
--- vim.opt.formatoptions = vim.opt.formatoptions + 'j' --- vim.opt.formatoptions = vim.opt.formatoptions + 'j'
--- ``` --- ```
---
---@param value string Value to append ---@param value string Value to append
---@diagnostic disable-next-line:unused-local used for gen_vimdoc ---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:append(value) end -- luacheck: no unused 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:prepend('*.o')
--- vim.opt.wildignore = vim.opt.wildignore ^ '*.o' --- vim.opt.wildignore = vim.opt.wildignore ^ '*.o'
--- ``` --- ```
---
---@param value string Value to prepend ---@param value string Value to prepend
---@diagnostic disable-next-line:unused-local used for gen_vimdoc ---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:prepend(value) end -- luacheck: no unused 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:remove('*.pyc')
--- vim.opt.wildignore = vim.opt.wildignore - '*.pyc' --- vim.opt.wildignore = vim.opt.wildignore - '*.pyc'
--- ``` --- ```
---
---@param value string Value to remove ---@param value string Value to remove
---@diagnostic disable-next-line:unused-local used for gen_vimdoc ---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:remove(value) end -- luacheck: no unused function Option:remove(value) end -- luacheck: no unused

View File

@ -70,6 +70,7 @@ local M = {}
--- @field linehl? table<vim.diagnostic.Severity,string> --- @field linehl? table<vim.diagnostic.Severity,string>
--- @field texthl? table<vim.diagnostic.Severity,string> --- @field texthl? table<vim.diagnostic.Severity,string>
--- @nodoc
--- @enum vim.diagnostic.Severity --- @enum vim.diagnostic.Severity
M.severity = { M.severity = {
ERROR = 1, 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 show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved)
--- @field hide? fun(namespace:integer, bufnr:integer) --- @field hide? fun(namespace:integer, bufnr:integer)
--- @nodoc
--- @type table<string,vim.diagnostic.Handler> --- @type table<string,vim.diagnostic.Handler>
M.handlers = setmetatable({}, { M.handlers = setmetatable({}, {
__newindex = function(t, name, handler) __newindex = function(t, name, handler)
@ -731,71 +733,71 @@ end
--- - `function`: Function with signature (namespace, bufnr) that returns any of the above. --- - `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 ---@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: --- - underline: (default true) Use underline for diagnostics. Options:
--- * severity: Only underline diagnostics matching the given --- * severity: Only underline diagnostics matching the given
--- severity |diagnostic-severity| --- severity |diagnostic-severity|
--- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics --- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics
--- are set for a namespace, one prefix per diagnostic + the last diagnostic --- are set for a namespace, one prefix per diagnostic + the last diagnostic
--- message are shown. In addition to the options listed below, the --- message are shown. In addition to the options listed below, the
--- "virt_text" options of |nvim_buf_set_extmark()| may also be used here --- "virt_text" options of |nvim_buf_set_extmark()| may also be used here
--- (e.g. "virt_text_pos" and "hl_mode"). --- (e.g. "virt_text_pos" and "hl_mode").
--- Options: --- Options:
--- * severity: Only show virtual text for diagnostics matching the given --- * severity: Only show virtual text for diagnostics matching the given
--- severity |diagnostic-severity| --- severity |diagnostic-severity|
--- * source: (boolean or string) Include the diagnostic source in virtual --- * source: (boolean or string) Include the diagnostic source in virtual
--- text. Use "if_many" to only show sources if there is more than --- text. Use "if_many" to only show sources if there is more than
--- one diagnostic source in the buffer. Otherwise, any truthy value --- one diagnostic source in the buffer. Otherwise, any truthy value
--- means to always show the diagnostic source. --- means to always show the diagnostic source.
--- * spacing: (number) Amount of empty spaces inserted at the beginning --- * spacing: (number) Amount of empty spaces inserted at the beginning
--- of the virtual text. --- of the virtual text.
--- * prefix: (string or function) prepend diagnostic message with prefix. --- * prefix: (string or function) prepend diagnostic message with prefix.
--- If a function, it must have the signature (diagnostic, i, total) --- If a function, it must have the signature (diagnostic, i, total)
--- -> string, where {diagnostic} is of type |diagnostic-structure|, --- -> string, where {diagnostic} is of type |diagnostic-structure|,
--- {i} is the index of the diagnostic being evaluated, and {total} --- {i} is the index of the diagnostic being evaluated, and {total}
--- is the total number of diagnostics for the line. This can be --- is the total number of diagnostics for the line. This can be
--- used to render diagnostic symbols or error codes. --- used to render diagnostic symbols or error codes.
--- * suffix: (string or function) Append diagnostic message with suffix. --- * suffix: (string or function) Append diagnostic message with suffix.
--- If a function, it must have the signature (diagnostic) -> --- If a function, it must have the signature (diagnostic) ->
--- string, where {diagnostic} is of type |diagnostic-structure|. --- string, where {diagnostic} is of type |diagnostic-structure|.
--- This can be used to render an LSP diagnostic error code. --- This can be used to render an LSP diagnostic error code.
--- * format: (function) A function that takes a diagnostic as input and --- * format: (function) A function that takes a diagnostic as input and
--- returns a string. The return value is the text used to display --- returns a string. The return value is the text used to display
--- the diagnostic. Example: --- the diagnostic. Example:
--- <pre>lua --- ```lua
--- function(diagnostic) --- function(diagnostic)
--- if diagnostic.severity == vim.diagnostic.severity.ERROR then --- if diagnostic.severity == vim.diagnostic.severity.ERROR then
--- return string.format("E: %s", diagnostic.message) --- return string.format("E: %s", diagnostic.message)
--- end --- end
--- return diagnostic.message --- return diagnostic.message
--- end --- end
--- </pre> --- ```
--- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options: --- - signs: (default true) Use signs for diagnostics |diagnostic-signs|. Options:
--- * severity: Only show signs for diagnostics matching the given --- * severity: Only show signs for diagnostics matching the given
--- severity |diagnostic-severity| --- severity |diagnostic-severity|
--- * priority: (number, default 10) Base priority to use for signs. When --- * priority: (number, default 10) Base priority to use for signs. When
--- {severity_sort} is used, the priority of a sign is adjusted based on --- {severity_sort} is used, the priority of a sign is adjusted based on
--- its severity. Otherwise, all signs use the same priority. --- its severity. Otherwise, all signs use the same priority.
--- * text: (table) A table mapping |diagnostic-severity| to the sign text --- * 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" --- to display in the sign column. The default is to use "E", "W", "I", and "H"
--- for errors, warnings, information, and hints, respectively. Example: --- for errors, warnings, information, and hints, respectively. Example:
--- <pre>lua --- ```lua
--- vim.diagnostic.config({ --- vim.diagnostic.config({
--- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } } --- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
--- }) --- })
--- </pre> --- ```
--- * numhl: (table) A table mapping |diagnostic-severity| to the highlight --- * numhl: (table) A table mapping |diagnostic-severity| to the highlight
--- group used for the line number where the sign is placed. --- group used for the line number where the sign is placed.
--- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group --- * linehl: (table) A table mapping |diagnostic-severity| to the highlight group
--- used for the whole line the sign is placed in. --- used for the whole line the sign is placed in.
--- - float: Options for floating windows. See |vim.diagnostic.open_float()|. --- - float: Options for floating windows. See |vim.diagnostic.open_float()|.
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false, --- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
--- diagnostics are updated on InsertLeave) --- diagnostics are updated on InsertLeave)
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in --- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
--- which signs and virtual text are displayed. When true, higher severities --- which signs and virtual text are displayed. When true, higher severities
--- are displayed before lower severities (e.g. ERROR is displayed before WARN). --- are displayed before lower severities (e.g. ERROR is displayed before WARN).
--- Options: --- Options:
--- * reverse: (boolean) Reverse sort order --- * reverse: (boolean) Reverse sort order
--- ---
---@param namespace integer? Update the options for the given namespace. When omitted, update the ---@param namespace integer? Update the options for the given namespace. When omitted, update the
--- global diagnostic options. --- global diagnostic options.
@ -1090,8 +1092,8 @@ M.handlers.signs = {
api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name)) api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name))
end end
--- Handle legacy diagnostic sign definitions -- Handle legacy diagnostic sign definitions
--- These were deprecated in 0.10 and will be removed in 0.12 -- 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 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 for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do
local name = string.format('DiagnosticSign%s', v) local name = string.format('DiagnosticSign%s', v)
@ -1543,7 +1545,8 @@ end
--- Overrides the setting from |vim.diagnostic.config()|. --- Overrides the setting from |vim.diagnostic.config()|.
--- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of --- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of
--- prepending it. Overrides the setting from |vim.diagnostic.config()|. --- 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, ...) function M.open_float(opts, ...)
-- Support old (bufnr, opts) signature -- Support old (bufnr, opts) signature
local bufnr --- @type integer? local bufnr --- @type integer?

View File

@ -2279,9 +2279,9 @@ end
--- Perform filetype detection. --- Perform filetype detection.
--- ---
--- The filetype can be detected using one of three methods: --- The filetype can be detected using one of three methods:
--- 1. Using an existing buffer --- 1. Using an existing buffer
--- 2. Using only a file name --- 2. Using only a file name
--- 3. Using only file contents --- 3. Using only file contents
--- ---
--- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and --- 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 --- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but

View File

@ -320,7 +320,7 @@ end
--- Normalize a path to a standard format. A tilde (~) character at the --- 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 --- 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. --- variables are also expanded.
--- ---
--- Examples: --- Examples:

View File

@ -1,4 +1,4 @@
---@defgroup vim.highlight ---@brief
--- ---
--- Nvim includes a function for highlighting a selection on yank. --- Nvim includes a function for highlighting a selection on yank.
--- ---
@ -19,18 +19,19 @@
--- ```vim --- ```vim
--- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false} --- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
--- ``` --- ```
---
local api = vim.api local api = vim.api
local M = {} local M = {}
--- Table with default priorities used for highlighting: --- Table with default priorities used for highlighting:
--- - `syntax`: `50`, used for standard syntax highlighting --- - `syntax`: `50`, used for standard syntax highlighting
--- - `treesitter`: `100`, used for treesitter-based highlighting --- - `treesitter`: `100`, used for treesitter-based highlighting
--- - `semantic_tokens`: `125`, used for LSP semantic token highlighting --- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
--- - `diagnostics`: `150`, used for code analysis such as diagnostics --- - `diagnostics`: `150`, used for code analysis such as diagnostics
--- - `user`: `200`, used for user-triggered highlights such as LSP document --- - `user`: `200`, used for user-triggered highlights such as LSP document
--- symbols or `on_yank` autocommands --- symbols or `on_yank` autocommands
M.priorities = { M.priorities = {
syntax = 50, syntax = 50,
treesitter = 100, treesitter = 100,

View File

@ -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 --- \*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 --- \*Iter\* object with methods (such as |Iter:filter()| and |Iter:map()|) that transform the
@ -66,6 +66,7 @@
---@class IterMod ---@class IterMod
---@operator call:Iter ---@operator call:Iter
local M = {} local M = {}
---@class Iter ---@class Iter
@ -599,7 +600,7 @@ end
--- -- 12 --- -- 12
--- ---
--- ``` --- ```
--- ---@param f any
---@return any ---@return any
function Iter.find(self, f) function Iter.find(self, f)
if type(f) ~= 'function' then if type(f) ~= 'function' then
@ -645,6 +646,7 @@ end
--- ---
---@see Iter.find ---@see Iter.find
--- ---
---@param f any
---@return any ---@return any
---@diagnostic disable-next-line: unused-local ---@diagnostic disable-next-line: unused-local
function Iter.rfind(self, f) -- luacheck: no unused args 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') error('nextback() requires a list-like table')
end end
--- @nodoc
function ListIter.nextback(self) function ListIter.nextback(self)
if self._head ~= self._tail then if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1 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') error('peekback() requires a list-like table')
end end
---@nodoc
function ListIter.peekback(self) function ListIter.peekback(self)
if self._head ~= self._tail then if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1 local inc = self._head < self._tail and 1 or -1

View File

@ -90,6 +90,8 @@ end
--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 }) --- 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: ---@param opts table|nil A table of optional arguments:
--- - "buffer": (integer|boolean) Remove a mapping from the given buffer. --- - "buffer": (integer|boolean) Remove a mapping from the given buffer.
--- When `0` or `true`, use the current buffer. --- When `0` or `true`, use the current buffer.

View File

@ -190,7 +190,6 @@ function Loader.loader_lib(modname)
local sysname = uv.os_uname().sysname:lower() or '' local sysname = uv.os_uname().sysname:lower() or ''
local is_win = sysname:find('win', 1, true) and not sysname:find('darwin', 1, true) 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] local ret = M.find(modname, { patterns = is_win and { '.dll' } or { '.so' } })[1]
---@type function?, string?
if ret then if ret then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is -- 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 -- a) strip prefix up to and including the first dash, if any
@ -208,15 +207,13 @@ end
--- `loadfile` using the cache --- `loadfile` using the cache
--- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible. --- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible.
---@param filename? string ---@param filename? string
---@param mode? "b"|"t"|"bt" ---@param _mode? "b"|"t"|"bt"
---@param env? table ---@param env? table
---@return function?, string? error_message ---@return function?, string? error_message
---@private ---@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 -- ignore mode, since we byte-compile the Lua source files
mode = nil return Loader.load(normalize(filename), { env = env })
return Loader.load(normalize(filename), { mode = mode, env = env })
end end
--- Checks whether two cache hashes are the same based on: --- Checks whether two cache hashes are the same based on:
@ -273,14 +270,14 @@ end
--- Finds Lua modules for the given module name. --- Finds Lua modules for the given module name.
---@param modname string Module name, or `"*"` to find the top-level modules instead ---@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`) --- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`)
--- - paths: (string[]) Extra paths to search for modname (defaults to `{}`) --- - paths: (string[]) Extra paths to search for modname (defaults to `{}`)
--- - patterns: (string[]) List of patterns to use when searching for modules. --- - 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. --- A pattern is a string added to the basename of the Lua module being searched.
--- (defaults to `{"/init.lua", ".lua"}`) --- (defaults to `{"/init.lua", ".lua"}`)
--- - all: (boolean) Return all matches instead of just the first one (defaults to `false`) --- - 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 --- - modpath: (string) the path to the module
--- - modname: (string) the name of 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="*"` --- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"`

View File

@ -206,99 +206,96 @@ end
--- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|. --- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
--- ---
--- - Methods: --- - 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(method, params, [handler], bufnr) --- - request_sync(method, params, timeout_ms, bufnr)
--- Sends a request to the server. --- Sends a request to the server and synchronously waits for the response.
--- This is a thin wrapper around {client.rpc.request} with some additional --- This is a wrapper around {client.request}
--- checking. --- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
--- If {handler} is not specified, If one is not found there, then an error will occur. --- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if --- string describing the failure reason. If the request was unsuccessful returns `nil`.
--- 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) --- - notify(method, params)
--- Sends a request to the server and synchronously waits for the response. --- Sends a notification to an LSP server.
--- This is a wrapper around {client.request} --- Returns: a boolean to indicate if the notification was successful. If
--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from --- it is false, then it will always be false (the client has shutdown).
--- 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) --- - cancel_request(id)
--- Sends a notification to an LSP server. --- Cancels a request with a given request id.
--- Returns: a boolean to indicate if the notification was successful. If --- Returns: same as `notify()`.
--- it is false, then it will always be false (the client has shutdown).
--- ---
--- - cancel_request(id) --- - stop([force])
--- Cancels a request with a given request id. --- Stops a client, optionally with force.
--- Returns: same as `notify()`. --- 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.
--- ---
--- - stop([force]) --- - is_stopped()
--- Stops a client, optionally with force. --- Checks whether a client is stopped.
--- By default, it will just ask the server to shutdown without force. --- Returns: true if the client is fully stopped.
--- If you request to stop a client which has previously been requested to
--- shutdown, it will automatically escalate and force shutdown.
--- ---
--- - is_stopped() --- - on_attach(client, bufnr)
--- Checks whether a client is stopped. --- Runs the on_attach function from the client's config if it was defined.
--- Returns: true if the client is fully stopped. --- Useful for buffer-local setup.
--- ---
--- - on_attach(client, bufnr) --- - supports_method(method, [opts]): boolean
--- Runs the on_attach function from the client's config if it was defined. --- Checks if a client supports a given method.
--- Useful for buffer-local setup. --- Always returns true for unknown off-spec methods.
--- --- [opts] is a optional `{bufnr?: integer}` table.
--- - supports_method(method, [opts]): boolean --- Some language server capabilities can be file specific.
--- 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 --- - 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 --- - {name} (string): If a name is specified on creation, that will be
--- used. Otherwise it is just the client id. This is used for --- used. Otherwise it is just the client id. This is used for
--- logs and messages. --- logs and messages.
--- ---
--- - {rpc} (table): RPC client object, for low level interaction with the --- - {rpc} (table): RPC client object, for low level interaction with the
--- client. See |vim.lsp.rpc.start()|. --- client. See |vim.lsp.rpc.start()|.
--- ---
--- - {offset_encoding} (string): The encoding used for communicating --- - {offset_encoding} (string): The encoding used for communicating
--- with the server. You can modify this in the `config`'s `on_init` method --- with the server. You can modify this in the `config`'s `on_init` method
--- before text is sent to the server. --- 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 --- - {commands} (table): Table of command name to function which is called if
--- any LSP action (code action, code lenses, ...) triggers the command. --- any LSP action (code action, code lenses, ...) triggers the command.
--- Client commands take precedence over the global command registry. --- Client commands take precedence over the global command registry.
--- ---
--- - {requests} (table): The current pending requests in flight --- - {requests} (table): The current pending requests in flight
--- to the server. Entries are key-value pairs with the key --- to the server. Entries are key-value pairs with the key
--- being the request ID while the value is a table with `type`, --- being the request ID while the value is a table with `type`,
--- `bufnr`, and `method` key-value pairs. `type` is either "pending" --- `bufnr`, and `method` key-value pairs. `type` is either "pending"
--- for an active request, or "cancel" for a cancel request. It will --- for an active request, or "cancel" for a cancel request. It will
--- be "complete" ephemerally while executing |LspRequest| autocmds --- be "complete" ephemerally while executing |LspRequest| autocmds
--- when replies are received from the server. --- when replies are received from the server.
--- ---
--- - {config} (table): Reference of the table that was passed by the user --- - {config} (table): Reference of the table that was passed by the user
--- to |vim.lsp.start_client()|. --- to |vim.lsp.start_client()|.
--- ---
--- - {server_capabilities} (table): Response from the server sent on --- - {server_capabilities} (table): Response from the server sent on
--- `initialize` describing the server's capabilities. --- `initialize` describing the server's capabilities.
--- ---
--- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages --- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages
--- sent by the server. --- sent by the server.
--- ---
--- - {settings} Map with language server specific settings. --- - {settings} Map with language server specific settings.
--- See {config} in |vim.lsp.start_client()| --- See {config} in |vim.lsp.start_client()|
--- ---
--- - {flags} A table with flags for the client. 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() lsp.client = nil
error()
end
--- @class lsp.StartOpts --- @class lsp.StartOpts
--- @field reuse_client fun(client: lsp.Client, config: table): boolean --- @field reuse_client fun(client: lsp.Client, config: table): boolean
@ -581,9 +578,9 @@ end
--- spawn. Must be specified using a table. --- spawn. Must be specified using a table.
--- Non-string values are coerced to string. --- Non-string values are coerced to string.
--- Example: --- Example:
--- <pre> --- ```
--- { PORT = 8080; HOST = "0.0.0.0"; } --- { PORT = 8080; HOST = "0.0.0.0"; }
--- </pre> --- ```
--- ---
--- - detached: (boolean, default true) Daemonize the server process so that it runs in a --- - 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 --- 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 --- \|vim.lsp.protocol.make_client_capabilities()|, passed to the language
--- server on initialization. Hint: use make_client_capabilities() and modify --- server on initialization. Hint: use make_client_capabilities() and modify
--- its result. --- 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| --- - 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 --- - on_exit Callback (code, signal, client_id) invoked on client
--- exit. --- exit.
--- - code: exit code of the process --- - code: exit code of the process
--- - signal: number describing the signal used to terminate (if any) --- - signal: number describing the signal used to terminate (if any)
--- - client_id: client handle --- - client_id: client handle
--- ---
--- - on_attach: Callback (client, bufnr) invoked when client --- - on_attach: Callback (client, bufnr) invoked when client
--- attaches to a buffer. --- attaches to a buffer.
@ -656,13 +654,13 @@ end
--- server in the initialize request. Invalid/empty values will default to "off" --- 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: --- - 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 --- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
--- - debounce_text_changes (number, default 150): Debounce didChange --- - debounce_text_changes (number, default 150): Debounce didChange
--- notifications to the server by the given number in milliseconds. No debounce --- notifications to the server by the given number in milliseconds. No debounce
--- occurs if nil --- occurs if nil
--- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to --- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
--- exit cleanly after sending the "shutdown" request before sending kill -15. --- 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. --- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
--- ---
--- - root_dir: (string) Directory where the LSP --- - root_dir: (string) Directory where the LSP
--- server will base its workspaceFolders, rootUri, and rootPath --- server will base its workspaceFolders, rootUri, and rootPath
@ -1239,7 +1237,7 @@ end
--- ---
--- Currently only supports a single client. This can be set via --- 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` --- `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 ---@param opts table options for customizing the formatting expression which takes the
--- following optional keys: --- following optional keys:

View File

@ -12,7 +12,7 @@ local M = {}
---@param method (string) LSP method name ---@param method (string) LSP method name
---@param params (table|nil) Parameters to send to the server ---@param params (table|nil) Parameters to send to the server
---@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| ---@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 ---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs
---for all successful requests. ---for all successful requests.
---@return function _cancel_all_requests Function which can be used to ---@return function _cancel_all_requests Function which can be used to
@ -172,12 +172,13 @@ end
--- ---
--- - filter (function|nil): --- - filter (function|nil):
--- Predicate used to filter clients. Receives a client as argument and must return a --- Predicate used to filter clients. Receives a client as argument and must return a
--- boolean. Clients matching the predicate are included. Example: <pre>lua --- boolean. Clients matching the predicate are included. Example:
--- -- Never request typescript-language-server for formatting --- ```lua
--- vim.lsp.buf.format { --- -- Never request typescript-language-server for formatting
--- filter = function(client) return client.name ~= "tsserver" end --- vim.lsp.buf.format {
--- } --- filter = function(client) return client.name ~= "tsserver" end
--- </pre> --- }
--- ```
--- ---
--- - async boolean|nil --- - async boolean|nil
--- If true the method won't block. Defaults to false. --- 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 --- Add the folder at path to the workspace folders. If {path} is
--- not provided, the user will be prompted for a path using |input()|. --- not provided, the user will be prompted for a path using |input()|.
--- @param workspace_folder? string
function M.add_workspace_folder(workspace_folder) function M.add_workspace_folder(workspace_folder)
workspace_folder = workspace_folder workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'), 'dir') 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 --- Remove the folder at path from the workspace folders. If
--- {path} is not provided, the user will be prompted for --- {path} is not provided, the user will be prompted for
--- a path using |input()|. --- a path using |input()|.
--- @param workspace_folder? string
function M.remove_workspace_folder(workspace_folder) function M.remove_workspace_folder(workspace_folder)
workspace_folder = workspace_folder workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h')) 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: ---@param options table|nil Optional table which holds the following optional fields:
--- - context: (table|nil) --- - context: (table|nil)
--- Corresponds to `CodeActionContext` of the LSP specification: --- Corresponds to `CodeActionContext` of the LSP specification:
--- - diagnostics (table|nil): --- - diagnostics (table|nil):
--- LSP `Diagnostic[]`. Inferred from the current --- LSP `Diagnostic[]`. Inferred from the current
--- position if not provided. --- position if not provided.
--- - only (table|nil): --- - only (table|nil):
--- List of LSP `CodeActionKind`s used to filter the code actions. --- List of LSP `CodeActionKind`s used to filter the code actions.
--- Most language servers support values like `refactor` --- Most language servers support values like `refactor`
--- or `quickfix`. --- or `quickfix`.
--- - triggerKind (number|nil): The reason why code actions were requested. --- - triggerKind (number|nil): The reason why code actions were requested.
--- - filter: (function|nil) --- - filter: (function|nil)
--- Predicate taking an `CodeAction` and returning a boolean. --- Predicate taking an `CodeAction` and returning a boolean.
--- - apply: (boolean|nil) --- - apply: (boolean|nil)

View File

@ -258,6 +258,8 @@ end
--- |lsp-handler| for the method `textDocument/codeLens` --- |lsp-handler| for the method `textDocument/codeLens`
--- ---
---@param err lsp.ResponseError?
---@param result lsp.CodeLens[]
---@param ctx lsp.HandlerContext ---@param ctx lsp.HandlerContext
function M.on_codelens(err, result, ctx, _) function M.on_codelens(err, result, ctx, _)
if err then if err then

View File

@ -1,5 +1,3 @@
---@brief lsp-diagnostic
local protocol = require('vim.lsp.protocol') local protocol = require('vim.lsp.protocol')
local ms = protocol.Methods local ms = protocol.Methods
@ -287,6 +285,7 @@ end
--- ) --- )
--- ``` --- ```
--- ---
---@param _ lsp.ResponseError?
---@param result lsp.PublishDiagnosticsParams ---@param result lsp.PublishDiagnosticsParams
---@param ctx lsp.HandlerContext ---@param ctx lsp.HandlerContext
---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). ---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|).
@ -319,6 +318,7 @@ end
--- ) --- )
--- ``` --- ```
--- ---
---@param _ lsp.ResponseError?
---@param result lsp.DocumentDiagnosticReport ---@param result lsp.DocumentDiagnosticReport
---@param ctx lsp.HandlerContext ---@param ctx lsp.HandlerContext
---@param config table Configuration table (see |vim.diagnostic.config()|). ---@param config table Configuration table (see |vim.diagnostic.config()|).

View File

@ -368,6 +368,8 @@ end
--- ) --- )
--- ``` --- ```
--- ---
---@param _ lsp.ResponseError?
---@param result lsp.Hover
---@param ctx lsp.HandlerContext ---@param ctx lsp.HandlerContext
---@param config table Configuration table. ---@param config table Configuration table.
--- - border: (default=nil) --- - 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 ctx lsp.HandlerContext Client context
---@param config table Configuration table. ---@param config table Configuration table.
--- - border: (default=nil) --- - border: (default=nil)

View File

@ -165,7 +165,7 @@ end
--- Checks whether the level is sufficient for logging. --- Checks whether the level is sufficient for logging.
---@param level integer log level ---@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) function log.should_log(level)
return level >= current_log_level return level >= current_log_level
end end

View File

@ -273,8 +273,6 @@ end
---@field notify_reply_callbacks table<integer, function> dict of message_id to callback ---@field notify_reply_callbacks table<integer, function> dict of message_id to callback
---@field transport vim.lsp.rpc.Transport ---@field transport vim.lsp.rpc.Transport
---@field dispatchers vim.lsp.rpc.Dispatchers ---@field dispatchers vim.lsp.rpc.Dispatchers
---@class vim.lsp.rpc.Client
local Client = {} local Client = {}
---@private ---@private

View File

@ -53,7 +53,7 @@ local str_utf_end = vim.str_utf_end
---@param line string the line to index into ---@param line string the line to index into
---@param byte integer the byte idx ---@param byte integer the byte idx
---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) ---@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) local function byte_to_utf(line, byte, offset_encoding)
-- convert to 0 based indexing for str_utfindex -- convert to 0 based indexing for str_utfindex
byte = byte - 1 byte = byte - 1
@ -204,7 +204,7 @@ end
--- Normalized to the next codepoint. --- Normalized to the next codepoint.
--- prev_end_range is the text range sent to the server representing the changed region. --- 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. --- curr_end_range is the text that should be collected and sent to the server.
-- ---
---@param prev_lines string[] list of lines ---@param prev_lines string[] list of lines
---@param curr_lines string[] list of lines ---@param curr_lines string[] list of lines
---@param start_range vim.lsp.sync.Range ---@param start_range vim.lsp.sync.Range

View File

@ -574,6 +574,7 @@ end
--- ---
---@param text_document_edit table: a `TextDocumentEdit` object ---@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 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 ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
function M.apply_text_document_edit(text_document_edit, index, offset_encoding) function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
local text_document = text_document_edit.textDocument local text_document = text_document_edit.textDocument
@ -770,7 +771,7 @@ end
--- ---
---@param workspace_edit table `WorkspaceEdit` ---@param workspace_edit table `WorkspaceEdit`
---@param offset_encoding string utf-8|utf-16|utf-32 (required) ---@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) function M.apply_workspace_edit(workspace_edit, offset_encoding)
if offset_encoding == nil then if offset_encoding == nil then
vim.notify_once( vim.notify_once(
@ -1130,6 +1131,7 @@ end
--- - for LocationLink, targetRange is shown (e.g., body of function definition) --- - for LocationLink, targetRange is shown (e.g., body of function definition)
--- ---
---@param location table a single `Location` or `LocationLink` ---@param location table a single `Location` or `LocationLink`
---@param opts table
---@return integer|nil buffer id of float window ---@return integer|nil buffer id of float window
---@return integer|nil window id of float window ---@return integer|nil window id of float window
function M.preview_location(location, opts) 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 --- 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 contents table of lines to show in window
---@param opts table with optional fields ---@param opts table with optional fields
--- - height of floating window --- - height of floating window
@ -1603,7 +1606,7 @@ end
---@param contents table of lines to show in window ---@param contents table of lines to show in window
---@param syntax string of syntax to set for opened buffer ---@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()| ---@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 --- - height: (integer) height of floating window
--- - width: (integer) width of floating window --- - width: (integer) width of floating window
--- - wrap: (boolean, default true) wrap long lines --- - wrap: (boolean, default true) wrap long lines
@ -1868,6 +1871,7 @@ end
--- Converts symbols to quickfix list items. --- Converts symbols to quickfix list items.
--- ---
---@param symbols table DocumentSymbol[] or SymbolInformation[] ---@param symbols table DocumentSymbol[] or SymbolInformation[]
---@param bufnr integer
function M.symbols_to_items(symbols, bufnr) function M.symbols_to_items(symbols, bufnr)
local function _symbols_to_items(_symbols, _items, _bufnr) local function _symbols_to_items(_symbols, _items, _bufnr)
for _, symbol in ipairs(_symbols) do for _, symbol in ipairs(_symbols) do

View File

@ -6,6 +6,7 @@
-- or the test suite. (Eventually the test suite will be run in a worker process, -- 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) -- so this wouldn't be a separate case to consider)
---@nodoc
---@diagnostic disable-next-line: lowercase-global ---@diagnostic disable-next-line: lowercase-global
vim = vim or {} vim = vim or {}
@ -191,8 +192,8 @@ end
--- ---
---@param s string String to split ---@param s string String to split
---@param sep string Separator or pattern ---@param sep string Separator or pattern
---@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()| ---@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()|
---@return string[] List of split components ---@return string[] : List of split components
function vim.split(s, sep, opts) function vim.split(s, sep, opts)
local t = {} local t = {}
for c in vim.gsplit(s, sep, opts) do 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 ---@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 ---@param t table<T, any> (table) Table
---@return T[] (list) List of keys ---@return T[] : List of keys
function vim.tbl_keys(t) function vim.tbl_keys(t)
vim.validate({ t = { t, 't' } }) vim.validate({ t = { t, 't' } })
--- @cast t table<any,any> --- @cast t table<any,any>
@ -225,7 +226,7 @@ end
--- ---
---@generic T ---@generic T
---@param t table<any, T> (table) Table ---@param t table<any, T> (table) Table
---@return T[] (list) List of values ---@return T[] : List of values
function vim.tbl_values(t) function vim.tbl_values(t)
vim.validate({ t = { t, 't' } }) vim.validate({ t = { t, 't' } })
@ -243,7 +244,7 @@ end
---@generic T ---@generic T
---@param func fun(value: T): any (function) Function ---@param func fun(value: T): any (function) Function
---@param t table<any, T> (table) Table ---@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) function vim.tbl_map(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } }) vim.validate({ func = { func, 'c' }, t = { t, 't' } })
--- @cast t table<any,any> --- @cast t table<any,any>
@ -260,7 +261,7 @@ end
---@generic T ---@generic T
---@param func fun(value: T): boolean (function) Function ---@param func fun(value: T): boolean (function) Function
---@param t table<any, T> (table) Table ---@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) function vim.tbl_filter(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } }) vim.validate({ func = { func, 'c' }, t = { t, 't' } })
--- @cast t table<any,any> --- @cast t table<any,any>
@ -401,7 +402,7 @@ end
--- - "keep": use value from the leftmost map --- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map --- - "force": use value from the rightmost map
---@param ... table Two or more tables ---@param ... table Two or more tables
---@return table Merged table ---@return table : Merged table
function vim.tbl_extend(behavior, ...) function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...) return tbl_extend(behavior, false, ...)
end end
@ -456,7 +457,7 @@ end
--- Add the reverse lookup values to an existing table. --- Add the reverse lookup values to an existing table.
--- For example: --- 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. --- Note that this *modifies* the input.
---@param o table Table to add the reverse to ---@param o table Table to add the reverse to
@ -493,7 +494,7 @@ end
--- ---
---@param o table Table to index ---@param o table Table to index
---@param ... any Optional keys (0 or more, variadic) via which to index the table ---@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, ...) function vim.tbl_get(o, ...)
local keys = { ... } local keys = { ... }
if #keys == 0 then if #keys == 0 then
@ -519,8 +520,8 @@ end
---@generic T: table ---@generic T: table
---@param dst T List which will be modified and appended to ---@param dst T List which will be modified and appended to
---@param src table List from which values will be inserted ---@param src table List from which values will be inserted
---@param start (integer|nil) Start index on src. Defaults to 1 ---@param start integer? Start index on src. Defaults to 1
---@param finish (integer|nil) Final index on src. Defaults to `#src` ---@param finish integer? Final index on src. Defaults to `#src`
---@return T dst ---@return T dst
function vim.list_extend(dst, src, start, finish) function vim.list_extend(dst, src, start, finish)
vim.validate({ vim.validate({
@ -666,7 +667,7 @@ end
--- ---
---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua ---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
---@param t table Table ---@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) function vim.tbl_count(t)
vim.validate({ t = { t, 't' } }) vim.validate({ t = { t, 't' } })
--- @cast t table<any,any> --- @cast t table<any,any>
@ -681,10 +682,10 @@ end
--- Creates a copy of a table containing only elements from start to end (inclusive) --- Creates a copy of a table containing only elements from start to end (inclusive)
--- ---
---@generic T ---@generic T
---@param list T[] (list) Table ---@param list T[] Table
---@param start integer|nil Start range of slice ---@param start integer|nil Start range of slice
---@param finish integer|nil End 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) function vim.list_slice(list, start, finish)
local new_list = {} --- @type `T`[] local new_list = {} --- @type `T`[]
for i = start or 1, finish or #list do for i = start or 1, finish or #list do
@ -840,38 +841,37 @@ do
--- Usage example: --- Usage example:
--- ---
--- ```lua --- ```lua
--- function user.new(name, age, hobbies) --- function user.new(name, age, hobbies)
--- vim.validate{ --- vim.validate{
--- name={name, 'string'}, --- name={name, 'string'},
--- age={age, 'number'}, --- age={age, 'number'},
--- hobbies={hobbies, 'table'}, --- hobbies={hobbies, 'table'},
--- } --- }
--- ... --- ...
--- end --- end
--- ``` --- ```
--- ---
--- Examples with explicit argument values (can be run directly): --- Examples with explicit argument values (can be run directly):
--- ---
--- ```lua --- ```lua
--- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
--- --> NOP (success) --- --> NOP (success)
--- ---
--- vim.validate{arg1={1, 'table'}} --- vim.validate{arg1={1, 'table'}}
--- --> error('arg1: expected table, got number') --- --> error('arg1: expected table, got number')
--- ---
--- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
--- --> error('arg1: expected even number, got 3') --- --> error('arg1: expected even number, got 3')
--- ``` --- ```
--- ---
--- If multiple types are valid they can be given as a list. --- If multiple types are valid they can be given as a list.
--- ---
--- ```lua --- ```lua
--- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
--- -- NOP (success) --- -- NOP (success)
---
--- vim.validate{arg1={1, {'string', 'table'}}}
--- -- error('arg1: expected string|table, got number')
--- ---
--- 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 ---@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. --- Once the buffer is full, adding a new entry overrides the oldest entry.
--- ---
--- ```lua --- ```lua
--- local ringbuf = vim.ringbuf(4) --- local ringbuf = vim.ringbuf(4)
--- ringbuf:push("a") --- ringbuf:push("a")
--- ringbuf:push("b") --- ringbuf:push("b")
--- ringbuf:push("c") --- ringbuf:push("c")
--- ringbuf:push("d") --- ringbuf:push("d")
--- ringbuf:push("e") -- overrides "a" --- ringbuf:push("e") -- overrides "a"
--- print(ringbuf:pop()) -- returns "b" --- print(ringbuf:pop()) -- returns "b"
--- print(ringbuf:pop()) -- returns "c" --- print(ringbuf:pop()) -- returns "c"
--- ---
--- -- Can be used as iterator. Pops remaining items: --- -- Can be used as iterator. Pops remaining items:
--- for val in ringbuf do --- for val in ringbuf do
--- print(val) --- print(val)
--- end --- end
--- ``` --- ```
--- ---
--- Returns a Ringbuf instance with the following methods: --- Returns a Ringbuf instance with the following methods:

View File

@ -245,8 +245,6 @@ function Session:set_group_gravity(index, right_gravity)
end end
end end
--- @class vim.snippet.Snippet
--- @field private _session? vim.snippet.Session
local M = { session = nil } local M = { session = nil }
--- Displays the choices for the given tabstop as completion items. --- Displays the choices for the given tabstop as completion items.

View File

@ -432,7 +432,7 @@ end
--- Can be used in an ftplugin or FileType autocommand. --- Can be used in an ftplugin or FileType autocommand.
--- ---
--- Note: By default, disables regex syntax highlighting, which may be required for some plugins. --- 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: --- Example:
--- ---

View File

@ -197,7 +197,7 @@ function M.clear(buf)
end end
--- @private --- @private
--- @param findstart integer --- @param findstart 0|1
--- @param base string --- @param base string
function M.omnifunc(findstart, base) function M.omnifunc(findstart, base)
if findstart == 1 then if findstart == 1 then

View File

@ -231,7 +231,6 @@ function TSHighlighter:on_changedtree(changes)
end end
--- Gets the query used for @param lang --- Gets the query used for @param lang
--
---@package ---@package
---@param lang string Language used by the highlighter. ---@param lang string Language used by the highlighter.
---@return vim.treesitter.highlighter.Query ---@return vim.treesitter.highlighter.Query

View File

@ -1,5 +1,3 @@
--- @defgroup lua-treesitter-languagetree
---
--- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and --- @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. --- 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 --- 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 query_time = 0
local total_parse_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 if not self:is_valid(true) then
changes, no_regions_parsed, total_parse_time = self:_parse_regions(range) changes, no_regions_parsed, total_parse_time = self:_parse_regions(range)
-- Need to run injections when we parsed something -- Need to run injections when we parsed something

View File

@ -231,7 +231,7 @@ end
---@param lang string Language to use for the query ---@param lang string Language to use for the query
---@param query_name string Name of the query (e.g. "highlights") ---@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) M.get = vim.func._memoize('concat-2', function(lang, query_name)
if explicit_queries[lang][query_name] then if explicit_queries[lang][query_name] then
return explicit_queries[lang][query_name] return explicit_queries[lang][query_name]
@ -1019,6 +1019,8 @@ end
--- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc' --- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
--- ``` --- ```
--- ---
--- @param findstart 0|1
--- @param base string
function M.omnifunc(findstart, base) function M.omnifunc(findstart, base)
return vim.treesitter._query_linter.omnifunc(findstart, base) return vim.treesitter._query_linter.omnifunc(findstart, base)
end end

View File

@ -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/rfc3986
-- https://tools.ietf.org/html/rfc2732 -- https://tools.ietf.org/html/rfc2732
-- https://tools.ietf.org/html/rfc2396 -- https://tools.ietf.org/html/rfc2396
@ -116,7 +116,6 @@ end
---Gets the buffer for a uri. ---Gets the buffer for a uri.
---Creates a new unloaded buffer if no buffer for the uri already exists. ---Creates a new unloaded buffer if no buffer for the uri already exists.
--
---@param uri string ---@param uri string
---@return integer bufnr ---@return integer bufnr
function M.uri_to_bufnr(uri) function M.uri_to_bufnr(uri)

View File

@ -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 --- conforming to the https://semver.org spec. Plugins, and plugin managers, can use this to check
--- available tools and dependencies on the current system. --- available tools and dependencies on the current system.
--- ---
@ -13,9 +12,9 @@
--- end --- 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, --- A version "range spec" defines a semantic version range which can be tested against a version,
--- using |vim.version.range()|. --- using |vim.version.range()|.

87
scripts/cdoc_grammar.lua Normal file
View File

@ -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]]

223
scripts/cdoc_parser.lua Normal file
View File

@ -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

View File

@ -3,7 +3,6 @@
-- Generator for various vimdoc and Lua type files -- Generator for various vimdoc and Lua type files
local DEP_API_METADATA = 'build/api_metadata.mpack' local DEP_API_METADATA = 'build/api_metadata.mpack'
local DEP_API_DOC = 'runtime/doc/api.mpack'
--- @class vim.api.metadata --- @class vim.api.metadata
--- @field name string --- @field name string
@ -210,44 +209,65 @@ end
--- @return table<string, vim.EvalFn> --- @return table<string, vim.EvalFn>
local function get_api_meta() 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 ret = {} --- @type table<string, vim.EvalFn>
local doc_mpack_f = assert(io.open(DEP_API_DOC, 'rb')) local cdoc_parser = require('scripts.cdoc_parser')
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 local f = 'src/nvim/api'
if fun.lua then
local fdoc = doc_metadata[fun.name]
local params = {} --- @type {[1]:string,[2]:string}[] local function include(fun)
for _, p in ipairs(fun.parameters) do if not vim.startswith(fun.name, 'nvim_') then
local ptype, pname = p[1], p[2] return false
params[#params + 1] = {
pname,
api_type(ptype),
fdoc and fdoc.parameters_doc[pname] or nil,
}
end
local r = {
signature = 'NA',
name = fun.name,
params = params,
returns = api_type(fun.return_type),
deprecated = fun.deprecated_since ~= nil,
}
if fdoc then
if #fdoc.doc > 0 then
r.desc = table.concat(fdoc.doc, '\n')
end
r.return_desc = (fdoc['return'] or {})[1]
end
ret[fun.name] = r
end 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
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,
}
if not deprecated then
r.desc = fun.desc
r.return_desc = fun.returns[1].desc
end
ret[fun.name] = r
end end
return ret return ret
end end
@ -275,12 +295,10 @@ end
--- @param fun vim.EvalFn --- @param fun vim.EvalFn
--- @param write fun(line: string) --- @param write fun(line: string)
local function render_api_meta(_f, fun, write) local function render_api_meta(_f, fun, write)
if not vim.startswith(fun.name, 'nvim_') then
return
end
write('') write('')
local text_utils = require('scripts.text_utils')
if vim.startswith(fun.name, 'nvim__') then if vim.startswith(fun.name, 'nvim__') then
write('--- @private') write('--- @private')
end end
@ -291,10 +309,10 @@ local function render_api_meta(_f, fun, write)
local desc = fun.desc local desc = fun.desc
if desc then if desc then
desc = text_utils.md_to_vimdoc(desc, 0, 0, 74)
for _, l in ipairs(split(norm_text(desc))) do for _, l in ipairs(split(norm_text(desc))) do
write('--- ' .. l) write('--- ' .. l)
end end
write('---')
end end
local param_names = {} --- @type string[] local param_names = {} --- @type string[]
@ -303,8 +321,11 @@ local function render_api_meta(_f, fun, write)
param_names[#param_names + 1] = p[1] param_names[#param_names + 1] = p[1]
local pdesc = p[3] local pdesc = p[3]
if pdesc then if pdesc then
local pdesc_a = split(norm_text(pdesc)) local s = '--- @param ' .. p[1] .. ' ' .. p[2] .. ' '
write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1]) 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 for i = 2, #pdesc_a do
if not pdesc_a[i] then if not pdesc_a[i] then
break break
@ -317,6 +338,7 @@ local function render_api_meta(_f, fun, write)
end end
if fun.returns ~= '' then if fun.returns ~= '' then
local ret_desc = fun.returns_desc and ' : ' .. fun.returns_desc or '' 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 local ret = LUA_API_RETURN_OVERRIDES[fun.name] or fun.returns
write('--- @return ' .. ret .. ret_desc) write('--- @return ' .. ret .. ret_desc)
end end
@ -328,8 +350,6 @@ end
--- @return table<string, vim.EvalFn> --- @return table<string, vim.EvalFn>
local function get_api_keysets_meta() local function get_api_keysets_meta()
local mpack_f = assert(io.open(DEP_API_METADATA, 'rb')) 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 metadata = assert(vim.mpack.decode(mpack_f:read('*all')))
local ret = {} --- @type table<string, vim.EvalFn> local ret = {} --- @type table<string, vim.EvalFn>

787
scripts/gen_vimdoc.lua Executable file
View File

@ -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()

File diff suppressed because it is too large Load Diff

View File

@ -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

218
scripts/luacats_grammar.lua Normal file
View File

@ -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]]

521
scripts/luacats_parser.lua Normal file
View File

@ -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

239
scripts/text_utils.lua Normal file
View File

@ -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

View File

@ -902,14 +902,6 @@ set(VIMDOC_FILES
${NVIM_RUNTIME_DIR}/doc/treesitter.txt ${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 API_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/nvim/api/*.c)
file(GLOB LUA_SOURCES CONFIGURE_DEPENDS file(GLOB LUA_SOURCES CONFIGURE_DEPENDS
@ -921,25 +913,25 @@ file(GLOB LUA_SOURCES CONFIGURE_DEPENDS
) )
add_custom_command( add_custom_command(
OUTPUT ${MPACK_FILES} OUTPUT ${VIMDOC_FILES}
COMMAND ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.py COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
$<TARGET_FILE:nvim_bin> -l scripts/gen_vimdoc.lua
DEPENDS DEPENDS
nvim_bin nvim
${API_SOURCES} ${API_SOURCES}
${LUA_SOURCES} ${LUA_SOURCES}
${VIMDOC_FILES} ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.lua
${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.py
${PROJECT_SOURCE_DIR}/scripts/lua2dox.lua
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
) )
add_custom_command( add_custom_command(
OUTPUT ${GEN_EVAL_TOUCH} OUTPUT ${GEN_EVAL_TOUCH}
COMMAND ${CMAKE_COMMAND} -E touch ${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 DEPENDS
nvim
${API_METADATA} ${API_METADATA}
${NVIM_RUNTIME_DIR}/doc/api.mpack
${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua ${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
${PROJECT_SOURCE_DIR}/src/nvim/eval.lua ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua
${PROJECT_SOURCE_DIR}/src/nvim/options.lua ${PROJECT_SOURCE_DIR}/src/nvim/options.lua

View File

@ -75,7 +75,7 @@ static int64_t next_autocmd_id = 1;
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands /// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern} /// |autocmd-buflocal|. Cannot be used with {pattern}
/// @return Array of autocommands matching the criteria, with each item /// @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). /// - id (number): the autocommand id (only when defined with the API).
/// - group (integer): the autocommand group id. /// - group (integer): the autocommand group id.
/// - group_name (string): the autocommand group name. /// - group_name (string): the autocommand group name.
@ -83,10 +83,10 @@ static int64_t next_autocmd_id = 1;
/// - event (string): the autocommand event. /// - event (string): the autocommand event.
/// - command (string): the autocommand command. Note: this will be empty if a callback is set. /// - 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 /// - 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. /// - once (boolean): whether the autocommand is only run once.
/// - pattern (string): the autocommand pattern. /// - 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. /// - buflocal (boolean): true if the autocommand is buffer local.
/// - buffer (number): the buffer number. /// - buffer (number): the buffer number.
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err) 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 /// @param opts Parameters
/// - event: (string|table) /// - event: (string|table)
/// Examples: /// Examples:
/// - event: "pat1" /// - event: "pat1"
/// - event: { "pat1" } /// - event: { "pat1" }
/// - event: { "pat1", "pat2", "pat3" } /// - event: { "pat1", "pat2", "pat3" }
/// - pattern: (string|table) /// - pattern: (string|table)
/// - pattern or patterns to match exactly. /// - pattern or patterns to match exactly.
/// - For example, if you have `*.py` as that pattern for the autocmd, /// - For example, if you have `*.py` as that pattern for the autocmd,

View File

@ -50,9 +50,8 @@
# include "api/buffer.c.generated.h" # include "api/buffer.c.generated.h"
#endif #endif
/// \defgroup api-buffer /// @brief <pre>help
/// /// For more information on buffers, see |buffers|.
/// \brief For more information on buffers, see |buffers|
/// ///
/// Unloaded Buffers: ~ /// Unloaded Buffers: ~
/// ///
@ -64,6 +63,7 @@
/// ///
/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check /// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
/// whether a buffer is loaded. /// whether a buffer is loaded.
/// </pre>
/// Returns the number of lines in the given buffer. /// 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; return true;
} }
/// @nodoc
void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err) void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err)
{ {
buf_T *buf = find_buffer_by_handle(buffer, 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. /// 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 buffer Buffer handle, or 0 for current buffer
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
/// @returns Array of |maparg()|-like dictionaries describing mappings. /// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle. /// The "buffer" key holds the associated buffer handle.
@ -1223,6 +1224,7 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
return res; return res;
} }
/// @nodoc
Dictionary nvim__buf_stats(Buffer buffer, Arena *arena, Error *err) Dictionary nvim__buf_stats(Buffer buffer, Arena *arena, Error *err)
{ {
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);

View File

@ -67,7 +67,7 @@
/// - file: (boolean) The command expands filenames. Which means characters such as "%", /// - file: (boolean) The command expands filenames. Which means characters such as "%",
/// "#" and wildcards are expanded. /// "#" and wildcards are expanded.
/// - bar: (boolean) The "|" character is treated as a command separator and the double /// - 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|. /// - mods: (dictionary) |:command-modifiers|.
/// - filter: (dictionary) |:filter|. /// - filter: (dictionary) |:filter|.
/// - pattern: (string) Filter pattern. Empty string if there is no filter. /// - pattern: (string) Filter pattern. Empty string if there is no filter.

View File

@ -61,8 +61,7 @@ Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
/// Gets the buffer number /// Gets the buffer number
/// ///
/// @deprecated The buffer number now is equal to the object id, /// @deprecated The buffer number now is equal to the object id
/// so there is no need to use this function.
/// ///
/// @param buffer Buffer handle, or 0 for current buffer /// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any /// @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. /// Set the virtual text (annotation) for a buffer line.
/// ///
/// @deprecated use nvim_buf_set_extmark to use full virtual text /// @deprecated use nvim_buf_set_extmark to use full virtual text functionality.
/// functionality.
/// ///
/// The text will be placed after the buffer text. Virtual text will never /// 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 /// 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. /// virtual text, the allocated id is then returned.
/// ///
/// @param buffer Buffer handle, or 0 for current buffer /// @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 /// or -1 for a ungrouped annotation
/// @param line Line to annotate with virtual text (zero-indexed) /// @param line Line to annotate with virtual text (zero-indexed)
/// @param chunks A list of [text, hl_group] arrays, each representing a /// @param chunks A list of [text, hl_group] arrays, each representing a

View File

@ -1205,6 +1205,7 @@ free_exit:
return virt_text; return virt_text;
} }
/// @nodoc
String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error *err) String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error *err)
FUNC_API_SINCE(7) FUNC_API_RET_ALLOC FUNC_API_SINCE(7) FUNC_API_RET_ALLOC
{ {

View File

@ -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 /// Gets the option information for one option from arbitrary buffer or window
/// ///
/// Resulting dictionary has keys: /// Resulting dictionary has keys:
/// - name: Name of the option (like 'filetype') /// - name: Name of the option (like 'filetype')
/// - shortname: Shortened name of the option (like 'ft') /// - shortname: Shortened name of the option (like 'ft')
/// - type: type of option ("string", "number" or "boolean") /// - type: type of option ("string", "number" or "boolean")
/// - default: The default value for the option /// - default: The default value for the option
/// - was_set: Whether the option was set. /// - was_set: Whether the option was set.
/// ///
/// - last_set_sid: Last set script id (if any) /// - last_set_sid: Last set script id (if any)
/// - last_set_linenr: line number where option was set /// - last_set_linenr: line number where option was set
/// - last_set_chan: Channel where option was set (0 for local) /// - last_set_chan: Channel where option was set (0 for local)
/// ///
/// - scope: one of "global", "win", or "buf" /// - scope: one of "global", "win", or "buf"
/// - global_local: whether win or buf option has a global value /// - global_local: whether win or buf option has a global value
/// ///
/// - commalist: List of comma separated values /// - commalist: List of comma separated values
/// - flaglist: List of single char flags /// - flaglist: List of single char flags
/// ///
/// When {scope} is not provided, the last set information applies to the local /// 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 /// value in the current buffer or window if it is available, otherwise the

View File

@ -165,7 +165,7 @@ void remote_ui_wait_for_attach(bool only_stdio)
/// Activates UI events on the channel. /// 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 /// Implies that the client is ready to show the UI. Adds the client to the
/// list of UIs. |nvim_list_uis()| /// 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 channel_id
/// @param event Event name /// @param event Event name
/// @param payload Event payload /// @param value Event payload
/// @param[out] err Error details, if any. /// @param[out] err Error details, if any.
void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err) void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err)
FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY

View File

@ -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, /// @note Unlike the `:highlight` command which can update a highlight group,
/// this function completely replaces the definition. For example: /// 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'. /// 'Visual'.
/// ///
/// @note The fg and bg keys also accept the string values `"fg"` or `"bg"` /// @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); return nvim_get_runtime_file(NULL_STRING, true, arena, err);
} }
/// @nodoc
Array nvim__runtime_inspect(Arena *arena) Array nvim__runtime_inspect(Arena *arena)
{ {
return runtime_inspect(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; return num_fnames > 0;
} }
/// @nodoc
String nvim__get_lib_dir(void) String nvim__get_lib_dir(void)
FUNC_API_RET_ALLOC FUNC_API_RET_ALLOC
{ {
@ -1547,14 +1549,14 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// @param channel_id /// @param channel_id
/// @param name Short name for the connected client /// @param name Short name for the connected client
/// @param version Dictionary describing the version, with these /// @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) /// - "major" major version (defaults to 0 if not set, for no release yet)
/// - "minor" minor version /// - "minor" minor version
/// - "patch" patch number /// - "patch" patch number
/// - "prerelease" string describing a prerelease, like "dev" or "beta1" /// - "prerelease" string describing a prerelease, like "dev" or "beta1"
/// - "commit" hash or similar identifier of commit /// - "commit" hash or similar identifier of commit
/// @param type Must be one of the following values. Client libraries should /// @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 /// - "remote" remote client connected "Nvim flavored" MessagePack-RPC (responses
/// must be in reverse order of requests). |msgpack-rpc| /// must be in reverse order of requests). |msgpack-rpc|
/// - "msgpack-rpc" remote client connected to Nvim via fully MessagePack-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 /// - "host" plugin host, typically started by nvim
/// - "plugin" single plugin, started by nvim /// - "plugin" single plugin, started by nvim
/// @param methods Builtin methods in the client. For a host, this does not /// @param methods Builtin methods in the client. For a host, this does not
/// include plugin methods which will be discovered later. /// include plugin methods which will be discovered later.
/// The key should be the method name, the values are dicts with /// The key should be the method name, the values are dicts with
/// these (optional) keys (more keys may be added in future /// these (optional) keys (more keys may be added in future
/// versions of Nvim, thus unknown keys are ignored. Clients /// versions of Nvim, thus unknown keys are ignored. Clients
/// must only use keys defined in this or later versions of /// must only use keys defined in this or later versions of
/// Nvim): /// Nvim):
/// - "async" if true, send as a notification. If false or unspecified, /// - "async" if true, send as a notification. If false or unspecified,
/// use a blocking request /// use a blocking request
/// - "nargs" Number of arguments. Could be a single integer or an array /// - "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); 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 nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err)
{ {
Array ret = ARRAY_DICT_INIT; Array ret = ARRAY_DICT_INIT;
@ -2015,6 +2017,7 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E
return ret; return ret;
} }
/// @nodoc
void nvim__screenshot(String path) void nvim__screenshot(String path)
FUNC_API_FAST FUNC_API_FAST
{ {
@ -2029,6 +2032,7 @@ void nvim__invalidate_glyph_cache(void)
must_redraw = UPD_CLEAR; must_redraw = UPD_CLEAR;
} }
/// @nodoc
Object nvim__unpack(String str, Arena *arena, Error *err) Object nvim__unpack(String str, Arena *arena, Error *err)
FUNC_API_FAST FUNC_API_FAST
{ {
@ -2319,6 +2323,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena *
return result; return result;
} }
/// @nodoc
void nvim_error_event(uint64_t channel_id, Integer lvl, String data) void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
FUNC_API_REMOTE_ONLY FUNC_API_REMOTE_ONLY
{ {

View File

@ -351,9 +351,7 @@ typedef struct {
Object *ret_node_p; Object *ret_node_p;
} ExprASTConvStackItem; } ExprASTConvStackItem;
/// @cond DOXYGEN_NOT_A_FUNCTION
typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// @endcond
/// Parse a Vimscript expression. /// Parse a Vimscript expression.
/// ///
@ -387,8 +385,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "arg": String, error message argument. /// - "arg": String, error message argument.
/// - "len": Amount of bytes successfully parsed. With flags equal to "" /// - "len": Amount of bytes successfully parsed. With flags equal to ""
/// that should be equal to the length of expr string. /// that should be equal to the length of expr string.
/// (“Successfully parsed” here means “participated in AST /// ("Successfully parsed" here means "participated in AST
/// creation”, not “till the first error”.) /// creation", not "till the first error".)
/// - "ast": AST, either nil or a dictionary with these keys: /// - "ast": AST, either nil or a dictionary with these keys:
/// - "type": node type, one of the value names from ExprASTNodeType /// - "type": node type, one of the value names from ExprASTNodeType
/// stringified without "kExprNode" prefix. /// stringified without "kExprNode" prefix.

View File

@ -116,12 +116,12 @@
/// - width: Window width (in character cells). Minimum of 1. /// - width: Window width (in character cells). Minimum of 1.
/// - height: Window height (in character cells). Minimum of 1. /// - height: Window height (in character cells). Minimum of 1.
/// - bufpos: Places float relative to buffer text (only when /// - bufpos: Places float relative to buffer text (only when
/// relative="win"). Takes a tuple of zero-indexed [line, column]. /// relative="win"). Takes a tuple of zero-indexed [line, column].
/// `row` and `col` if given are applied relative to this /// `row` and `col` if given are applied relative to this
/// position, else they default to: /// position, else they default to:
/// - `row=1` and `col=0` if `anchor` is "NW" or "NE" /// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
/// - `row=0` and `col=0` if `anchor` is "SW" or "SE" /// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
/// (thus like a tooltip near the buffer text). /// (thus like a tooltip near the buffer text).
/// - row: Row position in units of "screen cell height", may be fractional. /// - row: Row position in units of "screen cell height", may be fractional.
/// - col: Column position in units of "screen cell width", may be /// - col: Column position in units of "screen cell width", may be
/// fractional. /// fractional.
@ -153,7 +153,7 @@
/// 'fillchars' to a space char, and clearing the /// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'. /// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: Style of (optional) window border. This can either be a string /// - 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). /// - "none": No border (default).
/// - "single": A single line box. /// - "single": A single line box.
/// - "double": A double line box. /// - "double": A double line box.
@ -161,21 +161,31 @@
/// - "solid": Adds padding by a single whitespace cell. /// - "solid": Adds padding by a single whitespace cell.
/// - "shadow": A drop shadow effect by blending with the background. /// - "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 /// - 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 /// eight. The array will specify the eight chars building up the border
/// in a clockwise fashion starting with the top-left corner. As an /// in a clockwise fashion starting with the top-left corner. As an
/// example, the double box style could be specified as /// 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" ]. /// [ "x" ].
/// ```
/// An empty string can be used to turn off a specific border, for instance, /// An empty string can be used to turn off a specific border, for instance,
/// ```
/// [ "", "", "", ">", "", "", "", "<" ] /// [ "", "", "", ">", "", "", "", "<" ]
/// ```
/// will only make vertical borders but not horizontal ones. /// will only make vertical borders but not horizontal ones.
/// By default, `FloatBorder` highlight is used, which links to `WinSeparator` /// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
/// when not defined. It could also be specified by character: /// when not defined. It could also be specified by character:
/// ```
/// [ ["+", "MyCorner"], ["x", "MyBorder"] ]. /// [ ["+", "MyCorner"], ["x", "MyBorder"] ].
/// ```
/// - title: Title (optional) in window border, string or list. /// - title: Title (optional) in window border, string or list.
/// List should consist of `[text, highlight]` tuples. /// List should consist of `[text, highlight]` tuples.
/// If string, the default highlight group is `FloatTitle`. /// If string, the default highlight group is `FloatTitle`.

View File

@ -452,6 +452,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
/// ///
/// This takes precedence over the 'winhighlight' option. /// This takes precedence over the 'winhighlight' option.
/// ///
/// @param window
/// @param ns_id the namespace to use /// @param ns_id the namespace to use
/// @param[out] err Error details, if any /// @param[out] err Error details, if any
void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err) void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err)

View File

@ -6,46 +6,74 @@ local lpeg = vim.lpeg
local P, R, S = lpeg.P, lpeg.R, lpeg.S local P, R, S = lpeg.P, lpeg.R, lpeg.S
local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg 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 any = P(1) -- (consume one character)
local letter = R('az', 'AZ') + S('_$') local letter = R('az', 'AZ') + S('_$')
local num = R('09') local num = R('09')
local alpha = letter + num local alpha = letter + num
local nl = P('\r\n') + P('\n') local nl = P('\r\n') + P('\n')
local not_nl = any - nl local not_nl = any - nl
local ws = S(' \t') + nl local space = S(' \t')
local fill = ws ^ 0 local ws = space + nl
local c_comment = P('//') * (not_nl ^ 0) local fill = rep(ws)
local c_preproc = P('#') * (not_nl ^ 0) local c_comment = P('//') * rep(not_nl)
local dllexport = P('DLLEXPORT') * (ws ^ 1) local cdoc_comment = P('///') * opt(Ct(Cg(rep(space) * rep(not_nl), 'comment')))
local typed_container = (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) local c_preproc = P('#') * rep(not_nl)
* ((any - P(')')) ^ 1) local dllexport = P('DLLEXPORT') * rep1(ws)
local typed_container = (
(P('ArrayOf(') + P('DictionaryOf(') + P('Dict('))
* rep1(any - P(')'))
* 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_void = P('void')
local c_param_type = ( local c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error')) ((P('Error') * fill * P('*') * fill) * Cc('error'))
+ ((P('Arena') * fill * P('*') * fill) * Cc('arena')) + ((P('Arena') * fill * P('*') * fill) * Cc('arena'))
+ ((P('lua_State') * fill * P('*') * fill) * Cc('lstate')) + ((P('lua_State') * fill * P('*') * fill) * Cc('lstate'))
+ C((P('const ') ^ -1) * c_id * (ws ^ 1) * P('*')) + C(opt(P('const ')) * c_id * rep1(ws) * rep1(P('*')))
+ (C(c_id) * (ws ^ 1)) + (C(c_id) * rep1(ws))
) )
local c_type = (C(c_void) * (ws ^ 1)) + c_param_type local c_type = (C(c_void) * (ws ^ 1)) + c_param_type
local c_param = Ct(c_param_type * C(c_id)) local c_param = Ct(c_param_type * C(c_id))
local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0)
local c_params = Ct(c_void + c_param_list) 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( 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_type, 'return_type')
* Cg(c_id, 'name') * Cg(c_id, 'name')
* fill * fill
* P('(') * (P('(') * fill * Cg(c_params, 'parameters') * fill * P(')'))
* fill
* Cg(c_params, 'parameters')
* fill
* P(')')
* Cg(Cc(false), 'fast') * Cg(Cc(false), 'fast')
* (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * (fill * Cg((P('FUNC_API_SINCE(') * C(rep1(num))) * P(')'), 'since') ^ -1)
* (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), 'deprecated_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_FAST') * Cc(true)), 'fast') ^ -1)
* (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1) * (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1)
* (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -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_IMPL') * Cc(true)), 'client_impl') ^ -1)
* (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) * (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1)
* fill * 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) 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(';') * 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 } return { grammar = grammar, typed_container = typed_container }

View File

@ -23,9 +23,7 @@ local function_names = {}
local c_grammar = require('generators.c_grammar') local c_grammar = require('generators.c_grammar')
local function startswith(String, Start) local startswith = vim.startswith
return string.sub(String, 1, string.len(Start)) == Start
end
local function add_function(fn) local function add_function(fn)
local public = startswith(fn.name, 'nvim_') or fn.deprecated_since 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')) local tmp = c_grammar.grammar:match(input:read('*all'))
for j = 1, #tmp do for j = 1, #tmp do
local val = tmp[j] local val = tmp[j]
if val.keyset_name then if val[1] ~= 'empty' then
add_keyset(val) if val.keyset_name then
else add_keyset(val)
add_function(val) else
add_function(val)
end
end end
end end
input:close() input:close()

View File

@ -93,6 +93,10 @@ local function call_ui_event_method(output, ev)
output:write('}\n\n') output:write('}\n\n')
end end
events = vim.tbl_filter(function(ev)
return ev[1] ~= 'empty'
end, events)
for i = 1, #events do for i = 1, #events do
local ev = events[i] local ev = events[i]
assert(ev.return_type == 'void') assert(ev.return_type == 'void')

View File

@ -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]]

View File

@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq local eq = helpers.eq
local grammar = require('src/nvim/generators/luacats_grammar') local grammar = require('scripts/luacats_grammar')
describe('luacats grammar', function() describe('luacats grammar', function()
--- @param text string --- @param text string
@ -85,7 +85,7 @@ describe('luacats grammar', function()
test('@param level (integer|string) desc', { test('@param level (integer|string) desc', {
kind = 'param', kind = 'param',
name = 'level', name = 'level',
type = '(integer|string)', type = 'integer|string',
desc = 'desc', desc = 'desc',
}) })

View File

@ -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)