aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.builds/freebsd.yml5
-rw-r--r--.builds/openbsd.yml5
-rw-r--r--.editorconfig4
-rw-r--r--.git-blame-ignore-revs1
-rw-r--r--.github/workflows/ci.yml7
-rw-r--r--.stylua.toml6
-rw-r--r--.styluaignore3
-rw-r--r--CMakeLists.txt1
-rw-r--r--Makefile11
-rw-r--r--man/nvim.114
-rw-r--r--runtime/doc/api.txt89
-rw-r--r--runtime/doc/builtin.txt22
-rw-r--r--runtime/doc/diagnostic.txt106
-rw-r--r--runtime/doc/lsp.txt159
-rw-r--r--runtime/doc/lua.txt649
-rw-r--r--runtime/doc/map.txt2
-rw-r--r--runtime/doc/options.txt17
-rw-r--r--runtime/doc/starting.txt317
-rw-r--r--runtime/doc/treesitter.txt6
-rw-r--r--runtime/doc/usr_21.txt4
-rw-r--r--runtime/doc/vim_diff.txt8
-rw-r--r--runtime/filetype.lua24
-rw-r--r--runtime/ftplugin/abaqus.vim8
-rw-r--r--runtime/ftplugin/query.lua2
-rw-r--r--runtime/indent/query.lua2
-rw-r--r--runtime/lua/man.lua28
-rw-r--r--runtime/lua/vim/F.lua10
-rw-r--r--runtime/lua/vim/_editor.lua244
-rw-r--r--runtime/lua/vim/_init_packages.lua28
-rw-r--r--runtime/lua/vim/_meta.lua233
-rw-r--r--runtime/lua/vim/compat.lua4
-rw-r--r--runtime/lua/vim/diagnostic.lua446
-rw-r--r--runtime/lua/vim/filetype.lua3075
-rw-r--r--runtime/lua/vim/filetype/detect.lua169
-rw-r--r--runtime/lua/vim/highlight.lua20
-rw-r--r--runtime/lua/vim/inspect.lua108
-rw-r--r--runtime/lua/vim/keymap.lua30
-rw-r--r--runtime/lua/vim/lsp.lua535
-rw-r--r--runtime/lua/vim/lsp/_snippet.lua167
-rw-r--r--runtime/lua/vim/lsp/buf.lua201
-rw-r--r--runtime/lua/vim/lsp/codelens.lua54
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua107
-rw-r--r--runtime/lua/vim/lsp/handlers.lua182
-rw-r--r--runtime/lua/vim/lsp/health.lua9
-rw-r--r--runtime/lua/vim/lsp/log.lua72
-rw-r--r--runtime/lua/vim/lsp/protocol.lua542
-rw-r--r--runtime/lua/vim/lsp/rpc.lua240
-rw-r--r--runtime/lua/vim/lsp/sync.lua43
-rw-r--r--runtime/lua/vim/lsp/util.lua604
-rw-r--r--runtime/lua/vim/shared.lua282
-rw-r--r--runtime/lua/vim/treesitter.lua48
-rw-r--r--runtime/lua/vim/treesitter/health.lua12
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua189
-rw-r--r--runtime/lua/vim/treesitter/language.lua6
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua97
-rw-r--r--runtime/lua/vim/treesitter/query.lua118
-rw-r--r--runtime/lua/vim/ui.lua10
-rw-r--r--runtime/lua/vim/uri.lua36
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim6
-rw-r--r--runtime/syntax/query.lua2
-rw-r--r--runtime/syntax/vim.vim3
-rw-r--r--scripts/genvimvim.lua9
-rw-r--r--scripts/lua2dox.lua23
-rwxr-xr-xscripts/vim-patch.sh4
-rwxr-xr-xsrc/nvim/CMakeLists.txt18
-rw-r--r--src/nvim/README.md2
-rw-r--r--src/nvim/api/buffer.c34
-rw-r--r--src/nvim/api/keysets.lua39
-rw-r--r--src/nvim/api/private/helpers.c173
-rw-r--r--src/nvim/api/vimscript.c385
-rw-r--r--src/nvim/buffer.c4
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval/funcs.c23
-rw-r--r--src/nvim/eval/funcs.h6
-rw-r--r--src/nvim/ex_cmds_defs.h3
-rw-r--r--src/nvim/ex_docmd.c467
-rw-r--r--src/nvim/ex_getln.c5
-rw-r--r--src/nvim/ex_session.c2
-rw-r--r--src/nvim/generators/gen_eval.lua42
-rw-r--r--src/nvim/generators/hashy.lua24
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/keycodes.c (renamed from src/nvim/keymap.c)46
-rw-r--r--src/nvim/keycodes.h (renamed from src/nvim/keymap.h)118
-rw-r--r--src/nvim/log.c14
-rw-r--r--src/nvim/lua/executor.c11
-rw-r--r--src/nvim/mbyte.c25
-rw-r--r--src/nvim/menu.c2
-rw-r--r--src/nvim/message.c2
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/option.c10
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/os/stdpaths.c23
-rw-r--r--src/nvim/os/stdpaths_defs.h1
-rw-r--r--src/nvim/search.c2
-rw-r--r--src/nvim/shada.c2
-rw-r--r--src/nvim/spellfile.c11
-rw-r--r--src/nvim/syntax.c2
-rw-r--r--src/nvim/terminal.c6
-rw-r--r--src/nvim/testdir/test_buffer.vim11
-rw-r--r--src/nvim/testdir/test_matchfuzzy.vim3
-rw-r--r--src/nvim/testdir/test_spell.vim8
-rw-r--r--src/nvim/testdir/test_spell_utf8.vim6
-rw-r--r--src/nvim/testdir/test_undo.vim17
-rw-r--r--src/nvim/undo.c11
-rw-r--r--src/nvim/vim.h2
-rw-r--r--test/functional/api/vim_spec.lua147
-rw-r--r--test/functional/editor/tabpage_spec.lua11
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua15
-rw-r--r--test/functional/options/defaults_spec.lua96
-rw-r--r--test/functional/plugin/lsp_spec.lua21
-rw-r--r--test/symbolic/klee/nvim/keymap.c2
-rw-r--r--test/symbolic/klee/viml_expressions_lexer.c2
-rw-r--r--test/symbolic/klee/viml_expressions_parser.c2
-rw-r--r--test/unit/keycodes_spec.lua (renamed from test/unit/keymap_spec.lua)4
-rw-r--r--third-party/CMakeLists.txt16
-rw-r--r--third-party/cmake/BuildGperf.cmake68
-rw-r--r--third-party/cmake/GperfCMakeLists.txt30
118 files changed, 6640 insertions, 4811 deletions
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index 2d06b1e685..4be49fd153 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -23,6 +23,11 @@ environment:
CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3
tasks:
+- should-run: |
+ if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then
+ echo "Skipping build because only ignored files were changed"
+ complete-build
+ fi
- build-deps: |
cd neovim
gmake deps
diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml
index 0aaa003820..6263c436ae 100644
--- a/.builds/openbsd.yml
+++ b/.builds/openbsd.yml
@@ -23,6 +23,11 @@ environment:
CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3
tasks:
+- should-run: |
+ if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then
+ echo "Skipping build because only ignored files were changed"
+ complete-build
+ fi
- build-deps: |
export AUTOCONF_VERSION=2.71
export AUTOMAKE_VERSION=1.16
diff --git a/.editorconfig b/.editorconfig
index 5a5fba37ac..2aa956b1fc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,14 +6,10 @@ indent_size = 2
tab_width = 8
end_of_line = lf
insert_final_newline = true
-charset = utf-8
[*.{c,h,in,lua}]
max_line_length = 100
-[*.{vim,po}]
-charset = unset
-
[{Makefile,**/Makefile,runtime/doc/*.txt}]
indent_style = tab
indent_size = 8
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index fce35b54ee..c3078cfd35 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -47,6 +47,7 @@ a68faed02dc8e37b8f10da14dc02e33e6ed93947
ee031eb5256bb83e0d6add2bae6fd943a4186ffe
69e11b58b4db0952f11a5ff85aa7150b5f5b8db8
271bb32855853b011fceaf0ad2f829bce66b2a19
+aefdc6783cb77f09786542c90901a9e7120bea42
# typos
d238b8f6003d34cae7f65ff7585b48a2cd9449fb
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1aa0906ffc..87c270afbe 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -87,6 +87,13 @@ jobs:
run: ./ci/run_lint.sh clint-full
- if: "!cancelled()"
+ name: stylua
+ uses: JohnnyMorganz/stylua-action@1.0.0
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ args: --check runtime/
+
+ - if: "!cancelled()"
name: lualint
run: ./ci/run_lint.sh lualint
diff --git a/.stylua.toml b/.stylua.toml
new file mode 100644
index 0000000000..255bfd939d
--- /dev/null
+++ b/.stylua.toml
@@ -0,0 +1,6 @@
+column_width = 120
+line_endings = "Unix"
+indent_type = "Spaces"
+indent_width = 2
+quote_style = "AutoPreferSingle"
+call_parentheses = "Always"
diff --git a/.styluaignore b/.styluaignore
new file mode 100644
index 0000000000..c1871de90a
--- /dev/null
+++ b/.styluaignore
@@ -0,0 +1,3 @@
+/scripts
+/src
+/test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01df172ed4..409face71c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -614,7 +614,6 @@ endif()
find_program(LUACHECK_PRG luacheck)
find_program(FLAKE8_PRG flake8)
-find_program(GPERF_PRG gperf)
include(InstallHelpers)
diff --git a/Makefile b/Makefile
index df4f2995d8..3039d84a6b 100644
--- a/Makefile
+++ b/Makefile
@@ -146,9 +146,16 @@ functionaltest: | nvim
functionaltest-lua: | nvim
+$(BUILD_TOOL) -C build functionaltest-lua
+stylua:
+ stylua --check runtime/
+
lualint: | build/.ran-cmake deps
$(BUILD_TOOL) -C build lualint
+_opt_stylua:
+ @command -v stylua && { $(MAKE) stylua; exit $$?; } \
+ || echo "SKIP: stylua (stylua not found)"
+
shlint:
@shellcheck --version | head -n 2
shellcheck scripts/vim-patch.sh
@@ -214,7 +221,7 @@ appimage:
appimage-%:
bash scripts/genappimage.sh $*
-lint: check-single-includes clint lualint _opt_pylint _opt_shlint _opt_commitlint
+lint: check-single-includes clint _opt_stylua lualint _opt_pylint _opt_shlint _opt_commitlint
# Generic pattern rules, allowing for `make build/bin/nvim` etc.
# Does not work with "Unix Makefiles".
@@ -226,4 +233,4 @@ $(DEPS_BUILD_DIR)/%: phony_force
$(BUILD_TOOL) -C $(DEPS_BUILD_DIR) $(patsubst $(DEPS_BUILD_DIR)/%,%,$@)
endif
-.PHONY: test lualint pylint shlint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install appimage checkprefix commitlint
+.PHONY: test stylua lualint pylint shlint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install appimage checkprefix commitlint
diff --git a/man/nvim.1 b/man/nvim.1
index 43dfc21dc7..9f35014ee8 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -188,7 +188,7 @@ loading plugins is also skipped.
Use
.Ar shada
instead of the default
-.Pa ~/.local/share/nvim/shada/main.shada .
+.Pa ~/.local/state/nvim/shada/main.shada .
If
.Ar shada
is
@@ -326,7 +326,7 @@ Print version information and exit.
.Sh ENVIRONMENT
.Bl -tag -width Fl
.It Ev NVIM_LOG_FILE
-Low-level log file, usually found at ~/.cache/nvim/log.
+Low-level log file, usually found at ~/.local/state/nvim/log.
:help $NVIM_LOG_FILE
.It Ev VIM
Used to locate user files, such as init.vim.
@@ -340,12 +340,20 @@ Path to the user-local configuration directory, see
Defaults to
.Pa ~/.config .
:help xdg
-.It Ev XDG_DATA_HOME
+.It Ev XDG_STATE_HOME
Like
.Ev XDG_CONFIG_HOME ,
but used to store data not generally edited by the user,
namely swap, backup, and ShaDa files.
Defaults to
+.Pa ~/.local/state .
+:help xdg
+.It Ev XDG_DATA_HOME
+Like
+.Ev XDG_CONFIG_HOME ,
+but used to store data not generally edited by the user,
+things like runtime files.
+Defaults to
.Pa ~/.local/share .
:help xdg
.It Ev VIMINIT
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 50fe60a0fc..36325fb0ba 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -426,6 +426,14 @@ Two ways to create a floating window:
To close it use |nvim_win_close()| or a command such as |:close|.
+To check whether a window is floating, check whether the `relative` option in
+its config is non-empty: >
+
+ if vim.api.nvim_win_get_config(window_id).relative ~= '' then
+ -- window with this window_id is floating
+ end
+>
+
Buffer text can be highlighted by typical mechanisms (syntax highlighting,
|api-highlights|). The |hl-NormalFloat| group highlights normal text;
'winhighlight' can be used as usual to override groups locally. Floats inherit
@@ -1711,17 +1719,49 @@ nvim_call_function({fn}, {args}) *nvim_call_function()*
Return: ~
Result of the function call
-nvim_command({command}) *nvim_command()*
- Executes an ex-command.
+nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
+ Executes an Ex command.
- On execution error: fails with VimL error, does not update
- v:errmsg.
+ Unlike |nvim_command()| this command takes a structured
+ Dictionary instead of a String. This allows for easier
+ construction and manipulation of an Ex command. This also
+ allows for things such as having spaces inside a command
+ argument, expanding filenames in a command that otherwise
+ doesn't expand filenames, etc.
Parameters: ~
- {command} Ex-command string
+ {cmd} Command to execute. Must be a Dictionary that can
+ contain the same values as the return value of
+ |nvim_parse_cmd()| except "addr", "nargs" and
+ "nextcmd" which are ignored if provided. All
+ values except for "cmd" are optional.
+ {opts} Optional parameters.
+ • output: (boolean, default false) Whether to
+ return command output.
+
+ Return: ~
+ Command output (non-error, non-shell |:!|) if `output` is
+ true, else empty string.
See also: ~
|nvim_exec()|
+ |nvim_command()|
+
+nvim_command({command}) *nvim_command()*
+ Executes an Ex command.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Prefer using |nvim_cmd()| or |nvim_exec()| over this. To
+ evaluate multiple lines of Vim script or an Ex command
+ directly, use |nvim_exec()|. To construct an Ex command using
+ a structured format and then execute it, use |nvim_cmd()|. To
+ modify an Ex command before evaluating it, use
+ |nvim_parse_cmd()| in conjunction with |nvim_cmd()|.
+
+ Parameters: ~
+ {command} Ex command string
nvim_eval({expr}) *nvim_eval()*
Evaluates a VimL |expression|. Dictionaries and Lists are
@@ -1737,7 +1777,7 @@ nvim_eval({expr}) *nvim_eval()*
Evaluation result or expanded object
nvim_exec({src}, {output}) *nvim_exec()*
- Executes Vimscript (multiline block of Ex-commands), like
+ Executes Vimscript (multiline block of Ex commands), like
anonymous |:source|.
Unlike |nvim_command()| this function supports heredocs,
@@ -1758,6 +1798,7 @@ nvim_exec({src}, {output}) *nvim_exec()*
See also: ~
|execute()|
|nvim_command()|
+ |nvim_cmd()|
nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
Parse command line.
@@ -2197,7 +2238,7 @@ nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{start} First line index
- {end} Last line index (exclusive)
+ {end} Last line index, exclusive
{strict_indexing} Whether out-of-bounds should be an
error.
@@ -2268,16 +2309,18 @@ nvim_buf_get_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
This differs from |nvim_buf_get_lines()| in that it allows
retrieving only portions of a line.
- Indexing is zero-based. Column indices are end-exclusive.
+ Indexing is zero-based. Row indices are end-inclusive, and
+ column indices are end-exclusive.
Prefer |nvim_buf_get_lines()| when retrieving entire lines.
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{start_row} First line index
- {start_col} Starting byte offset of first line
- {end_row} Last line index
- {end_col} Ending byte offset of last line (exclusive)
+ {start_col} Starting column (byte offset) on first line
+ {end_row} Last line index, inclusive
+ {end_col} Ending column (byte offset) on last line,
+ exclusive
{opts} Optional parameters. Currently unused.
Return: ~
@@ -2357,7 +2400,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{start} First line index
- {end} Last line index (exclusive)
+ {end} Last line index, exclusive
{strict_indexing} Whether out-of-bounds should be an
error.
{replacement} Array of lines to use as replacement
@@ -2407,25 +2450,27 @@ nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
{replacement})
Sets (replaces) a range in the buffer
- This is recommended over nvim_buf_set_lines when only
+ This is recommended over |nvim_buf_set_lines()| when only
modifying parts of a line, as extmarks will be preserved on
non-modified parts of the touched lines.
- Indexing is zero-based and end-exclusive.
+ Indexing is zero-based. Row indices are end-inclusive, and
+ column indices are end-exclusive.
- To insert text at a given index, set `start` and `end` ranges
- to the same index. To delete a range, set `replacement` to an
- array containing an empty string, or simply an empty array.
+ To insert text at a given `(row, column)` location, use
+ `start_row = end_row = row` and `start_col = end_col = col`.
+ To delete the text in a range, use `replacement = {}`.
- Prefer nvim_buf_set_lines when adding or deleting entire lines
- only.
+ Prefer |nvim_buf_set_lines()| if you are only adding or
+ deleting entire lines.
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
{start_row} First line index
- {start_col} First column
- {end_row} Last line index
- {end_col} Last column
+ {start_col} Starting column (byte offset) on first line
+ {end_row} Last line index, inclusive
+ {end_col} Ending column (byte offset) on last line,
+ exclusive
{replacement} Array of lines to use as replacement
nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index b9954dc99c..d197a2c62c 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2800,7 +2800,7 @@ getcmdcompltype() *getcmdcompltype()*
Return the type of the current command-line completion.
Only works when the command line is being edited, thus
requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
- See |command-completion| for the return string.
+ See |:command-completion| for the return string.
Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
Returns an empty string when completion is not defined.
@@ -4976,10 +4976,9 @@ matchfuzzy({list}, {str} [, {dict}]) *matchfuzzy()*
The optional {dict} argument always supports the following
items:
- matchseq When this item is present and {str} contains
- multiple words separated by white space, then
- returns only matches that contain the words in
- the given sequence.
+ matchseq When this item is present return only matches
+ that contain the characters in {str} in the
+ given sequence.
If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items:
@@ -7466,14 +7465,17 @@ stdpath({what}) *stdpath()* *E6100*
directories.
{what} Type Description ~
- cache String Cache directory. Arbitrary temporary
+ cache String Cache directory: arbitrary temporary
storage for plugins, etc.
- config String User configuration directory. The
- |init.vim| is stored here.
- config_dirs List Additional configuration directories.
+ config String User configuration directory. |init.vim|
+ is stored here.
+ config_dirs List Other configuration directories.
data String User data directory. The |shada-file|
is stored here.
- data_dirs List Additional data directories.
+ data_dirs List Other data directories.
+ log String Logs directory (for use by plugins too).
+ state String Session state directory: storage for file
+ drafts, undo history, shada, etc.
Example: >
:echo stdpath("config")
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 32936a7ee6..2446506dec 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -336,8 +336,8 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
that returns any of the above.
Parameters: ~
- {opts} table|nil When omitted or "nil", retrieve the
- current configuration. Otherwise, a
+ {opts} (table|nil) When omitted or "nil", retrieve
+ the current configuration. Otherwise, a
configuration table with the following keys:
• underline: (default true) Use underline for
diagnostics. Options:
@@ -401,7 +401,7 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
displayed before lower severities (e.g.
ERROR is displayed before WARN). Options:
• reverse: (boolean) Reverse sort order
- {namespace} number|nil Update the options for the given
+ {namespace} (number|nil) Update the options for the given
namespace. When omitted, update the global
diagnostic options.
@@ -409,28 +409,28 @@ disable({bufnr}, {namespace}) *vim.diagnostic.disable()*
Disable diagnostics in the given buffer.
Parameters: ~
- {bufnr} number|nil Buffer number, or 0 for current
+ {bufnr} (number|nil) Buffer number, or 0 for current
buffer. When omitted, disable diagnostics in
all buffers.
- {namespace} number|nil Only disable diagnostics for the
+ {namespace} (number|nil) Only disable diagnostics for the
given namespace.
enable({bufnr}, {namespace}) *vim.diagnostic.enable()*
Enable diagnostics in the given buffer.
Parameters: ~
- {bufnr} number|nil Buffer number, or 0 for current
+ {bufnr} (number|nil) Buffer number, or 0 for current
buffer. When omitted, enable diagnostics in
all buffers.
- {namespace} number|nil Only enable diagnostics for the
+ {namespace} (number|nil) Only enable diagnostics for the
given namespace.
fromqflist({list}) *vim.diagnostic.fromqflist()*
Convert a list of quickfix items to a list of diagnostics.
Parameters: ~
- {list} table A list of quickfix items from |getqflist()|
- or |getloclist()|.
+ {list} (table) A list of quickfix items from
+ |getqflist()| or |getloclist()|.
Return: ~
array of diagnostics |diagnostic-structure|
@@ -439,9 +439,10 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
Get current diagnostics.
Parameters: ~
- {bufnr} number|nil Buffer number to get diagnostics from.
- Use 0 for current buffer or nil for all buffers.
- {opts} table|nil A table with the following keys:
+ {bufnr} (number|nil) Buffer number to get diagnostics
+ from. Use 0 for current buffer or nil for all
+ buffers.
+ {opts} (table|nil) A table with the following keys:
• namespace: (number) Limit diagnostics to the
given namespace.
• lnum: (number) Limit diagnostics to the given
@@ -449,67 +450,68 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
• severity: See |diagnostic-severity|.
Return: ~
- table A list of diagnostic items |diagnostic-structure|.
+ (table) A list of diagnostic items |diagnostic-structure|.
get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata.
Parameters: ~
- {namespace} number Diagnostic namespace
+ {namespace} (number) Diagnostic namespace
Return: ~
- table Namespace metadata
+ (table) Namespace metadata
get_namespaces() *vim.diagnostic.get_namespaces()*
Get current diagnostic namespaces.
Return: ~
- table A list of active diagnostic namespaces
+ (table) A list of active diagnostic namespaces
|vim.diagnostic|.
get_next({opts}) *vim.diagnostic.get_next()*
Get the next diagnostic closest to the cursor position.
Parameters: ~
- {opts} table See |vim.diagnostic.goto_next()|
+ {opts} (table) See |vim.diagnostic.goto_next()|
Return: ~
- table Next diagnostic
+ (table) Next diagnostic
get_next_pos({opts}) *vim.diagnostic.get_next_pos()*
Return the position of the next diagnostic in the current
buffer.
Parameters: ~
- {opts} table See |vim.diagnostic.goto_next()|
+ {opts} (table) See |vim.diagnostic.goto_next()|
Return: ~
- table Next diagnostic position as a (row, col) tuple.
+ (table) Next diagnostic position as a (row, col) tuple.
get_prev({opts}) *vim.diagnostic.get_prev()*
Get the previous diagnostic closest to the cursor position.
Parameters: ~
- {opts} table See |vim.diagnostic.goto_next()|
+ {opts} (table) See |vim.diagnostic.goto_next()|
Return: ~
- table Previous diagnostic
+ (table) Previous diagnostic
get_prev_pos({opts}) *vim.diagnostic.get_prev_pos()*
Return the position of the previous diagnostic in the current
buffer.
Parameters: ~
- {opts} table See |vim.diagnostic.goto_next()|
+ {opts} (table) See |vim.diagnostic.goto_next()|
Return: ~
- table Previous diagnostic position as a (row, col) tuple.
+ (table) Previous diagnostic position as a (row, col)
+ tuple.
goto_next({opts}) *vim.diagnostic.goto_next()*
Move to the next diagnostic.
Parameters: ~
- {opts} table|nil Configuration table with the following
+ {opts} (table|nil) Configuration table with the following
keys:
• namespace: (number) Only consider diagnostics
from the given namespace.
@@ -533,7 +535,7 @@ goto_prev({opts}) *vim.diagnostic.goto_prev()*
Move to the previous diagnostic in the current buffer.
Parameters: ~
- {opts} table See |vim.diagnostic.goto_next()|
+ {opts} (table) See |vim.diagnostic.goto_next()|
hide({namespace}, {bufnr}) *vim.diagnostic.hide()*
Hide currently displayed diagnostics.
@@ -547,10 +549,10 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()*
|vim.diagnostic.disable()|.
Parameters: ~
- {namespace} number|nil Diagnostic namespace. When
+ {namespace} (number|nil) Diagnostic namespace. When
omitted, hide diagnostics from all
namespaces.
- {bufnr} number|nil Buffer number, or 0 for current
+ {bufnr} (number|nil) Buffer number, or 0 for current
buffer. When omitted, hide diagnostics in all
buffers.
@@ -573,16 +575,16 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
<
Parameters: ~
- {str} string String to parse diagnostics from.
- {pat} string Lua pattern with capture groups.
- {groups} table List of fields in a
+ {str} (string) String to parse diagnostics from.
+ {pat} (string) Lua pattern with capture groups.
+ {groups} (table) List of fields in a
|diagnostic-structure| to associate with
captures from {pat}.
- {severity_map} table A table mapping the severity field
+ {severity_map} (table) A table mapping the severity field
from {groups} with an item from
|vim.diagnostic.severity|.
- {defaults} table|nil Table of default values for any
- fields not listed in {groups}. When
+ {defaults} (table|nil) Table of default values for
+ any fields not listed in {groups}. When
omitted, numeric values default to 0 and
"severity" defaults to ERROR.
@@ -594,7 +596,7 @@ open_float({opts}, {...}) *vim.diagnostic.open_float()*
Show diagnostics in a floating window.
Parameters: ~
- {opts} table|nil Configuration table with the same keys
+ {opts} (table|nil) Configuration table with the same keys
as |vim.lsp.util.open_floating_preview()| in
addition to the following:
• bufnr: (number) Buffer number to show
@@ -665,10 +667,10 @@ reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
|vim.diagnostic.hide()|.
Parameters: ~
- {namespace} number|nil Diagnostic namespace. When
+ {namespace} (number|nil) Diagnostic namespace. When
omitted, remove diagnostics from all
namespaces.
- {bufnr} number|nil Remove diagnostics for the given
+ {bufnr} (number|nil) Remove diagnostics for the given
buffer. When omitted, diagnostics are removed
for all buffers.
@@ -676,18 +678,18 @@ set({namespace}, {bufnr}, {diagnostics}, {opts}) *vim.diagnostic.set()*
Set diagnostics for the given namespace and buffer.
Parameters: ~
- {namespace} number The diagnostic namespace
- {bufnr} number Buffer number
- {diagnostics} table A list of diagnostic items
+ {namespace} (number) The diagnostic namespace
+ {bufnr} (number) Buffer number
+ {diagnostics} (table) A list of diagnostic items
|diagnostic-structure|
- {opts} table|nil Display options to pass to
+ {opts} (table|nil) Display options to pass to
|vim.diagnostic.show()|
setloclist({opts}) *vim.diagnostic.setloclist()*
Add buffer diagnostics to the location list.
Parameters: ~
- {opts} table|nil Configuration table with the following
+ {opts} (table|nil) Configuration table with the following
keys:
• namespace: (number) Only add diagnostics from
the given namespace.
@@ -703,7 +705,7 @@ setqflist({opts}) *vim.diagnostic.setqflist()*
Add all diagnostics to the quickfix list.
Parameters: ~
- {opts} table|nil Configuration table with the following
+ {opts} (table|nil) Configuration table with the following
keys:
• namespace: (number) Only add diagnostics from
the given namespace.
@@ -718,20 +720,20 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
Display diagnostics for the given namespace and buffer.
Parameters: ~
- {namespace} number|nil Diagnostic namespace. When
+ {namespace} (number|nil) Diagnostic namespace. When
omitted, show diagnostics from all
namespaces.
- {bufnr} number|nil Buffer number, or 0 for current
- buffer. When omitted, show diagnostics in
- all buffers.
- {diagnostics} table|nil The diagnostics to display. When
- omitted, use the saved diagnostics for the
- given namespace and buffer. This can be
+ {bufnr} (number|nil) Buffer number, or 0 for
+ current buffer. When omitted, show
+ diagnostics in all buffers.
+ {diagnostics} (table|nil) The diagnostics to display.
+ When omitted, use the saved diagnostics for
+ the given namespace and buffer. This can be
used to display a list of diagnostics
without saving them or to display only a
subset of diagnostics. May not be used when
{namespace} or {bufnr} is nil.
- {opts} table|nil Display options. See
+ {opts} (table|nil) Display options. See
|vim.diagnostic.config()|.
toqflist({diagnostics}) *vim.diagnostic.toqflist()*
@@ -739,7 +741,7 @@ toqflist({diagnostics}) *vim.diagnostic.toqflist()*
can be passed to |setqflist()| or |setloclist()|.
Parameters: ~
- {diagnostics} table List of diagnostics
+ {diagnostics} (table) List of diagnostics
|diagnostic-structure|.
Return: ~
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 647feb6755..569c570624 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -495,8 +495,8 @@ buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()*
notification.
Parameters: ~
- {bufnr} number Buffer handle, or 0 for current
- {client_id} number Client id
+ {bufnr} (number) Buffer handle, or 0 for current
+ {client_id} (number) Client id
buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()*
Gets a map of client_id:client pairs for the given buffer,
@@ -668,11 +668,11 @@ for_each_buffer_client({bufnr}, {fn})
Invokes a function for each LSP client attached to a buffer.
Parameters: ~
- {bufnr} number Buffer number
- {fn} function Function to run on each client attached
- to buffer {bufnr}. The function takes the client,
- client ID, and buffer number as arguments.
- Example: >
+ {bufnr} (number) Buffer number
+ {fn} (function) Function to run on each client
+ attached to buffer {bufnr}. The function takes
+ the client, client ID, and buffer number as
+ arguments. Example: >
vim.lsp.for_each_buffer_client(0, function(client, client_id, bufnr)
print(vim.inspect(client))
@@ -690,7 +690,7 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`.
Parameters: ~
- {opts} table options for customizing the formatting
+ {opts} (table) options for customizing the formatting
expression which takes the following optional
keys:
• timeout_ms (default 500ms). The timeout period
@@ -707,7 +707,7 @@ get_buffers_by_client_id({client_id})
Returns list of buffers attached to client_id.
Parameters: ~
- {client_id} number client id
+ {client_id} (number) client id
Return: ~
list of buffer ids
@@ -717,7 +717,7 @@ get_client_by_id({client_id}) *vim.lsp.get_client_by_id()*
client may not yet be fully initialized.
Parameters: ~
- {client_id} number client id
+ {client_id} (number) client id
Return: ~
|vim.lsp.client| object, or nil
@@ -820,7 +820,7 @@ start_client({config}) *vim.lsp.start_client()*
language server if requested via
`workspace/configuration`. Keys are
case-sensitive.
- {commands} table Table that maps string of
+ {commands} (table) Table that maps string of
clientside commands to user-defined
functions. Commands passed to
start_client take precedence over the
@@ -908,10 +908,10 @@ start_client({config}) *vim.lsp.start_client()*
kill -15. If set to false, nvim
exits immediately after sending the
'shutdown' request to the server.
- {root_dir} string Directory where the LSP server
- will base its workspaceFolders,
- rootUri, and rootPath on
- initialization.
+ {root_dir} (string) Directory where the LSP
+ server will base its
+ workspaceFolders, rootUri, and
+ rootPath on initialization.
Return: ~
Client id. |vim.lsp.get_client_by_id()| Note: client may
@@ -935,7 +935,7 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()*
Parameters: ~
{client_id} client id or |vim.lsp.client| object, or list
thereof
- {force} boolean (optional) shutdown forcefully
+ {force} (boolean) (optional) shutdown forcefully
tagfunc({...}) *vim.lsp.tagfunc()*
Provides an interface between the built-in client and
@@ -980,7 +980,7 @@ code_action({options}) *vim.lsp.buf.code_action()*
position.
Parameters: ~
- {options} table|nil Optional table which holds the
+ {options} (table|nil) Optional table which holds the
following optional fields:
• context (table|nil): Corresponds to `CodeActionContext` of the LSP specification:
• diagnostics (table|nil): LSP`Diagnostic[]` . Inferred from the current position if not
@@ -1048,7 +1048,7 @@ execute_command({command_params}) *vim.lsp.buf.execute_command()*
Executes an LSP server command.
Parameters: ~
- {command_params} table A valid `ExecuteCommandParams`
+ {command_params} (table) A valid `ExecuteCommandParams`
object
See also: ~
@@ -1146,7 +1146,7 @@ formatting_sync({options}, {timeout_ms})
<
Parameters: ~
- {options} table|nil with valid `FormattingOptions`
+ {options} (table|nil) with valid `FormattingOptions`
entries
{timeout_ms} (number) Request timeout
@@ -1180,7 +1180,7 @@ range_code_action({context}, {start_pos}, {end_pos})
Performs |vim.lsp.buf.code_action()| for a given range.
Parameters: ~
- {context} table|nil `CodeActionContext` of the LSP specification:
+ {context} (table|nil) `CodeActionContext` of the LSP specification:
• diagnostics: (table|nil) LSP`Diagnostic[]` . Inferred from the current position if not
provided.
• only: (table|nil) List of LSP
@@ -1227,10 +1227,10 @@ rename({new_name}, {options}) *vim.lsp.buf.rename()*
Renames all references to the symbol under the cursor.
Parameters: ~
- {new_name} string|nil If not provided, the user will be
+ {new_name} (string|nil) If not provided, the user will be
prompted for a new name using
|vim.ui.input()|.
- {options} table|nil additional options
+ {options} (table|nil) additional options
• filter (function|nil): Predicate to filter
clients used for rename. Receives the
attached clients as argument and must return
@@ -1275,7 +1275,7 @@ get_namespace({client_id}) *vim.lsp.diagnostic.get_namespace()*
|vim.diagnostic|.
Parameters: ~
- {client_id} number The id of the LSP client
+ {client_id} (number) The id of the LSP client
*vim.lsp.diagnostic.on_publish_diagnostics()*
on_publish_diagnostics({_}, {result}, {ctx}, {config})
@@ -1305,7 +1305,7 @@ on_publish_diagnostics({_}, {result}, {ctx}, {config})
<
Parameters: ~
- {config} table Configuration table (see
+ {config} (table) Configuration table (see
|vim.diagnostic.config()|).
@@ -1316,20 +1316,20 @@ display({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.display()*
Display the lenses using virtual text
Parameters: ~
- {lenses} table of lenses to display (`CodeLens[] |
+ {lenses} (table) of lenses to display (`CodeLens[] |
null`)
- {bufnr} number
- {client_id} number
+ {bufnr} (number)
+ {client_id} (number)
get({bufnr}) *vim.lsp.codelens.get()*
Return all lenses for the given buffer
Parameters: ~
- {bufnr} number Buffer number. 0 can be used for the
+ {bufnr} (number) Buffer number. 0 can be used for the
current buffer.
Return: ~
- table (`CodeLens[]`)
+ (table) (`CodeLens[]`)
*vim.lsp.codelens.on_codelens()*
on_codelens({err}, {result}, {ctx}, {_})
@@ -1351,10 +1351,10 @@ save({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.save()*
Store lenses for a specific buffer and client
Parameters: ~
- {lenses} table of lenses to store (`CodeLens[] |
+ {lenses} (table) of lenses to store (`CodeLens[] |
null`)
- {bufnr} number
- {client_id} number
+ {bufnr} (number)
+ {client_id} (number)
==============================================================================
@@ -1372,7 +1372,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
<
Parameters: ~
- {config} table Configuration table.
+ {config} (table) Configuration table.
• border: (default=nil)
• Add borders to the floating window
• See |nvim_open_win()|
@@ -1392,7 +1392,7 @@ signature_help({_}, {result}, {ctx}, {config})
<
Parameters: ~
- {config} table Configuration table.
+ {config} (table) Configuration table.
• border: (default=nil)
• Add borders to the floating window
• See |vim.api.nvim_open_win()|
@@ -1420,9 +1420,9 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding})
Applies a list of text edits to a buffer.
Parameters: ~
- {text_edits} table list of `TextEdit` objects
- {bufnr} number Buffer id
- {offset_encoding} string utf-8|utf-16|utf-32
+ {text_edits} (table) list of `TextEdit` objects
+ {bufnr} (number) Buffer id
+ {offset_encoding} (string) utf-8|utf-16|utf-32
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
@@ -1432,24 +1432,24 @@ apply_workspace_edit({workspace_edit}, {offset_encoding})
Applies a `WorkspaceEdit`.
Parameters: ~
- {workspace_edit} table `WorkspaceEdit`
- {offset_encoding} string utf-8|utf-16|utf-32 (required)
+ {workspace_edit} (table) `WorkspaceEdit`
+ {offset_encoding} (string) utf-8|utf-16|utf-32 (required)
buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer.
Parameters: ~
- {bufnr} number Buffer id
+ {bufnr} (number) Buffer id
*vim.lsp.util.buf_highlight_references()*
buf_highlight_references({bufnr}, {references}, {offset_encoding})
Shows a list of document highlights for a certain buffer.
Parameters: ~
- {bufnr} number Buffer id
- {references} table List of `DocumentHighlight`
+ {bufnr} (number) Buffer id
+ {references} (table) List of `DocumentHighlight`
objects to highlight
- {offset_encoding} string One of "utf-8", "utf-16",
+ {offset_encoding} (string) One of "utf-8", "utf-16",
"utf-32".
See also: ~
@@ -1464,9 +1464,9 @@ character_offset({buf}, {row}, {col}, {offset_encoding})
{buf} buffer id (0 for current)
{row} 0-indexed line
{col} 0-indexed byte offset in line
- {offset_encoding} string utf-8|utf-16|utf-32|nil defaults
- to `offset_encoding` of first client of
- `buf`
+ {offset_encoding} (string) utf-8|utf-16|utf-32|nil
+ defaults to `offset_encoding` of first
+ client of `buf`
Return: ~
(number, number) `offset_encoding` index of the character
@@ -1543,8 +1543,8 @@ jump_to_location({location}, {offset_encoding})
Jumps to a location.
Parameters: ~
- {location} table (`Location`|`LocationLink`)
- {offset_encoding} string utf-8|utf-16|utf-32 (required)
+ {location} (table) (`Location`|`LocationLink`)
+ {offset_encoding} (string) utf-8|utf-16|utf-32 (required)
Return: ~
`true` if the jump succeeded
@@ -1559,9 +1559,9 @@ locations_to_items({locations}, {offset_encoding})
|setqflist()| or |setloclist()|.
Parameters: ~
- {locations} table list of `Location`s or
+ {locations} (table) list of `Location`s or
`LocationLink`s
- {offset_encoding} string offset_encoding for locations
+ {offset_encoding} (string) offset_encoding for locations
utf-8|utf-16|utf-32
Return: ~
@@ -1606,7 +1606,7 @@ make_formatting_params({options})
buffer and cursor position.
Parameters: ~
- {options} table|nil with valid `FormattingOptions`
+ {options} (table|nil) with valid `FormattingOptions`
entries
Return: ~
@@ -1629,9 +1629,9 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
end of the last visual selection.
{bufnr} (optional, number): buffer handle or 0
for current, defaults to current
- {offset_encoding} string utf-8|utf-16|utf-32|nil defaults
- to `offset_encoding` of first client of
- `bufnr`
+ {offset_encoding} (string) utf-8|utf-16|utf-32|nil
+ defaults to `offset_encoding` of first
+ client of `bufnr`
Return: ~
{ textDocument = { uri = `current_file_uri` }, range = {
@@ -1645,9 +1645,9 @@ make_position_params({window}, {offset_encoding})
Parameters: ~
{window} (optional, number): window handle or 0
for current, defaults to current
- {offset_encoding} string utf-8|utf-16|utf-32|nil defaults
- to `offset_encoding` of first client of
- buffer of `window`
+ {offset_encoding} (string) utf-8|utf-16|utf-32|nil
+ defaults to `offset_encoding` of first
+ client of buffer of `window`
Return: ~
`TextDocumentPositionParams` object
@@ -1666,9 +1666,9 @@ make_range_params({window}, {offset_encoding})
Parameters: ~
{window} (optional, number): window handle or 0
for current, defaults to current
- {offset_encoding} string utf-8|utf-16|utf-32|nil defaults
- to `offset_encoding` of first client of
- buffer of `window`
+ {offset_encoding} (string) utf-8|utf-16|utf-32|nil
+ defaults to `offset_encoding` of first
+ client of buffer of `window`
Return: ~
{ textDocument = { uri = `current_file_uri` }, range = {
@@ -1702,9 +1702,9 @@ open_floating_preview({contents}, {syntax}, {opts})
Shows contents in a floating window.
Parameters: ~
- {contents} table of lines to show in window
- {syntax} string of syntax to set for opened buffer
- {opts} table with optional fields (additional keys
+ {contents} (table) of lines to show in window
+ {syntax} (string) of syntax to set for opened buffer
+ {opts} (table) with optional fields (additional keys
are passed on to |vim.api.nvim_open_win()|)
• height: (number) height of floating window
• width: (number) width of floating window
@@ -1739,10 +1739,10 @@ parse_snippet({input}) *vim.lsp.util.parse_snippet()*
Parses snippets in a completion entry.
Parameters: ~
- {input} string unparsed snippet
+ {input} (string) unparsed snippet
Return: ~
- string parsed snippet
+ (string) parsed snippet
preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
Previews a location in a floating window
@@ -1795,7 +1795,7 @@ stylize_markdown({bufnr}, {contents}, {opts})
`open_floating_preview` instead
Parameters: ~
- {contents} table of lines to show in window
+ {contents} (table) of lines to show in window
{opts} dictionary with optional fields
• height of floating window
• width of floating window
@@ -1873,14 +1873,15 @@ get_level() *vim.lsp.log.get_level()*
Gets the current log level.
Return: ~
- string current log level
+ (string) current log level
set_format_func({handle}) *vim.lsp.log.set_format_func()*
Sets formatting function used to format logs
Parameters: ~
- {handle} function function to apply to logging arguments,
- pass vim.inspect for multi-line formatting
+ {handle} (function) function to apply to logging
+ arguments, pass vim.inspect for multi-line
+ formatting
set_level({level}) *vim.lsp.log.set_level()*
Sets the current log level.
@@ -1892,7 +1893,7 @@ should_log({level}) *vim.lsp.log.should_log()*
Checks whether the level is sufficient for logging.
Parameters: ~
- {level} number log level
+ {level} (number) log level
Return: ~
(bool) true if would log, false if not
@@ -1998,19 +1999,19 @@ compute_diff({prev_lines}, {curr_lines}, {firstline}, {lastline},
curr lines
Parameters: ~
- {prev_lines} table list of lines
- {curr_lines} table list of lines
- {firstline} number line to begin search for first
+ {prev_lines} (table) list of lines
+ {curr_lines} (table) list of lines
+ {firstline} (number) line to begin search for first
difference
- {lastline} number line to begin search in
+ {lastline} (number) line to begin search in
old_lines for last difference
- {new_lastline} number line to begin search in
+ {new_lastline} (number) line to begin search in
new_lines for last difference
- {offset_encoding} string encoding requested by language
+ {offset_encoding} (string) encoding requested by language
server
Return: ~
- table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent
+ (table) TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent
==============================================================================
@@ -2027,10 +2028,10 @@ resolve_capabilities({server_capabilities})
capabilities.
Parameters: ~
- {server_capabilities} table Table of capabilities
+ {server_capabilities} (table) Table of capabilities
supported by the server
Return: ~
- table Normalized table of capabilities
+ (table) Normalized table of capabilities
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 534a40ff4f..150a3d18e9 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -4,52 +4,52 @@
NVIM REFERENCE MANUAL
-Lua engine *lua* *Lua*
+Lua engine *lua* *Lua*
- Type |gO| to see the table of contents.
+ Type |gO| to see the table of contents.
==============================================================================
-INTRODUCTION *lua-intro*
+INTRODUCTION *lua-intro*
-The Lua 5.1 language is builtin and always available. Try this command to get
+The Lua 5.1 language is builtin and always available. Try this command to get
an idea of what lurks beneath: >
:lua print(vim.inspect(package.loaded))
-
-Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
+<
+Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
"editor stdlib" (|builtin-functions| and Ex commands) and the |API|, all of
which can be used from Lua code. A good overview of using Lua in neovim is
given by https://github.com/nanotee/nvim-lua-guide.
The |:source| and |:runtime| commands can run Lua scripts as well as Vim
-scripts. Lua modules can be loaded with `require('name')`, which
+scripts. Lua modules can be loaded with `require('name')`, which
conventionally returns a table but can return any value.
See |lua-require| for details on how Nvim finds and loads Lua modules.
See |lua-require-example| for an example of how to write and use a module.
==============================================================================
-IMPORTING LUA MODULES *lua-require*
+IMPORTING LUA MODULES *lua-require*
Modules are searched for under the directories specified in 'runtimepath', in
-the order they appear. Any `.` in the module name is treated as a directory
-separator when searching. For a module `foo.bar`, each directory is searched
-for `lua/foo/bar.lua`, then `lua/foo/bar/init.lua`. If no files are found,
+the order they appear. Any `.` in the module name is treated as a directory
+separator when searching. For a module `foo.bar`, each directory is searched
+for `lua/foo/bar.lua`, then `lua/foo/bar/init.lua`. If no files are found,
the directories are searched again for a shared library with a name matching
-`lua/foo/bar.?`, where `?` is a list of suffixes (such as `so` or `dll`)
-derived from the initial value of `package.cpath`. If still no files are
-found, Nvim falls back to Lua's default search mechanism. The first script
-found is run and `require()` returns the value returned by the script if any,
-else `true`.
-
-The return value is cached after the first call to `require()` for each
-module, with subsequent calls returning the cached value without searching for
-or executing any script. For further details on `require()`, see the Lua
+`lua/foo/bar.?`, where `?` is a list of suffixes (such as `so` or `dll`) derived from
+the initial value of `package.cpath`. If still no files are found, Nvim falls
+back to Lua's default search mechanism. The first script found is run and
+`require()` returns the value returned by the script if any, else `true`.
+
+The return value is cached after the first call to `require()` for each module,
+with subsequent calls returning the cached value without searching for, or
+executing any script. For further details on `require()`, see the Lua
documentation at https://www.lua.org/manual/5.1/manual.html#pdf-require.
For example, if 'runtimepath' is `foo,bar` and `package.cpath` was
`./?.so;./?.dll` at startup, `require('mod')` searches these paths in order
and loads the first module found:
+
foo/lua/mod.lua
foo/lua/mod/init.lua
bar/lua/mod.lua
@@ -59,35 +59,34 @@ and loads the first module found:
bar/lua/mod.so
bar/lua/mod.dll
- *lua-package-path*
-Nvim automatically adjusts `package.path` and `package.cpath` according to
-effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
-changed. `package.path` is adjusted by simply appending `/lua/?.lua` and
+Nvim automatically adjusts `package.path` and `package.cpath` according to the
+effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
+changed. `package.path` is adjusted by simply appending `/lua/?.lua` and
`/lua/?/init.lua` to each directory from 'runtimepath' (`/` is actually the
first character of `package.config`).
Similarly to `package.path`, modified directories from 'runtimepath' are also
-added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and
+added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and
`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of
-the existing `package.cpath` are used. Example:
+the existing `package.cpath` are used. Example:
1. Given that
- 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`;
- - initial (defined at compile-time or derived from
- `$LUA_CPATH`/`$LUA_INIT`) `package.cpath` contains
+ - initial (defined at compile-time or derived from
+ `$LUA_CPATH`/`$LUA_INIT`) `package.cpath` contains
`./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`.
-2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in
- order: parts of the path starting from the first path component containing
+2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in
+ order: parts of the path starting from the first path component containing
question mark and preceding path separator.
-3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same
- as the suffix of the first path from `package.path` (i.e. `./?.so`). Which
+3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same
+ as the suffix of the first path from `package.path` (i.e. `./?.so`). Which
leaves `/?.so` and `/a?d/j/g.elf`, in this order.
-4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The
- second one contains semicolon which is a paths separator so it is out,
+4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The
+ second one contains a semicolon which is a paths separator so it is out,
leaving only `/foo/bar` and `/abc`, in order.
-5. The cartesian product of paths from 4. and suffixes from 3. is taken,
- giving four variants. In each variant `/lua` path segment is inserted
- between path and suffix, leaving
+5. The cartesian product of paths from 4. and suffixes from 3. is taken,
+ giving four variants. In each variant, a `/lua` path segment is inserted
+ between path and suffix, leaving:
- `/foo/bar/lua/?.so`
- `/foo/bar/lua/a?d/j/g.elf`
@@ -107,28 +106,28 @@ Note:
- To track 'runtimepath' updates, paths added at previous update are
remembered and removed at the next update, while all paths derived from the
- new 'runtimepath' are prepended as described above. This allows removing
+ new 'runtimepath' are prepended as described above. This allows removing
paths when path is removed from 'runtimepath', adding paths when they are
added and reordering `package.path`/`package.cpath` content if 'runtimepath'
was reordered.
- Although adjustments happen automatically, Nvim does not track current
- values of `package.path` or `package.cpath`. If you happen to delete some
+ values of `package.path` or `package.cpath`. If you happen to delete some
paths from there you can set 'runtimepath' to trigger an update: >
let &runtimepath = &runtimepath
- Skipping paths from 'runtimepath' which contain semicolons applies both to
- `package.path` and `package.cpath`. Given that there are some badly written
- plugins using shell which will not work with paths containing semicolons it
- is better to not have them in 'runtimepath' at all.
+ `package.path` and `package.cpath`. Given that there are some badly written
+ plugins using shell, which will not work with paths containing semicolons,
+ it is better to not have them in 'runtimepath' at all.
==============================================================================
-Lua Syntax Information *lua-syntax-help*
+Lua Syntax Information *lua-syntax-help*
While Lua has a simple syntax, there are a few things to understand,
particularly when looking at the documentation above.
- *lua-syntax-call-function*
+ *lua-syntax-call-function*
Lua functions can be called in multiple ways. Consider the function: >
@@ -136,8 +135,7 @@ Lua functions can be called in multiple ways. Consider the function: >
print("A is: ", a)
print("B is: ", b)
end
-
-
+<
The first way to call this function is: >
example_func(1, 2)
@@ -154,7 +152,6 @@ not supplied are automatically set to `nil`. For example: >
-- A is: 1
-- B is: nil
<
-
Additionally, if any extra parameters are passed, they are discarded
completely.
@@ -172,18 +169,16 @@ single dictionary, for example: >
func_with_opts { foo = true, filename = "hello.world" }
<
-
In this style, each "parameter" is passed via keyword. It is still valid
to call the function in the standard style: >
func_with_opts({ foo = true, filename = "hello.world" })
<
-
But often in the documentation, you will see the former rather than the
latter style due to its brevity.
==============================================================================
-Lua Patterns *lua-patterns*
+Lua Patterns *lua-patterns*
For performance reasons, Lua does not support regular expressions natively.
Instead, the Lua `string` standard library allows manipulations using a
@@ -207,13 +202,13 @@ For more complex matching, Vim regular expressions can be used from Lua
through |vim.regex()|.
------------------------------------------------------------------------------
-LUA PLUGIN EXAMPLE *lua-require-example*
+LUA PLUGIN EXAMPLE *lua-require-example*
-The following example plugin adds a command `:MakeCharBlob` which transforms
-current buffer into a long `unsigned char` array. Lua contains transformation
-function in a module `lua/charblob.lua` which is imported in
-`autoload/charblob.vim` (`require("charblob")`). Example plugin is supposed
-to be put into any directory from 'runtimepath', e.g. `~/.config/nvim` (in
+The following example plugin adds a command `:MakeCharBlob` which transforms
+current buffer into a long `unsigned char` array. Lua contains transformation
+function in a module `lua/charblob.lua` which is imported in
+`autoload/charblob.vim` (`require("charblob")`). Example plugin is supposed
+to be put into any directory from 'runtimepath', e.g. `~/.config/nvim` (in
this case `lua/charblob.lua` means `~/.config/nvim/lua/charblob.lua`).
autoload/charblob.vim: >
@@ -223,7 +218,7 @@ autoload/charblob.vim: >
\ 'require("charblob").encode(unpack(_A))',
\ [getline(1, '$'), &textwidth, ' ']))
endfunction
-
+<
plugin/charblob.vim: >
if exists('g:charblob_loaded')
@@ -232,7 +227,7 @@ plugin/charblob.vim: >
let g:charblob_loaded = 1
command MakeCharBlob :call charblob#encode_buffer()
-
+<
lua/charblob.lua: >
local function charblob_bytes_iter(lines)
@@ -282,9 +277,9 @@ lua/charblob.lua: >
bytes_iter = charblob_bytes_iter,
encode = charblob_encode,
}
-
+<
==============================================================================
-COMMANDS *lua-commands*
+COMMANDS *lua-commands*
These commands execute a Lua chunk from either the command line (:lua, :luado)
or a file (:luafile) on the given line [range]. As always in Lua, each chunk
@@ -295,10 +290,10 @@ command calls. The |lua-stdlib| modules, user modules, and anything else on
The Lua print() function redirects its output to the Nvim message area, with
arguments separated by " " (space) instead of "\t" (tab).
- *:lua*
+ *:lua*
:[range]lua {chunk}
Executes Lua chunk {chunk}.
- if {chunk} starts with "=" the rest of the chunk is
+ If {chunk} starts with "=" the rest of the chunk is
evaluated as an expression and printed. `:lua =expr`
is equivalent to `:lua print(vim.inspect(expr))`
Examples: >
@@ -308,7 +303,7 @@ arguments separated by " " (space) instead of "\t" (tab).
< To see the LuaJIT version: >
:lua =jit.version
<
- *:lua-heredoc*
+ *:lua-heredoc*
:[range]lua << [endmarker]
{script}
{endmarker}
@@ -328,11 +323,11 @@ arguments separated by " " (space) instead of "\t" (tab).
linenr, #curline))
EOF
endfunction
-
-< Note that the `local` variables will disappear when
+<
+ Note that the `local` variables will disappear when
the block finishes. But not globals.
- *:luado*
+ *:luado*
:[range]luado {body} Executes Lua chunk "function(line, linenr) {body} end"
for each buffer line in [range], where `line` is the
current line text (without <EOL>), and `linenr` is the
@@ -349,8 +344,7 @@ arguments separated by " " (space) instead of "\t" (tab).
:lua bp = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" }
:luado if bp:match(line) then return "-->\t" .. line end
<
-
- *:luafile*
+ *:luafile*
:[range]luafile {file}
Execute Lua script in {file}.
The whole argument is used as the filename (like
@@ -363,19 +357,19 @@ arguments separated by " " (space) instead of "\t" (tab).
<
==============================================================================
-luaeval() *lua-eval* *luaeval()*
+luaeval() *lua-eval* *luaeval()*
The (dual) equivalent of "vim.eval" for passing Lua values to Nvim is
-"luaeval". "luaeval" takes an expression string and an optional argument used
-for _A inside expression and returns the result of the expression. It is
-semantically equivalent in Lua to:
->
+"luaeval". "luaeval" takes an expression string and an optional argument used
+for _A inside expression and returns the result of the expression. It is
+semantically equivalent in Lua to: >
+
local chunkheader = "local _A = select(1, ...) return "
function luaeval (expstr, arg)
local chunk = assert(loadstring(chunkheader .. expstr, "luaeval"))
return chunk(arg) -- return typval
end
-
+<
Lua nils, numbers, strings, tables and booleans are converted to their
respective Vimscript types. If a Lua string contains a NUL byte, it will be
converted to a |Blob|. Conversion of other Lua types is an error.
@@ -387,22 +381,22 @@ Example: >
42
:echo luaeval('string.match(_A, "[a-z]+")', 'XYXfoo123')
foo
-
+<
Lua tables are used as both dictionaries and lists, so it is impossible to
determine whether empty table is meant to be empty list or empty dictionary.
Additionally Lua does not have integer numbers. To distinguish between these
cases there is the following agreement:
0. Empty table is empty list.
-1. Table with N incrementally growing integral numbers, starting from 1 and
+1. Table with N incrementally growing integral numbers, starting from 1 and
ending with N is considered to be a list.
-2. Table with string keys, none of which contains NUL byte, is considered to
+2. Table with string keys, none of which contains NUL byte, is considered to
be a dictionary.
-3. Table with string keys, at least one of which contains NUL byte, is also
- considered to be a dictionary, but this time it is converted to
+3. Table with string keys, at least one of which contains NUL byte, is also
+ considered to be a dictionary, but this time it is converted to
a |msgpack-special-map|.
- *lua-special-tbl*
-4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
+ *lua-special-tbl*
+4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
value:
- `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to
a floating-point 1.0. Note that by default integral Lua numbers are
@@ -425,14 +419,14 @@ Examples: >
: return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y})
: endfunction
:echo Rand(1,10)
-
-Note: second argument to `luaeval` is converted ("marshalled") from Vimscript
+<
+Note: Second argument to `luaeval` is converted ("marshalled") from Vimscript
to Lua, so changes to Lua containers do not affect values in Vimscript. Return
value is also always converted. When converting, |msgpack-special-dict|s are
treated specially.
==============================================================================
-Vimscript v:lua interface *v:lua-call*
+Vimscript v:lua interface *v:lua-call*
From Vimscript the special `v:lua` prefix can be used to call Lua functions
which are global or accessible from global tables. The expression >
@@ -447,7 +441,7 @@ is equivalent to the Lua chunk >
In addition, functions of packages can be accessed like >
v:lua.require'mypack'.func(arg1, arg2)
v:lua.require'mypack.submod'.func(arg1, arg2)
-Note: only single quote form without parens is allowed. Using
+Note: Only single quote form without parens is allowed. Using
`require"mypack"` or `require('mypack')` as prefixes do NOT work (the latter
is still valid as a function call of itself, in case require returns a useful
value).
@@ -455,7 +449,7 @@ value).
The `v:lua` prefix may be used to call Lua functions as |method|s. For
example: >
arg1->v:lua.somemod.func(arg2)
-
+<
You can use `v:lua` in "func" options like 'tagfunc', 'omnifunc', etc.
For example consider the following Lua omnifunc handler: >
@@ -468,7 +462,7 @@ For example consider the following Lua omnifunc handler: >
end
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc')
-Note: the module ("mymod" in the above example) must either be a Lua global,
+Note: The module ("mymod" in the above example) must either be a Lua global,
or use the require syntax as specified above to access it from a package.
Note: `v:lua` without a call is not allowed in a Vimscript expression:
@@ -478,13 +472,12 @@ Note: `v:lua` without a call is not allowed in a Vimscript expression:
call SomeFunc(v:lua.mycallback) " Error
let g:foo = v:lua " Error
let g:foo = v:['lua'] " Error
-
-
+<
==============================================================================
-Lua standard modules *lua-stdlib*
+Lua standard modules *lua-stdlib*
The Nvim Lua "standard library" (stdlib) is the `vim` module, which exposes
-various functions and sub-modules. It is always loaded, thus require("vim")
+various functions and sub-modules. It is always loaded, thus `require("vim")`
is unnecessary.
You can peek at the module properties: >
@@ -515,34 +508,35 @@ Note that underscore-prefixed functions (e.g. "_os_proc_children") are
internal/private and must not be used by plugins.
------------------------------------------------------------------------------
-VIM.LOOP *lua-loop* *vim.loop*
+VIM.LOOP *lua-loop* *vim.loop*
-`vim.loop` exposes all features of the Nvim event-loop. This is a low-level
+`vim.loop` exposes all features of the Nvim event-loop. This is a low-level
API that provides functionality for networking, filesystem, and process
-management. Try this command to see available functions: >
+management. Try this command to see available functions: >
:lua print(vim.inspect(vim.loop))
-
+<
Reference: https://github.com/luvit/luv/blob/master/docs.md
Examples: https://github.com/luvit/luv/tree/master/examples
- *E5560* *lua-loop-callbacks*
+ *E5560* *lua-loop-callbacks*
It is an error to directly invoke `vim.api` functions (except |api-fast|) in
-`vim.loop` callbacks. For example, this is an error: >
+`vim.loop` callbacks. For example, this is an error: >
local timer = vim.loop.new_timer()
timer:start(1000, 0, function()
vim.api.nvim_command('echomsg "test"')
end)
-
+<
To avoid the error use |vim.schedule_wrap()| to defer the callback: >
local timer = vim.loop.new_timer()
timer:start(1000, 0, vim.schedule_wrap(function()
vim.api.nvim_command('echomsg "test"')
end))
-
-(For one-shot timers, see |vim.defer_fn()|, which automatically adds the wrapping.)
+<
+(For one-shot timers, see |vim.defer_fn()|, which automatically adds the
+wrapping.)
Example: repeating timer
1. Save this code to a file.
@@ -560,9 +554,8 @@ Example: repeating timer
i = i + 1
end)
print('sleeping');
-
-
-Example: File-change detection *watch-file*
+<
+Example: File-change detection *watch-file*
1. Save this code to a file.
2. Execute it with ":luafile %".
3. Use ":Watch %" to watch any file.
@@ -586,9 +579,8 @@ Example: File-change detection *watch-file*
end
vim.api.nvim_command(
"command! -nargs=1 Watch call luaeval('watch_file(_A)', expand('<args>'))")
-
-
-Example: TCP echo-server *tcp-server*
+<
+Example: TCP echo-server *tcp-server*
1. Save this code to a file.
2. Execute it with ":luafile %".
3. Note the port number.
@@ -616,9 +608,8 @@ Example: TCP echo-server *tcp-server*
end)
end)
print('TCP echo-server listening on port: '..server:getsockname().port)
-
-
-Multithreading *lua-loop-threading*
+<
+Multithreading *lua-loop-threading*
Plugins can perform work in separate (os-level) threads using the threading
APIs in luv, for instance `vim.loop.new_thread`. Note that every thread
@@ -638,7 +629,7 @@ A subset of the `vim.*` API is available in threads. This includes:
- `vim.is_thread()` returns true from a non-main thread.
------------------------------------------------------------------------------
-VIM.HIGHLIGHT *lua-highlight*
+VIM.HIGHLIGHT *lua-highlight*
Nvim includes a function for highlighting a selection on yank (see for example
https://github.com/machakann/vim-highlightedyank). To enable it, add
@@ -654,8 +645,7 @@ If you want to exclude visual selections from highlighting on yank, use
>
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()*
Highlights the yanked text. The fields of the optional dict {opts}
control the highlight:
- {higroup} highlight group for yanked region (default |hl-IncSearch|)
@@ -678,12 +668,12 @@ vim.highlight.range({bufnr}, {ns}, {hlgroup}, {start}, {finish}, {opts})
{opts} optional parameters:
• `regtype`: type of range (characterwise, linewise,
or blockwise, see |setreg|), default `'v'`
- • `inclusive`: range includes end position, default
- `false`
+ • `inclusive`: range includes end position,
+ default `false`
• `priority`: priority of highlight, default
`vim.highlight.user` (see below)
-vim.highlight.priorities *vim.highlight.priorities*
+vim.highlight.priorities *vim.highlight.priorities*
Table with default priorities used for highlighting:
• `syntax`: `50`, used for standard syntax highlighting
@@ -693,19 +683,19 @@ vim.highlight.priorities *vim.highlight.priorities*
document symbols or `on_yank` autocommands
------------------------------------------------------------------------------
-VIM.REGEX *lua-regex*
+VIM.REGEX *lua-regex*
Vim regexes can be used directly from lua. Currently they only allow
matching within a single line.
-vim.regex({re}) *vim.regex()*
+vim.regex({re}) *vim.regex()*
Parse the Vim regex {re} and return a regex object. Regexes are
"magic" and case-insensitive by default, regardless of 'magic' and
- 'ignorecase'. The can be controlled with flags, see |/magic|.
+ 'ignorecase'. They can be controlled with flags, see |/magic|.
Methods on the regex object:
-regex:match_str({str}) *regex:match_str()*
+regex:match_str({str}) *regex:match_str()*
Match the string against the regex. If the string should match the
regex precisely, surround the regex with `^` and `$`.
If the was a match, the byte indices for the beginning and end of
@@ -713,7 +703,7 @@ regex:match_str({str}) *regex:match_str()*
As any integer is truth-y, `regex:match()` can be directly used
as a condition in an if-statement.
-regex:match_line({bufnr}, {line_idx}[, {start}, {end}]) *regex:match_line()*
+regex:match_line({bufnr}, {line_idx}[, {start}, {end}]) *regex:match_line()*
Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and
{end} are supplied, match only this byte index range. Otherwise see
|regex:match_str()|. If {start} is used, then the returned byte
@@ -728,18 +718,19 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
1-based.
Examples: >
- vim.diff('a\n', 'b\nc\n')
- -->
- @@ -1 +1,2 @@
- -a
- +b
- +c
-
- vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
- -->
- {
- {1, 1, 1, 2}
- }
+
+ vim.diff('a\n', 'b\nc\n')
+ -->
+ @@ -1 +1,2 @@
+ -a
+ +b
+ +c
+
+ vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
+ -->
+ {
+ {1, 1, 1, 2}
+ }
<
Parameters: ~
{a} First string to compare
@@ -757,7 +748,7 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
• `result_type` (string): Form of the returned diff:
• "unified": (default) String in unified format.
• "indices": Array of hunk locations.
- Note this option is ignored if `on_hunk` is
+ Note: This option is ignored if `on_hunk` is
used.
• `algorithm` (string):
Diff algorithm to use. Values:
@@ -792,31 +783,31 @@ VIM.MPACK *lua-mpack*
The *vim.mpack* module provides encoding and decoding of Lua objects to and
from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
-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.
-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.
------------------------------------------------------------------------------
-VIM.SPELL *lua-spell*
+VIM.SPELL *lua-spell*
-vim.spell.check({str}) *vim.spell.check()*
+vim.spell.check({str}) *vim.spell.check()*
Check {str} for spelling errors. Similar to the Vimscript function
|spellbadword()|.
Note: The behaviour of this function is dependent on: 'spelllang',
- 'spellfile', 'spellcapcheck' and 'spelloptions' which can all be local
- to the buffer. Consider calling this with |nvim_buf_call()|.
+ 'spellfile', 'spellcapcheck' and 'spelloptions' which can all be
+ local to the buffer. Consider calling this with |nvim_buf_call()|.
Example: >
+
vim.spell.check("the quik brown fox")
-->
{
{'quik', 'bad', 4}
}
<
-
Parameters: ~
{str} String to spell check.
@@ -831,24 +822,24 @@ vim.spell.check({str}) *vim.spell.check()*
- The position in {str} where the word begins.
------------------------------------------------------------------------------
-VIM *lua-builtin*
+VIM *lua-builtin*
-vim.api.{func}({...}) *vim.api*
+vim.api.{func}({...}) *vim.api*
Invokes Nvim |API| function {func} with arguments {...}.
Example: call the "nvim_get_current_line()" API function: >
print(tostring(vim.api.nvim_get_current_line()))
-vim.version() *vim.version*
+vim.version() *vim.version*
Gets the version of the current Nvim build.
-vim.in_fast_event() *vim.in_fast_event()*
+vim.in_fast_event() *vim.in_fast_event()*
Returns true if the code is executing as part of a "fast" event
handler, where most of the API is disabled. These are low-level events
(e.g. |lua-loop-callbacks|) which can be invoked whenever Nvim polls
- for input. When this is `false` most API functions are callable (but
+ for input. When this is `false` most API functions are callable (but
may be subject to other restrictions such as |textlock|).
-vim.NIL *vim.NIL*
+vim.NIL *vim.NIL*
Special value representing NIL in |RPC| and |v:null| in Vimscript
conversion, and similar cases. Lua `nil` cannot be used as part of
a Lua table representing a Dictionary or Array, because it is
@@ -860,10 +851,10 @@ vim.empty_dict() *vim.empty_dict()*
Vimscript or API types. Nvim by default converts an empty table `{}`
without this metatable to an list/array.
- Note: if numeric keys are present in the table, Nvim ignores the
+ Note: If numeric keys are present in the table, Nvim ignores the
metatable marker and converts the dict to a list/array anyway.
-vim.rpcnotify({channel}, {method}[, {args}...]) *vim.rpcnotify()*
+vim.rpcnotify({channel}, {method}[, {args}...]) *vim.rpcnotify()*
Sends {event} to {channel} via |RPC| and returns immediately. If
{channel} is 0, the event is broadcast to all channels.
@@ -876,12 +867,12 @@ vim.rpcrequest({channel}, {method}[, {args}...]) *vim.rpcrequest()*
Note: NIL values as part of the return value is represented as
|vim.NIL| special value
-vim.stricmp({a}, {b}) *vim.stricmp()*
- Compares strings case-insensitively. Returns 0, 1 or -1 if strings
+vim.stricmp({a}, {b}) *vim.stricmp()*
+ Compares strings case-insensitively. Returns 0, 1 or -1 if strings
are equal, {a} is greater than {b} or {a} is lesser than {b},
respectively.
-vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
+vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
supplied, the length of the string is used. All indices are zero-based.
Returns two values: the UTF-32 and UTF-16 indices respectively.
@@ -891,21 +882,21 @@ vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
point each. An {index} in the middle of a UTF-8 sequence is rounded
upwards to the end of that sequence.
-vim.str_byteindex({str}, {index}[, {use_utf16}]) *vim.str_byteindex()*
+vim.str_byteindex({str}, {index}[, {use_utf16}]) *vim.str_byteindex()*
Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not
supplied, it defaults to false (use UTF-32). Returns the byte index.
- Invalid UTF-8 and NUL is treated like by |vim.str_byteindex()|. An {index}
- in the middle of a UTF-16 sequence is rounded upwards to the end of that
- sequence.
+ Invalid UTF-8 and NUL is treated like by |vim.str_byteindex()|.
+ An {index} in the middle of a UTF-16 sequence is rounded upwards to
+ the end of that sequence.
-vim.schedule({callback}) *vim.schedule()*
+vim.schedule({callback}) *vim.schedule()*
Schedules {callback} to be invoked soon by the main event-loop. Useful
to avoid |textlock| or other temporary restrictions.
-vim.defer_fn({fn}, {timeout}) *vim.defer_fn*
- Defers calling {fn} until {timeout} ms passes. Use to do a one-shot timer
+vim.defer_fn({fn}, {timeout}) *vim.defer_fn*
+ Defers calling {fn} until {timeout} ms passes. Use to do a one-shot timer
that calls {fn}.
Note: The {fn} is |schedule_wrap|ped automatically, so API functions are
@@ -969,15 +960,15 @@ vim.wait({time} [, {callback}, {interval}, {fast_only}]) *vim.wait()*
end
<
-vim.type_idx *vim.type_idx*
- Type index for use in |lua-special-tbl|. Specifying one of the values
+vim.type_idx *vim.type_idx*
+ Type index for use in |lua-special-tbl|. Specifying one of the values
from |vim.types| allows typing the empty table (it is unclear whether
empty Lua table represents empty list or empty array) and forcing
- integral numbers to be |Float|. See |lua-special-tbl| for more
+ integral numbers to be |Float|. See |lua-special-tbl| for more
details.
-vim.val_idx *vim.val_idx*
- Value index for tables representing |Float|s. A table representing
+vim.val_idx *vim.val_idx*
+ Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >
{
[vim.type_idx] = vim.types.float,
@@ -985,17 +976,17 @@ vim.val_idx *vim.val_idx*
}
< See also |vim.type_idx| and |lua-special-tbl|.
-vim.types *vim.types*
- Table with possible values for |vim.type_idx|. Contains two sets of
+vim.types *vim.types*
+ Table with possible values for |vim.type_idx|. Contains two sets of
key-value pairs: first maps possible values for |vim.type_idx| to
human-readable strings, second maps human-readable type names to
- values for |vim.type_idx|. Currently contains pairs for `float`,
+ values for |vim.type_idx|. Currently contains pairs for `float`,
`array` and `dictionary` types.
- Note: one must expect that values corresponding to `vim.types.float`,
+ Note: One must expect that values corresponding to `vim.types.float`,
`vim.types.array` and `vim.types.dictionary` fall under only two
following assumptions:
- 1. Value may serve both as a key and as a value in a table. Given the
+ 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`.
@@ -1015,33 +1006,22 @@ Log levels are one of the values defined in `vim.log.levels`:
vim.log.levels.OFF
------------------------------------------------------------------------------
-LUA-VIMSCRIPT BRIDGE *lua-vimscript*
+LUA-VIMSCRIPT BRIDGE *lua-vimscript*
Nvim Lua provides an interface to Vimscript variables and functions, and
editor commands and options.
See also https://github.com/nanotee/nvim-lua-guide.
-vim.call({func}, {...}) *vim.call()*
+vim.call({func}, {...}) *vim.call()*
Invokes |vim-function| or |user-function| {func} with arguments {...}.
See also |vim.fn|.
Equivalent to: >
vim.fn[func]({...})
-vim.cmd({cmd}) *vim.cmd()*
- Executes multiple lines of Vimscript at once. It is an alias to
- |nvim_exec()|, where `output` is set to false. Thus it works identical
- to |:source|.
- See also |ex-cmd-index|.
- Example: >
- vim.cmd('echo 42')
- vim.cmd([[
- augroup My_group
- autocmd!
- autocmd FileType c setlocal cindent
- augroup END
- ]])
-
-vim.fn.{func}({...}) *vim.fn*
+vim.cmd({command})
+ See |vim.cmd()|.
+
+vim.fn.{func}({...}) *vim.fn*
Invokes |vim-function| or |user-function| {func} with arguments {...}.
To call autoload functions, use the syntax: >
vim.fn['some#function']({...})
@@ -1058,7 +1038,7 @@ vim.fn.{func}({...}) *vim.fn*
enumerates functions that were called at least once.
- *lua-vim-variables*
+ *lua-vim-variables*
The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
described below. In this way you can easily read and modify global Vimscript
@@ -1070,31 +1050,31 @@ Example: >
print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
vim.b[2].foo = 6 -- Set b:foo for buffer 2
-
-vim.g *vim.g*
+<
+vim.g *vim.g*
Global (|g:|) editor variables.
Key with no value returns `nil`.
-vim.b *vim.b*
+vim.b *vim.b*
Buffer-scoped (|b:|) variables for the current buffer.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific buffer.
-vim.w *vim.w*
+vim.w *vim.w*
Window-scoped (|w:|) variables for the current window.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific window.
-vim.t *vim.t*
+vim.t *vim.t*
Tabpage-scoped (|t:|) variables for the current tabpage.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific tabpage.
-vim.v *vim.v*
+vim.v *vim.v*
|v:| variables.
Invalid or unset key returns `nil`.
-vim.env *vim.env*
+vim.env *vim.env*
Environment variables defined in the editor session.
See |expand-env| and |:let-environment| for the Vimscript behavior.
Invalid or unset key returns `nil`.
@@ -1144,7 +1124,6 @@ from within Lua.
-- or using the `:append(...)` method
vim.opt.wildignore:append { "*.pyc", "node_modules" }
<
-
To replicate the behavior of |:set^=|, use: >
-- vim.opt supports prepending options via the "^" operator
@@ -1265,14 +1244,13 @@ vim.o :set set set
vim.bo/vim.wo :setlocal - set
vim.go :setglobal set -
-vim.o *vim.o*
+vim.o *vim.o*
Get or set editor options, like |:set|. Invalid key is an error.
Example: >
vim.o.cmdheight = 4
print(vim.o.columns)
-
-
-vim.go *vim.go*
+<
+vim.go *vim.go*
Get or set an |option|. Invalid key is an error.
This is a wrapper around |nvim_set_option()| and |nvim_get_option()|.
@@ -1284,8 +1262,7 @@ vim.go *vim.go*
Example: >
vim.go.cmdheight = 4
<
-
-vim.bo *vim.bo*
+vim.bo *vim.bo*
Get or set buffer-scoped |local-options|. Invalid key is an error.
This is a wrapper around |nvim_buf_set_option()| and
@@ -1294,8 +1271,8 @@ vim.bo *vim.bo*
Example: >
vim.bo.buflisted = true
print(vim.bo.comments)
-
-vim.wo *vim.wo*
+<
+vim.wo *vim.wo*
Get or set window-scoped |local-options|. Invalid key is an error.
This is a wrapper around |nvim_win_set_option()| and
@@ -1304,11 +1281,38 @@ vim.wo *vim.wo*
Example: >
vim.wo.cursorcolumn = true
print(vim.wo.foldmarker)
-
-
+<
==============================================================================
Lua module: vim *lua-vim*
+cmd({command}) *vim.cmd()*
+ Execute Vim script commands.
+
+ Example: >
+
+ vim.cmd('echo 42')
+ vim.cmd([[
+ augroup My_group
+ autocmd!
+ autocmd FileType c setlocal cindent
+ augroup END
+ ]])
+ vim.cmd({ cmd = 'echo', args = { '"foo"' } })
+<
+
+ Parameters: ~
+ {command} string|table Command(s) to execute. If a
+ string, executes multiple lines of Vim script
+ at once. In this case, it is an alias to
+ |nvim_exec()|, where `output` is set to false.
+ Thus it works identical to |:source|. If a
+ table, executes a single command. In this case,
+ it is an alias to |nvim_cmd()| where `opts` is
+ empty.
+
+ See also: ~
+ |ex-cmd-index|
+
*vim.connection_failure_errmsg()*
connection_failure_errmsg({consequence})
TODO: Documentation
@@ -1332,7 +1336,8 @@ deprecate({name}, {alternative}, {version}, {plugin}) *vim.deprecate()*
Parameters: ~
{name} string Deprecated function.
- {alternative} string|nil Preferred alternative function.
+ {alternative} (string|nil) Preferred alternative
+ function.
{version} string Version in which the deprecated
function will be removed.
{plugin} string|nil Plugin name that the function
@@ -1353,11 +1358,12 @@ notify({msg}, {level}, {opts}) *vim.notify()*
notification provider). By default, writes to |:messages|.
Parameters: ~
- {msg} string Content of the notification to show to the
- user.
- {level} number|nil One of the values from
+ {msg} (string) Content of the notification to show to
+ the user.
+ {level} (number|nil) One of the values from
|vim.log.levels|.
- {opts} table|nil Optional parameters. Unused by default.
+ {opts} (table|nil) Optional parameters. Unused by
+ default.
notify_once({msg}, {level}, {opts}) *vim.notify_once()*
Display a notification only one time.
@@ -1366,11 +1372,12 @@ notify_once({msg}, {level}, {opts}) *vim.notify_once()*
message will not display a notification.
Parameters: ~
- {msg} string Content of the notification to show to the
- user.
- {level} number|nil One of the values from
+ {msg} (string) Content of the notification to show to
+ the user.
+ {level} (number|nil) One of the values from
|vim.log.levels|.
- {opts} table|nil Optional parameters. Unused by default.
+ {opts} (table|nil) Optional parameters. Unused by
+ default.
on_key({fn}, {ns_id}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener
@@ -1396,8 +1403,8 @@ on_key({fn}, {ns_id}) *vim.on_key()*
returns a new |nvim_create_namespace()| id.
Return: ~
- number Namespace id associated with {fn}. Or count of all
- callbacks if on_key() is called without arguments.
+ (number) Namespace id associated with {fn}. Or count of
+ all callbacks if on_key() is called without arguments.
Note:
{fn} will be removed if an error occurs while calling.
@@ -1451,12 +1458,12 @@ region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()*
marked by two points
Parameters: ~
- {bufnr} number of buffer
+ {bufnr} (number) of buffer
{pos1} (line, column) tuple marking beginning of
region
{pos2} (line, column) tuple marking end of region
{regtype} type of selection (:help setreg)
- {inclusive} boolean indicating whether the selection is
+ {inclusive} (boolean) indicating whether the selection is
end-inclusive
Return: ~
@@ -1476,14 +1483,14 @@ schedule_wrap({cb}) *vim.schedule_wrap()*
deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality
- Tables are compared recursively unless they both provide the `eq` methamethod. All other types are compared using the equality `==` operator.
+ Tables are compared recursively unless they both provide the `eq` metamethod. All other types are compared using the equality `==` operator.
Parameters: ~
- {a} first value
- {b} second value
+ {a} any First value
+ {b} any Second value
Return: ~
- `true` if values are equals, else `false`.
+ (boolean) `true` if values are equals, else `false`
deepcopy({orig}) *vim.deepcopy()*
Returns a deep copy of the given object. Non-table objects are
@@ -1494,32 +1501,32 @@ deepcopy({orig}) *vim.deepcopy()*
and will throw an error.
Parameters: ~
- {orig} table Table to copy
+ {orig} (table) Table to copy
Return: ~
- New table of copied keys and (nested) values.
+ (table) Table of copied keys and (nested) values.
endswith({s}, {suffix}) *vim.endswith()*
Tests if `s` ends with `suffix`.
Parameters: ~
- {s} (string) a string
- {suffix} (string) a suffix
+ {s} (string) String
+ {suffix} (string) Suffix to match
Return: ~
- (boolean) true if `suffix` is a suffix of s
+ (boolean) `true` if `suffix` is a suffix of `s`
gsplit({s}, {sep}, {plain}) *vim.gsplit()*
Splits a string at each instance of a separator.
Parameters: ~
- {s} String to split
- {sep} Separator string or pattern
- {plain} If `true` use `sep` literally (passed to
- String.find)
+ {s} (string) String to split
+ {sep} (string) Separator or pattern
+ {plain} (boolean) If `true` use `sep` literally (passed
+ to string.find)
Return: ~
- Iterator over the split components
+ (function) Iterator over the split components
See also: ~
|vim.split()|
@@ -1530,10 +1537,10 @@ is_callable({f}) *vim.is_callable()*
Returns true if object `f` can be called as a function.
Parameters: ~
- {f} Any object
+ {f} any Any object
Return: ~
- true if `f` is callable, else false
+ (boolean) `true` if `f` is callable, else `false`
list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
Extends a list-like table with the values of another list-like
@@ -1542,13 +1549,14 @@ list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
NOTE: This mutates dst!
Parameters: ~
- {dst} list which will be modified and appended to.
- {src} list from which values will be inserted.
- {start} Start index on src. defaults to 1
- {finish} Final index on src. defaults to #src
+ {dst} (table) List which will be modified and appended
+ to
+ {src} (table) List from which values will be inserted
+ {start} (number) Start index on src. Defaults to 1
+ {finish} (number) Final index on src. Defaults to `#src`
Return: ~
- dst
+ (table) dst
See also: ~
|vim.tbl_extend()|
@@ -1558,21 +1566,22 @@ list_slice({list}, {start}, {finish}) *vim.list_slice()*
to end (inclusive)
Parameters: ~
- {list} table table
- {start} integer Start range of slice
- {finish} integer End range of slice
+ {list} (table) Table
+ {start} (number) Start range of slice
+ {finish} (number) End range of slice
Return: ~
- Copy of table sliced from start to finish (inclusive)
+ (table) Copy of table sliced from start to finish
+ (inclusive)
pesc({s}) *vim.pesc()*
Escapes magic chars in a Lua pattern.
Parameters: ~
- {s} String to escape
+ {s} (string) String to escape
Return: ~
- %-escaped pattern string
+ (string) %-escaped pattern string
See also: ~
https://github.com/rxi/lume
@@ -1589,16 +1598,16 @@ split({s}, {sep}, {kwargs}) *vim.split()*
<
Parameters: ~
- {s} String to split
- {sep} Separator string or pattern
- {kwargs} Keyword arguments:
+ {s} (string) String to split
+ {sep} (string) Separator or pattern
+ {kwargs} (table) Keyword arguments:
• plain: (boolean) If `true` use `sep` literally
(passed to string.find)
• trimempty: (boolean) If `true` remove empty
items from the front and back of the list
Return: ~
- List-like table of the split components.
+ (table) List of split components
See also: ~
|vim.gsplit()|
@@ -1607,28 +1616,34 @@ startswith({s}, {prefix}) *vim.startswith()*
Tests if `s` starts with `prefix`.
Parameters: ~
- {s} (string) a string
- {prefix} (string) a prefix
+ {s} (string) String
+ {prefix} (string) Prefix to match
Return: ~
- (boolean) true if `prefix` is a prefix of s
+ (boolean) `true` if `prefix` is a prefix of `s`
tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
Add the reverse lookup values to an existing table. For
- example: `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
+ example: `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A =
+ 1 }`
+
+ Note that this modifies the input.
Parameters: ~
- {o} table The table to add the reverse to.
+ {o} (table) Table to add the reverse to
+
+ Return: ~
+ (table) o
tbl_contains({t}, {value}) *vim.tbl_contains()*
Checks if a list-like (vector) table contains `value`.
Parameters: ~
- {t} Table to check
- {value} Value to compare
+ {t} (table) Table to check
+ {value} any Value to compare
Return: ~
- true if `t` contains `value`
+ (boolean) `true` if `t` contains `value`
tbl_count({t}) *vim.tbl_count()*
Counts the number of non-nil values in table `t`.
@@ -1639,10 +1654,10 @@ tbl_count({t}) *vim.tbl_count()*
<
Parameters: ~
- {t} Table
+ {t} (table) Table
Return: ~
- Number that is the number of the value in table
+ (number) Number of non-nil values in table
See also: ~
https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
@@ -1651,12 +1666,15 @@ tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
Merges recursively two or more map-like tables.
Parameters: ~
- {behavior} Decides what to do if a key is found in more
- than one map:
+ {behavior} (string) Decides what to do if a key is found
+ in more than one map:
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- {...} Two or more map-like tables.
+ {...} (table) Two or more map-like tables
+
+ Return: ~
+ (table) Merged table
See also: ~
|tbl_extend()|
@@ -1665,12 +1683,15 @@ tbl_extend({behavior}, {...}) *vim.tbl_extend()*
Merges two or more map-like tables.
Parameters: ~
- {behavior} Decides what to do if a key is found in more
- than one map:
+ {behavior} (string) Decides what to do if a key is found
+ in more than one map:
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- {...} Two or more map-like tables.
+ {...} (table) Two or more map-like tables
+
+ Return: ~
+ (table) Merged table
See also: ~
|extend()|
@@ -1679,43 +1700,51 @@ tbl_filter({func}, {t}) *vim.tbl_filter()*
Filter a table using a predicate function
Parameters: ~
- {func} function or callable table
- {t} table
+ {func} function|table Function or callable table
+ {t} (table) Table
+
+ Return: ~
+ (table) Table of filtered values
tbl_flatten({t}) *vim.tbl_flatten()*
Creates a copy of a list-like table such that any nested
tables are "unrolled" and appended to the result.
Parameters: ~
- {t} List-like table
+ {t} (table) List-like table
Return: ~
- Flattened copy of the given list-like table.
+ (table) Flattened copy of the given list-like table
See also: ~
From https://github.com/premake/premake-core/blob/master/src/base/table.lua
tbl_get({o}, {...}) *vim.tbl_get()*
Index into a table (first argument) via string keys passed as
- subsequent arguments. Return `nil` if the key does not exist. Examples: >
+ subsequent arguments. Return `nil` if the key does not exist.
+
+ Examples: >
vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
<
Parameters: ~
- {o} Table to index
- {...} Optional strings (0 or more, variadic) via which to
- index the table
+ {o} (table) Table to index
+ {...} (string) Optional strings (0 or more, variadic) via
+ which to index the table
Return: ~
- nested value indexed by key if it exists, else nil
+ any Nested value indexed by key (if it exists), else nil
tbl_isempty({t}) *vim.tbl_isempty()*
Checks if a table is empty.
Parameters: ~
- {t} Table to check
+ {t} (table) Table to check
+
+ Return: ~
+ (boolean) `true` if `t` is empty
See also: ~
https://github.com/premake/premake-core/blob/master/src/base/table.lua
@@ -1729,20 +1758,20 @@ tbl_islist({t}) *vim.tbl_islist()*
|vim.fn|.
Parameters: ~
- {t} Table
+ {t} (table) Table
Return: ~
- `true` if array-like table, else `false`.
+ (boolean) `true` if array-like table, else `false`
tbl_keys({t}) *vim.tbl_keys()*
Return a list of all keys used in a table. However, the order
of the return table of keys is not guaranteed.
Parameters: ~
- {t} Table
+ {t} (table) Table
Return: ~
- list of keys
+ (table) List of keys
See also: ~
From https://github.com/premake/premake-core/blob/master/src/base/table.lua
@@ -1751,28 +1780,32 @@ tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table.
Parameters: ~
- {func} function or callable table
- {t} table
+ {func} function|table Function or callable table
+ {t} (table) Table
+
+ Return: ~
+ (table) Table of transformed values
tbl_values({t}) *vim.tbl_values()*
Return a list of all values used in a table. However, the
order of the return table of values is not guaranteed.
Parameters: ~
- {t} Table
+ {t} (table) Table
Return: ~
- list of values
+ (table) List of values
trim({s}) *vim.trim()*
Trim whitespace (Lua pattern "%s") from both sides of a
string.
Parameters: ~
- {s} String to trim
+ {s} (string) String to trim
Return: ~
- String with whitespace removed from its beginning and end
+ (string) String with whitespace removed from its beginning
+ and end
See also: ~
https://www.lua.org/pil/20.2.html
@@ -1814,7 +1847,7 @@ validate({opt}) *vim.validate()*
<
Parameters: ~
- {opt} table of parameter names to validations. Each key
+ {opt} (table) Names of parameters to validate. Each key
is a parameter name; each value is a tuple in one
of these forms:
1. (arg_value, type_name, optional)
@@ -1844,38 +1877,38 @@ uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()*
Get a URI from a bufnr
Parameters: ~
- {bufnr} number
+ {bufnr} (number)
Return: ~
- string URI
+ (string) URI
uri_from_fname({path}) *vim.uri_from_fname()*
Get a URI from a file path.
Parameters: ~
- {path} string Path to file
+ {path} (string) Path to file
Return: ~
- string URI
+ (string) URI
uri_to_bufnr({uri}) *vim.uri_to_bufnr()*
Get the buffer for a uri. Creates a new unloaded buffer if no
buffer for the uri already exists.
Parameters: ~
- {uri} string
+ {uri} (string)
Return: ~
- number bufnr
+ (number) bufnr
uri_to_fname({uri}) *vim.uri_to_fname()*
Get a filename from a URI
Parameters: ~
- {uri} string
+ {uri} (string)
Return: ~
- string filename or unchanged URI for non-file URIs
+ (string) filename or unchanged URI for non-file URIs
==============================================================================
@@ -1892,7 +1925,7 @@ input({opts}, {on_confirm}) *vim.ui.input()*
<
Parameters: ~
- {opts} table Additional options. See |input()|
+ {opts} (table) Additional options. See |input()|
• prompt (string|nil) Text of the prompt.
Defaults to `Input:`.
• default (string|nil) Default reply to the
@@ -1905,10 +1938,10 @@ input({opts}, {on_confirm}) *vim.ui.input()*
|:command-completion|
• highlight (function) Function that will be
used for highlighting user inputs.
- {on_confirm} function ((input|nil) -> ()) Called once the
- user confirms or abort the input. `input` is
- what the user typed. `nil` if the user
- aborted the dialog.
+ {on_confirm} (function) ((input|nil) -> ()) Called once
+ the user confirms or abort the input.
+ `input` is what the user typed. `nil` if the
+ user aborted the dialog.
select({items}, {opts}, {on_choice}) *vim.ui.select()*
Prompts the user to pick a single item from a collection of
@@ -1931,8 +1964,8 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()*
<
Parameters: ~
- {items} table Arbitrary items
- {opts} table Additional options
+ {items} (table) Arbitrary items
+ {opts} (table) Additional options
• prompt (string|nil) Text of the prompt.
Defaults to `Select one of:`
• format_item (function item -> text)
@@ -1944,7 +1977,7 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()*
use this to infer the structure or
semantics of `items`, or the context in
which select() was called.
- {on_choice} function ((item|nil, idx|nil) -> ()) Called
+ {on_choice} (function) ((item|nil, idx|nil) -> ()) Called
once the user made a choice. `idx` is the
1-based index of `item` within `items`. `nil`
if the user aborted the dialog.
@@ -2013,16 +2046,16 @@ add({filetypes}) *vim.filetype.add()*
<
Parameters: ~
- {filetypes} table A table containing new filetype maps
+ {filetypes} (table) A table containing new filetype maps
(see example).
match({name}, {bufnr}) *vim.filetype.match()*
Set the filetype for the given buffer from a file name.
Parameters: ~
- {name} string File name (can be an absolute or relative
- path)
- {bufnr} number|nil The buffer to set the filetype for.
+ {name} (string) File name (can be an absolute or
+ relative path)
+ {bufnr} (number|nil) The buffer to set the filetype for.
Defaults to the current buffer.
@@ -2038,7 +2071,7 @@ del({modes}, {lhs}, {opts}) *vim.keymap.del()*
<
Parameters: ~
- {opts} table A table of optional arguments:
+ {opts} (table) A table of optional arguments:
• buffer: (number or boolean) Remove a mapping
from the given buffer. When "true" or 0, use the
current buffer.
@@ -2082,12 +2115,12 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
{mode} string|table Same mode short names as
|nvim_set_keymap()|. Can also be list of modes to
create mapping on multiple modes.
- {lhs} string Left-hand side |{lhs}| of the mapping.
+ {lhs} (string) Left-hand side |{lhs}| of the mapping.
{rhs} string|function Right-hand side |{rhs}| of the
mapping. Can also be a Lua function. If a Lua
function and `opts.expr == true`, returning `nil`
is equivalent to an empty string.
- {opts} table A table of |:map-arguments| such as
+ {opts} (table) A table of |:map-arguments| such as
"silent". In addition to the options listed in
|nvim_set_keymap()|, this table also accepts the
following keys:
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 6e100e5854..056e6c3b56 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -105,7 +105,7 @@ modes.
command applies.
Use the <buffer> argument to remove buffer-local
mappings |:map-<buffer>|
- Warning: This also removes the default mappings.
+ Warning: This also removes the |default-mappings|.
:map |mapmode-nvo|
:nm[ap] |mapmode-n|
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 1109056d47..4d6f589714 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -841,7 +841,7 @@ A jump table for the options with a short description can be found at |Q_op|.
again not rename the file.
*'backupdir'* *'bdir'*
-'backupdir' 'bdir' string (default ".,$XDG_DATA_HOME/nvim/backup//")
+'backupdir' 'bdir' string (default ".,$XDG_STATE_HOME/nvim/backup//")
global
List of directories for the backup file, separated with commas.
- The backup file will be created in the first directory in the list
@@ -2063,7 +2063,7 @@ A jump table for the options with a short description can be found at |Q_op|.
{char2}. See |digraphs|.
*'directory'* *'dir'*
-'directory' 'dir' string (default "$XDG_DATA_HOME/nvim/swap//")
+'directory' 'dir' string (default "$XDG_STATE_HOME/nvim/swap//")
global
List of directory names for the swap file, separated with commas.
@@ -3502,7 +3502,7 @@ A jump table for the options with a short description can be found at |Q_op|.
option. For '@' only characters up to 255 are used.
Careful: If you change this option, it might break expanding
environment variables. E.g., when '/' is included and Vim tries to
- expand "$HOME/.local/share/nvim/shada/main.shada". Maybe you should
+ expand "$HOME/.local/state/nvim/shada/main.shada". Maybe you should
change 'iskeyword' instead.
*'iskeyword'* *'isk'*
@@ -4942,9 +4942,12 @@ A jump table for the options with a short description can be found at |Q_op|.
but are not part of the Nvim distribution. XDG_DATA_DIRS defaults
to /usr/local/share/:/usr/share/, so system administrators are
expected to install site plugins to /usr/share/nvim/site.
- 5. $VIMRUNTIME, for files distributed with Neovim.
+ 5. Applications state home directory, for files that contain your
+ session state (eg. backupdir, viewdir, undodir, etc).
+ Given by `stdpath("state")`. |$XDG_STATE_HOME|
+ 6. $VIMRUNTIME, for files distributed with Neovim.
*after-directory*
- 6, 7, 8, 9. In after/ subdirectories of 1, 2, 3 and 4, with reverse
+ 7, 8, 9, 10. In after/ subdirectories of 1, 2, 3 and 4, with reverse
ordering. This is for preferences to overrule or add to the
distributed defaults or system-wide settings (rarely needed).
@@ -6623,7 +6626,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'ttyfast' 'tf' Removed. |vim-differences|
*'undodir'* *'udir'* *E5003*
-'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo//")
+'undodir' 'udir' string (default "$XDG_STATE_HOME/nvim/undo//")
global
List of directory names for undo files, separated with commas.
See 'backupdir' for details of the format.
@@ -6786,7 +6789,7 @@ A jump table for the options with a short description can be found at |Q_op|.
displayed when 'verbosefile' is set.
*'viewdir'* *'vdir'*
-'viewdir' 'vdir' string (default: "$XDG_DATA_HOME/nvim/view//")
+'viewdir' 'vdir' string (default: "$XDG_STATE_HOME/nvim/view//")
global
Name of the directory where to store files for |:mkview|.
This option cannot be set from a |modeline| or in the |sandbox|, for
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 1d3fa6c2ca..f542f33451 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -367,7 +367,7 @@ argument.
*--headless*
--headless Start without UI, and do not wait for `nvim_ui_attach`. The
builtin TUI is not used, so stdio works as an arbitrary
- communication channel. |channel-stdio|
+ communication channel. |channel-stdio|
Also useful for scripting (tests) to see messages that would
not be printed by |-es|.
@@ -584,7 +584,7 @@ setting can affect the entire editor in ways that are not initially obvious.
To find the cause of a problem in your config, you must "bisect" it:
1. Remove or disable half of your |config|.
2. Restart Nvim.
-3. If the problem still occurs, goto 1.
+3. If the problem still occurs, goto 1.
4. If the problem is gone, restore half of the removed lines.
5. Continue narrowing your config in this way, until you find the setting or
plugin causing the issue.
@@ -701,7 +701,7 @@ vimrc file.
These commands will write ":map" and ":set" commands to a file, in such a way
that when these commands are executed, the current key mappings and options
will be set to the same values. The options 'columns', 'endofline',
-'fileformat', 'lines', 'modified', and 'scroll' are not included, because
+'fileformat', 'lines', 'modified', and 'scroll' are not included, because
these are terminal or file dependent.
Note that the options 'binary', 'paste' and 'readonly' are included, this
might not always be what you want.
@@ -718,7 +718,7 @@ with ":map" and ":set" commands and write the modified file. First read the
default vimrc in with a command like ":source ~piet/.vimrc.Cprogs", change
the settings and then save them in the current directory with ":mkvimrc!". If
you want to make this file your default |config|, move it to
-$XDG_CONFIG_HOME/nvim. You could also use autocommands |autocommand| and/or
+$XDG_CONFIG_HOME/nvim. You could also use autocommands |autocommand| and/or
modelines |modeline|.
*vimrc-option-example*
@@ -886,7 +886,7 @@ Shada ("shared data") file *shada* *shada-file*
If you exit Vim and later start it again, you would normally lose a lot of
information. The ShaDa file can be used to remember that information, which
-enables you to continue where you left off. Its name is the abbreviation of
+enables you to continue where you left off. Its name is the abbreviation of
SHAred DAta because it is used for sharing data between Neovim sessions.
This is introduced in section |21.3| of the user manual.
@@ -917,9 +917,9 @@ The |v:oldfiles| variable is filled. The marks are not read in at startup
option upon startup.
*shada-write*
-When Vim exits and 'shada' is non-empty, the info is stored in the ShaDa file
-(it's actually merged with the existing one, if one exists |shada-merging|).
-The 'shada' option is a string containing information about what info should
+When Vim exits and 'shada' is non-empty, the info is stored in the ShaDa file
+(it's actually merged with the existing one, if one exists |shada-merging|).
+The 'shada' option is a string containing information about what info should
be stored, and contains limits on how much should be stored (see 'shada').
Notes for Unix:
@@ -977,75 +977,75 @@ remembered.
MERGING *shada-merging*
-When writing ShaDa files with |:wshada| without bang or at regular exit
-information in the existing ShaDa file is merged with information from current
-Neovim instance. For this purpose ShaDa files store timestamps associated
+When writing ShaDa files with |:wshada| without bang or at regular exit
+information in the existing ShaDa file is merged with information from current
+Neovim instance. For this purpose ShaDa files store timestamps associated
with ShaDa entries. Specifically the following is being done:
-1. History lines are merged, ordered by timestamp. Maximum amount of items in
- ShaDa file is defined by 'shada' option (|shada-/|, |shada-:|, |shada-@|,
- etc: one suboption for each character that represents history name
+1. History lines are merged, ordered by timestamp. Maximum amount of items in
+ ShaDa file is defined by 'shada' option (|shada-/|, |shada-:|, |shada-@|,
+ etc: one suboption for each character that represents history name
(|:history|)).
-2. Local marks and changes for files that were not opened by Neovim are copied
- to new ShaDa file. Marks for files that were opened by Neovim are merged,
+2. Local marks and changes for files that were not opened by Neovim are copied
+ to new ShaDa file. Marks for files that were opened by Neovim are merged,
changes to files opened by Neovim are ignored. |shada-'|
-3. Jump list is merged: jumps are ordered by timestamp, identical jumps
+3. Jump list is merged: jumps are ordered by timestamp, identical jumps
(identical position AND timestamp) are squashed.
-4. Search patterns and substitute strings are not merged: search pattern or
- substitute string which has greatest timestamp will be the only one copied
+4. Search patterns and substitute strings are not merged: search pattern or
+ substitute string which has greatest timestamp will be the only one copied
to ShaDa file.
-5. For each register entity with greatest timestamp is the only saved.
+5. For each register entity with greatest timestamp is the only saved.
|shada-<|
-6. All saved variables are saved from current Neovim instance. Additionally
- existing variable values are copied, meaning that the only way to remove
- variable from a ShaDa file is either removing it by hand or disabling
+6. All saved variables are saved from current Neovim instance. Additionally
+ existing variable values are copied, meaning that the only way to remove
+ variable from a ShaDa file is either removing it by hand or disabling
writing variables completely. |shada-!|
7. For each global mark entity with greatest timestamp is the only saved.
-8. Buffer list and header are the only entries which are not merged in any
- fashion: the only header and buffer list present are the ones from the
+8. Buffer list and header are the only entries which are not merged in any
+ fashion: the only header and buffer list present are the ones from the
Neovim instance which was last writing the file. |shada-%|
COMPATIBILITY *shada-compatibility*
ShaDa files are forward and backward compatible. This means that
-1. Entries which have unknown type (i.e. that hold unidentified data) are
+1. Entries which have unknown type (i.e. that hold unidentified data) are
ignored when reading and blindly copied when writing.
-2. Register entries with unknown register name are ignored when reading and
- blindly copied when writing. Limitation: only registers that use name with
+2. Register entries with unknown register name are ignored when reading and
+ blindly copied when writing. Limitation: only registers that use name with
code in interval [1, 255] are supported. |registers|
-3. Register entries with unknown register type are ignored when reading and
+3. Register entries with unknown register type are ignored when reading and
merged as usual when writing. |getregtype()|
-4. Local and global mark entries with unknown mark names are ignored when
- reading. When writing global mark entries are blindly copied and local mark
- entries are also blindly copied, but only if file they are attached to fits
- in the |shada-'| limit. Unknown local mark entry's timestamp is also taken
- into account when calculating which files exactly should fit into this
- limit. Limitation: only marks that use name with code in interval [1, 255]
+4. Local and global mark entries with unknown mark names are ignored when
+ reading. When writing global mark entries are blindly copied and local mark
+ entries are also blindly copied, but only if file they are attached to fits
+ in the |shada-'| limit. Unknown local mark entry's timestamp is also taken
+ into account when calculating which files exactly should fit into this
+ limit. Limitation: only marks that use name with code in interval [1, 255]
are supported. |mark-motions|
-5. History entries with unknown history type are ignored when reading and
- blindly copied when writing. Limitation: there can be only up to 256
+5. History entries with unknown history type are ignored when reading and
+ blindly copied when writing. Limitation: there can be only up to 256
history types. |history|
-6. Unknown keys found in register, local mark, global mark, change, jump and
- search pattern entries are saved internally and dumped when writing.
+6. Unknown keys found in register, local mark, global mark, change, jump and
+ search pattern entries are saved internally and dumped when writing.
Entries created during Neovim session never have such additions.
-7. Additional elements found in replacement string and history entries are
- saved internally and dumped. Entries created during Neovim session never
+7. Additional elements found in replacement string and history entries are
+ saved internally and dumped. Entries created during Neovim session never
have such additions.
-8. Additional elements found in variable entries are simply ignored when
- reading. When writing new variables they will be preserved during merging,
- but that's all. Variable values dumped from current Neovim session never
- have additional elements, even if variables themselves were obtained by
+8. Additional elements found in variable entries are simply ignored when
+ reading. When writing new variables they will be preserved during merging,
+ but that's all. Variable values dumped from current Neovim session never
+ have additional elements, even if variables themselves were obtained by
reading ShaDa files.
-"Blindly" here means that there will be no attempts to somehow merge them,
+"Blindly" here means that there will be no attempts to somehow merge them,
even if other entries (with known name/type/etc) are merged. |shada-merging|
SHADA FILE NAME *shada-file-name*
- Default name of the |shada| file is:
- Unix: "$XDG_DATA_HOME/nvim/shada/main.shada"
- Windows: "$XDG_DATA_HOME/nvim-data/shada/main.shada"
+ Unix: "$XDG_STATE_HOME/nvim/shada/main.shada"
+ Windows: "$XDG_STATE_HOME/nvim-data/shada/main.shada"
See also |base-directories|.
- To choose a different file name you can use:
- The "n" flag in the 'shada' option.
@@ -1067,55 +1067,55 @@ however that this means everything will be overwritten with information from
the first Vim, including the command line history, etc.
The ShaDa file itself can be edited by hand too, although we suggest you
-start with an existing one to get the format right. You need to understand
-MessagePack (or, more likely, find software that is able to use it) format to
-do this. This can be useful in order to create a second file, say
-"~/.my.shada" which could contain certain settings that you always want when
-you first start Neovim. For example, you can preload registers with
-particular data, or put certain commands in the command line history. A line
+start with an existing one to get the format right. You need to understand
+MessagePack (or, more likely, find software that is able to use it) format to
+do this. This can be useful in order to create a second file, say
+"~/.my.shada" which could contain certain settings that you always want when
+you first start Neovim. For example, you can preload registers with
+particular data, or put certain commands in the command line history. A line
in your |config| file like >
:rshada! ~/.my.shada
-can be used to load this information. You could even have different ShaDa
-files for different types of files (e.g., C code) and load them based on the
-file name, using the ":autocmd" command (see |:autocmd|). More information on
+can be used to load this information. You could even have different ShaDa
+files for different types of files (e.g., C code) and load them based on the
+file name, using the ":autocmd" command (see |:autocmd|). More information on
ShaDa file format is contained in |shada-format| section.
*E136* *E929* *shada-error-handling*
-Some errors make Neovim leave temporary file named `{basename}.tmp.X` (X is
-any free letter from `a` to `z`) while normally it will create this file,
-write to it and then rename `{basename}.tmp.X` to `{basename}`. Such errors
+Some errors make Neovim leave temporary file named `{basename}.tmp.X` (X is
+any free letter from `a` to `z`) while normally it will create this file,
+write to it and then rename `{basename}.tmp.X` to `{basename}`. Such errors
include:
-- Errors which make Neovim think that read file is not a ShaDa file at all:
- non-ShaDa files are not overwritten for safety reasons to avoid accidentally
- destroying an unrelated file. This could happen e.g. when typing "nvim -i
- file" in place of "nvim -R file" (yes, somebody did that at least with Vim).
+- Errors which make Neovim think that read file is not a ShaDa file at all:
+ non-ShaDa files are not overwritten for safety reasons to avoid accidentally
+ destroying an unrelated file. This could happen e.g. when typing "nvim -i
+ file" in place of "nvim -R file" (yes, somebody did that at least with Vim).
Such errors are listed at |shada-critical-contents-errors|.
-- If writing to the temporary file failed: e.g. because of the insufficient
+- If writing to the temporary file failed: e.g. because of the insufficient
space left.
- If renaming file failed: e.g. because of insufficient permissions.
-- If target ShaDa file has different from the Neovim instance's owners (user
- and group) and changing them failed. Unix-specific, applies only when
+- If target ShaDa file has different from the Neovim instance's owners (user
+ and group) and changing them failed. Unix-specific, applies only when
Neovim was launched from root.
-Do not forget to remove the temporary file or replace the target file with
-temporary one after getting one of the above errors or all attempts to create
-a ShaDa file may fail with |E929|. If you got one of them when using
-|:wshada| (and not when exiting Neovim: i.e. when you have Neovim session
+Do not forget to remove the temporary file or replace the target file with
+temporary one after getting one of the above errors or all attempts to create
+a ShaDa file may fail with |E929|. If you got one of them when using
+|:wshada| (and not when exiting Neovim: i.e. when you have Neovim session
running) you have additional options:
-- First thing which you should consider if you got any error, except failure
- to write to the temporary file: remove existing file and replace it with the
+- First thing which you should consider if you got any error, except failure
+ to write to the temporary file: remove existing file and replace it with the
temporary file. Do it even if you have running Neovim instance.
-- Fix the permissions and/or file ownership, free some space and attempt to
+- Fix the permissions and/or file ownership, free some space and attempt to
write again. Do not remove the existing file.
-- Use |:wshada| with bang. Does not help in case of permission error. If
- target file was actually the ShaDa file some information may be lost in this
- case. To make the matters slightly better use |:rshada| prior to writing,
- but this still will loose buffer-local marks and change list entries for any
+- Use |:wshada| with bang. Does not help in case of permission error. If
+ target file was actually the ShaDa file some information may be lost in this
+ case. To make the matters slightly better use |:rshada| prior to writing,
+ but this still will loose buffer-local marks and change list entries for any
file which is not opened in the current Neovim instance.
-- Remove the target file from shell and use |:wshada|. Consequences are not
- different from using |:wshada| with bang, but "rm -f" works in some cases
+- Remove the target file from shell and use |:wshada|. Consequences are not
+ different from using |:wshada| with bang, but "rm -f" works in some cases
when you don't have write permissions.
*:rsh* *:rshada* *E886*
@@ -1129,13 +1129,13 @@ running) you have additional options:
The information in the file is first read in to make
a merge between old and new info. When [!] is used,
the old information is not read first, only the
- internal info is written (also disables safety checks
- described in |shada-error-handling|). If 'shada' is
+ internal info is written (also disables safety checks
+ described in |shada-error-handling|). If 'shada' is
empty, marks for up to 100 files will be written.
- When you get error "E929: All .tmp.X files exist,
- cannot write ShaDa file!" check that no old temp files
- were left behind (e.g.
- ~/.local/share/nvim/shada/main.shada.tmp*).
+ When you get error "E929: All .tmp.X files exist,
+ cannot write ShaDa file!" check that no old temp files
+ were left behind (e.g.
+ ~/.local/state/nvim/shada/main.shada.tmp*).
Note: Executing :wshada will reset all |'quote| marks.
@@ -1158,82 +1158,82 @@ running) you have additional options:
SHADA FILE FORMAT *shada-format*
-ShaDa files are concats of MessagePack entries. Each entry is a concat of
+ShaDa files are concats of MessagePack entries. Each entry is a concat of
exactly four MessagePack objects:
-1. First goes type of the entry. Object type must be an unsigned integer.
+1. First goes type of the entry. Object type must be an unsigned integer.
Object type must not be equal to zero.
2. Second goes entry timestamp. It must also be an unsigned integer.
-3. Third goes the length of the fourth entry. Unsigned integer as well, used
+3. Third goes the length of the fourth entry. Unsigned integer as well, used
for fast skipping without parsing.
-4. Fourth is actual entry data. All currently used ShaDa entries use
- containers to hold data: either map or array. All string values in those
- containers are either binary (applies to filenames) or UTF-8, yet parser
+4. Fourth is actual entry data. All currently used ShaDa entries use
+ containers to hold data: either map or array. All string values in those
+ containers are either binary (applies to filenames) or UTF-8, yet parser
needs to expect that invalid bytes may be present in a UTF-8 string.
Exact format depends on the entry type:
Entry type (name) Entry data ~
- 1 (Header) Map containing data that describes the generator
- instance that wrote this ShaDa file. It is ignored
+ 1 (Header) Map containing data that describes the generator
+ instance that wrote this ShaDa file. It is ignored
when reading ShaDa files. Contains the following data:
Key Data ~
- generator Binary, software used to generate ShaDa
- file. Is equal to "nvim" when ShaDa file was
+ generator Binary, software used to generate ShaDa
+ file. Is equal to "nvim" when ShaDa file was
written by Neovim.
version Binary, generator version.
encoding Binary, effective 'encoding' value.
max_kbyte Integer, effective |shada-s| limit value.
pid Integer, instance process ID.
- * It is allowed to have any number of
+ * It is allowed to have any number of
additional keys with any data.
- 2 (SearchPattern) Map containing data describing last used search or
- substitute pattern. Normally ShaDa file contains two
- such entries: one with "ss" key set to true (describes
- substitute pattern, see |:substitute|), and one set to
- false (describes search pattern, see
- |search-commands|). "su" key should be true on one of
- the entries. If key value is equal to default then it
+ 2 (SearchPattern) Map containing data describing last used search or
+ substitute pattern. Normally ShaDa file contains two
+ such entries: one with "ss" key set to true (describes
+ substitute pattern, see |:substitute|), and one set to
+ false (describes search pattern, see
+ |search-commands|). "su" key should be true on one of
+ the entries. If key value is equal to default then it
is normally not present. Keys:
Key Type Default Description ~
sm Boolean true Effective 'magic' value.
sc Boolean false Effective 'smartcase' value.
- sl Boolean true True if search pattern comes
- with a line offset. See
+ sl Boolean true True if search pattern comes
+ with a line offset. See
|search-offset|.
- se Boolean false True if |search-offset|
- requested to place cursor at
- (relative to) the end of the
+ se Boolean false True if |search-offset|
+ requested to place cursor at
+ (relative to) the end of the
pattern.
so Integer 0 Offset value. |search-offset|
- su Boolean false True if current entry was the
+ su Boolean false True if current entry was the
last used search pattern.
- ss Boolean false True if current entry describes
+ ss Boolean false True if current entry describes
|:substitute| pattern.
sh Boolean false True if |v:hlsearch| is on.
- With |shada-h| or 'nohlsearch'
+ With |shada-h| or 'nohlsearch'
this key is always false.
sp Binary N/A Actual pattern. Required.
- sb Boolean false True if search direction is
+ sb Boolean false True if search direction is
backward.
- * any none Other keys are allowed for
- compatibility reasons, see
+ * any none Other keys are allowed for
+ compatibility reasons, see
|shada-compatibility|.
- 3 (SubString) Array containing last |:substitute| replacement string.
- Contains single entry: binary, replacement string used.
- More entries are allowed for compatibility reasons, see
+ 3 (SubString) Array containing last |:substitute| replacement string.
+ Contains single entry: binary, replacement string used.
+ More entries are allowed for compatibility reasons, see
|shada-compatibility|.
- 4 (HistoryEntry) Array containing one entry from history. Should have
- two or three entries. First one is history type
- (unsigned integer), second is history line (binary),
- third is the separator character (unsigned integer,
- must be in interval [0, 255]). Third item is only
- valid for search history. Possible history types are
- listed in |hist-names|, here are the corresponding
- numbers: 0 - cmd, 1 - search, 2 - expr, 3 - input,
+ 4 (HistoryEntry) Array containing one entry from history. Should have
+ two or three entries. First one is history type
+ (unsigned integer), second is history line (binary),
+ third is the separator character (unsigned integer,
+ must be in interval [0, 255]). Third item is only
+ valid for search history. Possible history types are
+ listed in |hist-names|, here are the corresponding
+ numbers: 0 - cmd, 1 - search, 2 - expr, 3 - input,
4 - debug.
- 5 (Register) Map describing one register (|registers|). If key
- value is equal to default then it is normally not
+ 5 (Register) Map describing one register (|registers|). If key
+ value is equal to default then it is normally not
present. Keys:
Key Type Def Description ~
rt UInteger 0 Register type:
@@ -1261,12 +1261,12 @@ exactly four MessagePack objects:
* any none Other keys are allowed
for compatibility reasons,
see |shada-compatibility|.
- 6 (Variable) Array containing two items: variable name (binary) and
- variable value (any object). Values are converted
- using the same code |msgpackparse()| uses when reading,
- |msgpackdump()| when writing, so there may appear
- |msgpack-special-dict|s. If there are more then two
- entries then the rest are ignored
+ 6 (Variable) Array containing two items: variable name (binary) and
+ variable value (any object). Values are converted
+ using the same code |msgpackparse()| uses when reading,
+ |msgpackdump()| when writing, so there may appear
+ |msgpack-special-dict|s. If there are more then two
+ entries then the rest are ignored
(|shada-compatibility|).
7 (GlobalMark)
8 (Jump)
@@ -1280,57 +1280,57 @@ exactly four MessagePack objects:
Data contained in the map:
Key Type Default Description ~
- l UInteger 1 Position line number. Must be
+ l UInteger 1 Position line number. Must be
greater then zero.
c UInteger 0 Position column number.
- n UInteger 34 ('"') Mark name. Only valid for
- GlobalMark and LocalMark
+ n UInteger 34 ('"') Mark name. Only valid for
+ GlobalMark and LocalMark
entries.
f Binary N/A File name. Required.
- * any none Other keys are allowed for
- compatibility reasons, see
+ * any none Other keys are allowed for
+ compatibility reasons, see
|shada-compatibility|.
- 9 (BufferList) Array containing maps. Each map in the array
+ 9 (BufferList) Array containing maps. Each map in the array
represents one buffer. Possible keys:
Key Type Default Description ~
- l UInteger 1 Position line number. Must be
+ l UInteger 1 Position line number. Must be
greater then zero.
c UInteger 0 Position column number.
f Binary N/A File name. Required.
- * any none Other keys are allowed for
- compatibility reasons, see
+ * any none Other keys are allowed for
+ compatibility reasons, see
|shada-compatibility|.
- * (Unknown) Any other entry type is allowed for compatibility
+ * (Unknown) Any other entry type is allowed for compatibility
reasons, see |shada-compatibility|.
*E575* *E576*
-Errors in ShaDa file may have two types: E575 used for all “logical†errors
-and E576 used for all “critical†errors. Critical errors trigger behaviour
-described in |shada-error-handling| when writing and skipping the rest of the
+Errors in ShaDa file may have two types: E575 used for all “logical†errors
+and E576 used for all “critical†errors. Critical errors trigger behaviour
+described in |shada-error-handling| when writing and skipping the rest of the
file when reading and include:
*shada-critical-contents-errors*
- Any of first three MessagePack objects being not an unsigned integer.
-- Third object requesting amount of bytes greater then bytes left in the ShaDa
+- Third object requesting amount of bytes greater then bytes left in the ShaDa
file.
- Entry with zero type. I.e. first object being equal to zero.
- MessagePack parser failing to parse the entry data.
-- MessagePack parser consuming less or requesting greater bytes then described
- in the third object for parsing fourth object. I.e. when fourth object
- either contains more then one MessagePack object or it does not contain
+- MessagePack parser consuming less or requesting greater bytes then described
+ in the third object for parsing fourth object. I.e. when fourth object
+ either contains more then one MessagePack object or it does not contain
complete MessagePack object.
==============================================================================
Standard Paths *standard-path*
-Nvim stores configuration, data, and logs in standard locations. Plugins are
-strongly encouraged to follow this pattern also. Use |stdpath()| to get the
+Nvim stores configuration, data, and logs in standard locations. Plugins are
+strongly encouraged to follow this pattern also. Use |stdpath()| to get the
paths.
*base-directories* *xdg*
The "base" (root) directories conform to the XDG Base Directory Specification.
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
-The $XDG_CONFIG_HOME and $XDG_DATA_HOME environment variables are used if they
-exist, otherwise default values (listed below) are used.
+The $XDG_CONFIG_HOME, $XDG_DATA_HOME and $XDG_STATE_HOME environment variables
+are used if they exist, otherwise default values (listed below) are used.
CONFIG DIRECTORY (DEFAULT) ~
*$XDG_CONFIG_HOME* Nvim: stdpath("config")
@@ -1342,6 +1342,11 @@ DATA DIRECTORY (DEFAULT) ~
Unix: ~/.local/share ~/.local/share/nvim
Windows: ~/AppData/Local ~/AppData/Local/nvim-data
+STATE DIRECTORY (DEFAULT) ~
+ *$XDG_STATE_HOME* Nvim: stdpath("state")
+ Unix: ~/.local/state ~/.local/state/nvim
+ Windows: ~/AppData/Local ~/AppData/Local/nvim-data
+
Note: Throughout the user manual these defaults are used as placeholders, e.g.
"~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config".
@@ -1349,7 +1354,7 @@ LOG FILE *$NVIM_LOG_FILE*
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
debugging, plugins and RPC clients. >
:echo $NVIM_LOG_FILE
-By default, the file is located at stdpath('cache')/log unless that path
+By default, the file is located at stdpath('log')/log unless that path
is inaccessible or if $NVIM_LOG_FILE was set before |startup|.
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index b10bf3498d..bc264bd971 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -472,8 +472,8 @@ parse_query({lang}, {query}) *parse_query()*
• `info.patterns` contains information about predicates.
Parameters: ~
- {lang} string The language
- {query} string A string containing the query (s-expr
+ {lang} (string) The language
+ {query} (string) A string containing the query (s-expr
syntax)
Return: ~
@@ -704,7 +704,7 @@ LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()*
Registers callbacks for the parser.
Parameters: ~
- {cbs} table An |nvim_buf_attach()|-like table argument
+ {cbs} (table) An |nvim_buf_attach()|-like table argument
with the following keys :
• `on_bytes` : see |nvim_buf_attach()|, but this will be
called after the parsers callback.
diff --git a/runtime/doc/usr_21.txt b/runtime/doc/usr_21.txt
index 44d653a1a7..add5d48073 100644
--- a/runtime/doc/usr_21.txt
+++ b/runtime/doc/usr_21.txt
@@ -352,12 +352,12 @@ another session.
this yourself then. Example: >
:mksession! ~/.config/nvim/secret.vim
- :wshada! ~/.local/share/nvim/shada/secret.shada
+ :wshada! ~/.local/state/nvim/shada/secret.shada
And to restore this again: >
:source ~/.config/nvim/secret.vim
- :rshada! ~/.local/share/nvim/shada/secret.shada
+ :rshada! ~/.local/state/nvim/shada/secret.shada
==============================================================================
*21.5* Views
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index e24dd46f49..1a3d6022ca 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -17,7 +17,7 @@ centralized reference of the differences.
- Use `$XDG_CONFIG_HOME/nvim/init.vim` instead of `.vimrc` for your |config|.
- Use `$XDG_CONFIG_HOME/nvim` instead of `.vim` to store configuration files.
-- Use `$XDG_DATA_HOME/nvim/shada/main.shada` instead of `.viminfo` for persistent
+- Use `$XDG_STATE_HOME/nvim/shada/main.shada` instead of `.viminfo` for persistent
session information. |shada|
==============================================================================
@@ -32,12 +32,12 @@ centralized reference of the differences.
- 'autoread' is enabled
- 'background' defaults to "dark" (unless set automatically by the terminal/UI)
- 'backspace' defaults to "indent,eol,start"
-- 'backupdir' defaults to .,~/.local/share/nvim/backup// (|xdg|), auto-created
+- 'backupdir' defaults to .,~/.local/state/nvim/backup// (|xdg|), auto-created
- 'belloff' defaults to "all"
- 'compatible' is always disabled
- 'complete' excludes "i"
- 'cscopeverbose' is enabled
-- 'directory' defaults to ~/.local/share/nvim/swap// (|xdg|), auto-created
+- 'directory' defaults to ~/.local/state/nvim/swap// (|xdg|), auto-created
- 'display' defaults to "lastline,msgsep"
- 'encoding' is UTF-8 (cf. 'fileencoding' for file-content encoding)
- 'fillchars' defaults (in effect) to "vert:│,fold:·,sep:│"
@@ -65,7 +65,7 @@ centralized reference of the differences.
- 'tags' defaults to "./tags;,tags"
- 'ttimeoutlen' defaults to 50
- 'ttyfast' is always set
-- 'undodir' defaults to ~/.local/share/nvim/undo// (|xdg|), auto-created
+- 'undodir' defaults to ~/.local/state/nvim/undo// (|xdg|), auto-created
- 'viewoptions' includes "unix,slash", excludes "options"
- 'viminfo' includes "!"
- 'wildmenu' is enabled
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index 47d55d8465..d2510c5494 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -7,23 +7,23 @@ if vim.g.do_filetype_lua ~= 1 then
return
end
-vim.api.nvim_create_augroup("filetypedetect", {clear = false})
+vim.api.nvim_create_augroup('filetypedetect', { clear = false })
-vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
- group = "filetypedetect",
+vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
+ group = 'filetypedetect',
callback = function()
- vim.filetype.match(vim.fn.expand("<afile>"))
+ vim.filetype.match(vim.fn.expand('<afile>'))
end,
})
-- These *must* be sourced after the autocommand above is created
if not vim.g.did_load_ftdetect then
- vim.cmd [[
+ vim.cmd([[
augroup filetypedetect
runtime! ftdetect/*.vim
runtime! ftdetect/*.lua
augroup END
- ]]
+ ]])
end
-- Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim
@@ -31,17 +31,17 @@ vim.g.did_load_ftdetect = 1
-- If filetype.vim is disabled, set up the autocmd to use scripts.vim
if vim.g.did_load_filetypes then
- vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
- group = "filetypedetect",
+ vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
+ group = 'filetypedetect',
command = "if !did_filetype() && expand('<amatch>') !~ g:ft_ignore_pat | runtime! scripts.vim | endif",
})
- vim.api.nvim_create_autocmd("StdinReadPost", {
- group = "filetypedetect",
- command = "if !did_filetype() | runtime! scripts.vim | endif",
+ vim.api.nvim_create_autocmd('StdinReadPost', {
+ group = 'filetypedetect',
+ command = 'if !did_filetype() | runtime! scripts.vim | endif',
})
end
if not vim.g.ft_ignore_pat then
- vim.g.ft_ignore_pat = "\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$"
+ vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
end
diff --git a/runtime/ftplugin/abaqus.vim b/runtime/ftplugin/abaqus.vim
index b263d0c318..5ce565ef3f 100644
--- a/runtime/ftplugin/abaqus.vim
+++ b/runtime/ftplugin/abaqus.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Abaqus finite element input file (www.abaqus.com)
" Maintainer: Carl Osterwisch <osterwischc@asme.org>
-" Last Change: 2012 Apr 30
+" Last Change: 2022 May 09
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin") | finish | endif
@@ -86,11 +86,11 @@ let b:undo_ftplugin .= "|unmap <buffer> [[|unmap <buffer> ]]"
\ . "|unmap <buffer> <LocalLeader><LocalLeader>"
" Undo must be done in nocompatible mode for <LocalLeader>.
-let b:undo_ftplugin = "let s:cpo_save = &cpoptions|"
+let b:undo_ftplugin = "let b:cpo_save = &cpoptions|"
\ . "set cpoptions&vim|"
\ . b:undo_ftplugin
- \ . "|let &cpoptions = s:cpo_save"
- \ . "|unlet s:cpo_save"
+ \ . "|let &cpoptions = b:cpo_save"
+ \ . "|unlet b:cpo_save"
" Restore saved compatibility options
let &cpoptions = s:cpo_save
diff --git a/runtime/ftplugin/query.lua b/runtime/ftplugin/query.lua
index c1694961af..3b99d67247 100644
--- a/runtime/ftplugin/query.lua
+++ b/runtime/ftplugin/query.lua
@@ -3,4 +3,4 @@
-- Last Change: 2022 Mar 29
-- it's a lisp!
-vim.cmd [[ runtime! ftplugin/lisp.vim ]]
+vim.cmd([[ runtime! ftplugin/lisp.vim ]])
diff --git a/runtime/indent/query.lua b/runtime/indent/query.lua
index 55cb73e62b..c86948e95e 100644
--- a/runtime/indent/query.lua
+++ b/runtime/indent/query.lua
@@ -3,4 +3,4 @@
-- Last Change: 2022 Mar 29
-- it's a lisp!
-vim.cmd [[ runtime! indent/lisp.vim ]]
+vim.cmd([[ runtime! indent/lisp.vim ]])
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index ba6b9d09c9..5da3d2a92f 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -8,7 +8,7 @@ local function highlight_line(line, linenr)
local overstrike, escape = false, false
local hls = {} -- Store highlight groups as { attr, start, final }
local NONE, BOLD, UNDERLINE, ITALIC = 0, 1, 2, 3
- local hl_groups = {[BOLD]="manBold", [UNDERLINE]="manUnderline", [ITALIC]="manItalic"}
+ local hl_groups = { [BOLD] = 'manBold', [UNDERLINE] = 'manUnderline', [ITALIC] = 'manItalic' }
local attr = NONE
local byte = 0 -- byte offset
@@ -47,7 +47,7 @@ local function highlight_line(line, linenr)
end
if continue_hl then
- hls[#hls + 1] = {attr=attr, start=byte, final=-1}
+ hls[#hls + 1] = { attr = attr, start = byte, final = -1 }
else
if attr == NONE then
for a, _ in pairs(hl_groups) do
@@ -63,7 +63,7 @@ local function highlight_line(line, linenr)
-- can be represented in one byte. Any code point above that is represented by
-- a leading byte (0xc0 and above) and continuation bytes (0x80 to 0xbf, or
-- decimal 128 to 191).
- for char in line:gmatch("[^\128-\191][\128-\191]*") do
+ for char in line:gmatch('[^\128-\191][\128-\191]*') do
if overstrike then
local last_hl = hls[#hls]
if char == prev_char then
@@ -93,7 +93,7 @@ local function highlight_line(line, linenr)
if last_hl and last_hl.attr == attr and last_hl.final == byte then
last_hl.final = byte + #char
else
- hls[#hls + 1] = {attr=attr, start=byte, final=byte + #char}
+ hls[#hls + 1] = { attr = attr, start = byte, final = byte + #char }
end
overstrike = false
@@ -106,25 +106,25 @@ local function highlight_line(line, linenr)
-- We only want to match against SGR sequences, which consist of ESC
-- followed by '[', then a series of parameter and intermediate bytes in
-- the range 0x20 - 0x3f, then 'm'. (See ECMA-48, sections 5.4 & 8.3.117)
- local sgr = prev_char:match("^%[([\032-\063]*)m$")
+ local sgr = prev_char:match('^%[([\032-\063]*)m$')
-- Ignore escape sequences with : characters, as specified by ITU's T.416
-- Open Document Architecture and interchange format.
- if sgr and not string.find(sgr, ":") then
+ if sgr and not string.find(sgr, ':') then
local match
while sgr and #sgr > 0 do
-- Match against SGR parameters, which may be separated by ';'
- match, sgr = sgr:match("^(%d*);?(.*)")
+ match, sgr = sgr:match('^(%d*);?(.*)')
add_attr_hl(match + 0) -- coerce to number
end
escape = false
- elseif not prev_char:match("^%[[\032-\063]*$") then
+ elseif not prev_char:match('^%[[\032-\063]*$') then
-- Stop looking if this isn't a partial CSI sequence
escape = false
end
- elseif char == "\027" then
+ elseif char == '\027' then
escape = true
prev_char = ''
- elseif char == "\b" then
+ elseif char == '\b' then
overstrike = true
prev_char = chars[#chars]
byte = byte - #prev_char
@@ -143,7 +143,7 @@ local function highlight_line(line, linenr)
hl_groups[hl.attr],
linenr - 1,
hl.start,
- hl.final
+ hl.final,
}
end
end
@@ -152,8 +152,8 @@ local function highlight_line(line, linenr)
end
local function highlight_man_page()
- local mod = vim.api.nvim_buf_get_option(0, "modifiable")
- vim.api.nvim_buf_set_option(0, "modifiable", true)
+ local mod = vim.api.nvim_buf_get_option(0, 'modifiable')
+ vim.api.nvim_buf_set_option(0, 'modifiable', true)
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
for i, line in ipairs(lines) do
@@ -166,7 +166,7 @@ local function highlight_man_page()
end
buf_hls = {}
- vim.api.nvim_buf_set_option(0, "modifiable", mod)
+ vim.api.nvim_buf_set_option(0, 'modifiable', mod)
end
return { highlight_man_page = highlight_man_page }
diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua
index 9327c652db..bca5ddf68b 100644
--- a/runtime/lua/vim/F.lua
+++ b/runtime/lua/vim/F.lua
@@ -5,13 +5,17 @@ local F = {}
---@param a
---@param b
function F.if_nil(a, b)
- if a == nil then return b end
+ if a == nil then
+ return b
+ end
return a
end
-- Use in combination with pcall
function F.ok_or_nil(status, ...)
- if not status then return end
+ if not status then
+ return
+ end
return ...
end
@@ -29,7 +33,7 @@ end
--- like {...} except preserve the length explicitly
function F.pack_len(...)
- return {n=select('#', ...), ...}
+ return { n = select('#', ...), ... }
end
--- like unpack() but use the length set by F.pack_len if present
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 119467de16..98921463b3 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -40,26 +40,28 @@ local vim = assert(vim)
-- These are for loading runtime modules lazily since they aren't available in
-- the nvim binary as specified in executor.c
-for k,v in pairs {
- treesitter=true;
- filetype = true;
- F=true;
- lsp=true;
- highlight=true;
- diagnostic=true;
- keymap=true;
- ui=true;
-} do vim._submodules[k] = v end
+for k, v in pairs({
+ treesitter = true,
+ filetype = true,
+ F = true,
+ lsp = true,
+ highlight = true,
+ diagnostic = true,
+ keymap = true,
+ ui = true,
+}) do
+ vim._submodules[k] = v
+end
vim.log = {
levels = {
- TRACE = 0;
- DEBUG = 1;
- INFO = 2;
- WARN = 3;
- ERROR = 4;
- OFF = 5;
- }
+ TRACE = 0,
+ DEBUG = 1,
+ INFO = 2,
+ WARN = 3,
+ ERROR = 4,
+ OFF = 5,
+ },
}
-- Internal-only until comments in #8107 are addressed.
@@ -77,14 +79,14 @@ function vim._os_proc_info(pid)
if pid == nil or pid <= 0 or type(pid) ~= 'number' then
error('invalid pid')
end
- local cmd = { 'ps', '-p', pid, '-o', 'comm=', }
+ local cmd = { 'ps', '-p', pid, '-o', 'comm=' }
local err, name = vim._system(cmd)
if 1 == err and vim.trim(name) == '' then
- return {} -- Process not found.
+ return {} -- Process not found.
elseif 0 ~= err then
- error('command failed: '..vim.fn.string(cmd))
+ error('command failed: ' .. vim.fn.string(cmd))
end
- local _, ppid = vim._system({ 'ps', '-p', pid, '-o', 'ppid=', })
+ local _, ppid = vim._system({ 'ps', '-p', pid, '-o', 'ppid=' })
-- Remove trailing whitespace.
name = vim.trim(name):gsub('^.*/', '')
ppid = tonumber(ppid) or -1
@@ -101,12 +103,12 @@ function vim._os_proc_children(ppid)
if ppid == nil or ppid <= 0 or type(ppid) ~= 'number' then
error('invalid ppid')
end
- local cmd = { 'pgrep', '-P', ppid, }
+ local cmd = { 'pgrep', '-P', ppid }
local err, rv = vim._system(cmd)
if 1 == err and vim.trim(rv) == '' then
- return {} -- Process not found.
+ return {} -- Process not found.
elseif 0 ~= err then
- error('command failed: '..vim.fn.string(cmd))
+ error('command failed: ' .. vim.fn.string(cmd))
end
local children = {}
for s in rv:gmatch('%S+') do
@@ -124,8 +126,8 @@ end
---
---@see https://github.com/kikito/inspect.lua
---@see https://github.com/mpeterv/vinspect
-local function inspect(object, options) -- luacheck: no unused
- error(object, options) -- Stub for gen_vimdoc.py
+local function inspect(object, options) -- luacheck: no unused
+ error(object, options) -- Stub for gen_vimdoc.py
end
do
@@ -160,11 +162,11 @@ do
local now = vim.loop.now()
local is_first_chunk = phase < 2
local is_last_chunk = phase == -1 or phase == 3
- if is_first_chunk then -- Reset flags.
+ if is_first_chunk then -- Reset flags.
tdots, tick, got_line1, undo_started, trailing_nl = now, 0, false, false, false
end
if #lines == 0 then
- lines = {''}
+ lines = { '' }
end
if #lines == 1 and lines[1] == '' and not is_last_chunk then
-- An empty chunk can cause some edge cases in streamed pasting,
@@ -172,7 +174,7 @@ do
return true
end
-- Note: mode doesn't always start with "c" in cmdline mode, so use getcmdtype() instead.
- if vim.fn.getcmdtype() ~= '' then -- cmdline-mode: paste only 1 line.
+ if vim.fn.getcmdtype() ~= '' then -- cmdline-mode: paste only 1 line.
if not got_line1 then
got_line1 = (#lines > 1)
-- Escape control characters
@@ -187,9 +189,9 @@ do
if undo_started then
vim.api.nvim_command('undojoin')
end
- if mode:find('^i') or mode:find('^n?t') then -- Insert mode or Terminal buffer
+ if mode:find('^i') or mode:find('^n?t') then -- Insert mode or Terminal buffer
vim.api.nvim_put(lines, 'c', false, true)
- elseif phase < 2 and mode:find('^R') and not mode:find('^Rv') then -- Replace mode
+ elseif phase < 2 and mode:find('^R') and not mode:find('^Rv') then -- Replace mode
-- TODO: implement Replace mode streamed pasting
-- TODO: support Virtual Replace mode
local nchars = 0
@@ -197,26 +199,26 @@ do
nchars = nchars + line:len()
end
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
- local bufline = vim.api.nvim_buf_get_lines(0, row-1, row, true)[1]
+ local bufline = vim.api.nvim_buf_get_lines(0, row - 1, row, true)[1]
local firstline = lines[1]
- firstline = bufline:sub(1, col)..firstline
+ firstline = bufline:sub(1, col) .. firstline
lines[1] = firstline
- lines[#lines] = lines[#lines]..bufline:sub(col + nchars + 1, bufline:len())
- vim.api.nvim_buf_set_lines(0, row-1, row, false, lines)
- elseif mode:find('^[nvV\22sS\19]') then -- Normal or Visual or Select mode
- if mode:find('^n') then -- Normal mode
+ lines[#lines] = lines[#lines] .. bufline:sub(col + nchars + 1, bufline:len())
+ vim.api.nvim_buf_set_lines(0, row - 1, row, false, lines)
+ elseif mode:find('^[nvV\22sS\19]') then -- Normal or Visual or Select mode
+ if mode:find('^n') then -- Normal mode
-- When there was a trailing new line in the previous chunk,
-- the cursor is on the first character of the next line,
-- so paste before the cursor instead of after it.
vim.api.nvim_put(lines, 'c', not trailing_nl, false)
- else -- Visual or Select mode
+ else -- Visual or Select mode
vim.api.nvim_command([[exe "silent normal! \<Del>"]])
local del_start = vim.fn.getpos("'[")
local cursor_pos = vim.fn.getpos('.')
- if mode:find('^[VS]') then -- linewise
- if cursor_pos[2] < del_start[2] then -- replacing lines at eof
+ if mode:find('^[VS]') then -- linewise
+ if cursor_pos[2] < del_start[2] then -- replacing lines at eof
-- create a new line
- vim.api.nvim_put({''}, 'l', true, true)
+ vim.api.nvim_put({ '' }, 'l', true, true)
end
vim.api.nvim_put(lines, 'c', false, false)
else
@@ -227,7 +229,7 @@ do
-- put cursor at the end of the text instead of one character after it
vim.fn.setpos('.', vim.fn.getpos("']"))
trailing_nl = lines[#lines] == ''
- else -- Don't know what to do in other modes
+ else -- Don't know what to do in other modes
return false
end
undo_started = true
@@ -240,9 +242,9 @@ do
vim.api.nvim_command(('echo "%s"'):format(dots))
end
if is_last_chunk then
- vim.api.nvim_command('redraw'..(tick > 1 and '|echo ""' or ''))
+ vim.api.nvim_command('redraw' .. (tick > 1 and '|echo ""' or ''))
end
- return true -- Paste will not continue if not returning `true`.
+ return true -- Paste will not continue if not returning `true`.
end
end
@@ -252,10 +254,12 @@ end
---@see |vim.schedule()|
---@see |vim.in_fast_event()|
function vim.schedule_wrap(cb)
- return (function (...)
+ return function(...)
local args = vim.F.pack_len(...)
- vim.schedule(function() cb(vim.F.unpack_len(args)) end)
- end)
+ vim.schedule(function()
+ cb(vim.F.unpack_len(args))
+ end)
+ end
end
-- vim.fn.{func}(...)
@@ -264,7 +268,7 @@ vim.fn = setmetatable({}, {
local _fn
if vim.api[key] ~= nil then
_fn = function()
- error(string.format("Tried to call API function with vim.fn: use vim.api.%s instead", key))
+ error(string.format('Tried to call API function with vim.fn: use vim.api.%s instead', key))
end
else
_fn = function(...)
@@ -273,16 +277,40 @@ vim.fn = setmetatable({}, {
end
t[key] = _fn
return _fn
- end
+ end,
})
vim.funcref = function(viml_func_name)
return vim.fn[viml_func_name]
end
--- An easier alias for commands.
-vim.cmd = function(command)
- return vim.api.nvim_exec(command, false)
+--- Execute Vim script commands.
+---
+--- Example:
+--- <pre>
+--- vim.cmd('echo 42')
+--- vim.cmd([[
+--- augroup My_group
+--- autocmd!
+--- autocmd FileType c setlocal cindent
+--- augroup END
+--- ]])
+--- vim.cmd({ cmd = 'echo', args = { '"foo"' } })
+--- </pre>
+---
+---@param command string|table Command(s) to execute.
+--- If a string, executes multiple lines of Vim script at once. In this
+--- case, it is an alias to |nvim_exec()|, where `output` is set to
+--- false. Thus it works identical to |:source|.
+--- If a table, executes a single command. In this case, it is an alias
+--- to |nvim_cmd()| where `opts` is empty.
+---@see |ex-cmd-index|
+function vim.cmd(command)
+ if type(command) == 'table' then
+ return vim.api.nvim_cmd(command, {})
+ else
+ return vim.api.nvim_exec(command, false)
+ end
end
-- These are the vim.env/v/g/o/bo/wo variable magic accessors.
@@ -291,9 +319,9 @@ do
--@private
local function make_dict_accessor(scope, handle)
- validate {
- scope = {scope, 's'};
- }
+ validate({
+ scope = { scope, 's' },
+ })
local mt = {}
function mt:__newindex(k, v)
return vim._setvar(scope, handle or 0, k, v)
@@ -343,7 +371,7 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive)
local region = {}
for l = pos1[1], pos2[1] do
local c1, c2
- if regtype:byte() == 22 then -- block selection: take width from regtype
+ if regtype:byte() == 22 then -- block selection: take width from regtype
c1 = pos1[2]
c2 = c1 + regtype:sub(2)
-- and adjust for non-ASCII characters
@@ -355,10 +383,10 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive)
c2 = vim.str_byteindex(bufline, c2)
end
else
- c1 = (l == pos1[1]) and (pos1[2]) or 0
+ c1 = (l == pos1[1]) and pos1[2] or 0
c2 = (l == pos2[1]) and (pos2[2] + (inclusive and 1 or 0)) or -1
end
- table.insert(region, l, {c1, c2})
+ table.insert(region, l, { c1, c2 })
end
return region
end
@@ -372,19 +400,22 @@ end
---@param timeout Number of milliseconds to wait before calling `fn`
---@return timer luv timer object
function vim.defer_fn(fn, timeout)
- vim.validate { fn = { fn, 'c', true}; }
+ vim.validate({ fn = { fn, 'c', true } })
local timer = vim.loop.new_timer()
- timer:start(timeout, 0, vim.schedule_wrap(function()
- timer:stop()
- timer:close()
+ timer:start(
+ timeout,
+ 0,
+ vim.schedule_wrap(function()
+ timer:stop()
+ timer:close()
- fn()
- end))
+ fn()
+ end)
+ )
return timer
end
-
--- Display a notification to the user.
---
--- This function can be overridden by plugins to display notifications using a
@@ -398,9 +429,9 @@ function vim.notify(msg, level, opts) -- luacheck: no unused args
if level == vim.log.levels.ERROR then
vim.api.nvim_err_writeln(msg)
elseif level == vim.log.levels.WARN then
- vim.api.nvim_echo({{msg, 'WarningMsg'}}, true, {})
+ vim.api.nvim_echo({ { msg, 'WarningMsg' } }, true, {})
else
- vim.api.nvim_echo({{msg}}, true, {})
+ vim.api.nvim_echo({ { msg } }, true, {})
end
end
@@ -453,10 +484,10 @@ function vim.on_key(fn, ns_id)
return #on_key_cbs
end
- vim.validate {
- fn = { fn, 'c', true},
- ns_id = { ns_id, 'n', true }
- }
+ vim.validate({
+ fn = { fn, 'c', true },
+ ns_id = { ns_id, 'n', true },
+ })
if ns_id == nil or ns_id == 0 then
ns_id = vim.api.nvim_create_namespace('')
@@ -481,10 +512,13 @@ function vim._on_key(char)
end
if failed_ns_ids[1] then
- error(string.format(
- "Error executing 'on_key' with ns_ids '%s'\n Messages: %s",
- table.concat(failed_ns_ids, ", "),
- table.concat(failed_messages, "\n")))
+ error(
+ string.format(
+ "Error executing 'on_key' with ns_ids '%s'\n Messages: %s",
+ table.concat(failed_ns_ids, ', '),
+ table.concat(failed_messages, '\n')
+ )
+ )
end
end
@@ -511,8 +545,10 @@ function vim._expand_pat(pat, env)
-- Probably just need to do a smarter match than just `:match`
-- Get the last part of the pattern
- local last_part = pat:match("[%w.:_%[%]'\"]+$")
- if not last_part then return {}, 0 end
+ local last_part = pat:match('[%w.:_%[%]\'"]+$')
+ if not last_part then
+ return {}, 0
+ end
local parts, search_index = vim._expand_pat_get_parts(last_part)
@@ -529,7 +565,7 @@ function vim._expand_pat(pat, env)
-- Normally, we just have a string
-- Just attempt to get the string directly from the environment
- if type(part) == "string" then
+ if type(part) == 'string' then
key = part
else
-- However, sometimes you want to use a variable, and complete on it
@@ -554,7 +590,7 @@ function vim._expand_pat(pat, env)
local field = rawget(final_env, key)
if field == nil then
local mt = getmetatable(final_env)
- if mt and type(mt.__index) == "table" then
+ if mt and type(mt.__index) == 'table' then
field = rawget(mt.__index, key)
elseif final_env == vim and vim._submodules[key] then
field = vim[key]
@@ -570,18 +606,18 @@ function vim._expand_pat(pat, env)
local keys = {}
---@private
local function insert_keys(obj)
- for k,_ in pairs(obj) do
- if type(k) == "string" and string.sub(k,1,string.len(match_part)) == match_part then
- table.insert(keys,k)
+ for k, _ in pairs(obj) do
+ if type(k) == 'string' and string.sub(k, 1, string.len(match_part)) == match_part then
+ table.insert(keys, k)
end
end
end
- if type(final_env) == "table" then
+ if type(final_env) == 'table' then
insert_keys(final_env)
end
local mt = getmetatable(final_env)
- if mt and type(mt.__index) == "table" then
+ if mt and type(mt.__index) == 'table' then
insert_keys(mt.__index)
end
if final_env == vim then
@@ -602,12 +638,12 @@ vim._expand_pat_get_parts = function(lua_string)
for idx = 1, #lua_string do
local s = lua_string:sub(idx, idx)
- if not in_brackets and (s == "." or s == ":") then
+ if not in_brackets and (s == '.' or s == ':') then
table.insert(parts, accumulator)
accumulator = ''
search_index = idx + 1
- elseif s == "[" then
+ elseif s == '[' then
in_brackets = true
table.insert(parts, accumulator)
@@ -619,7 +655,7 @@ vim._expand_pat_get_parts = function(lua_string)
in_brackets = false
search_index = idx + 1
- if string_char == "VAR" then
+ if string_char == 'VAR' then
table.insert(parts, { accumulator })
accumulator = ''
@@ -631,7 +667,7 @@ vim._expand_pat_get_parts = function(lua_string)
if s == '"' or s == "'" then
string_char = s
elseif s ~= ' ' then
- string_char = "VAR"
+ string_char = 'VAR'
accumulator = s
end
elseif string_char then
@@ -649,7 +685,9 @@ vim._expand_pat_get_parts = function(lua_string)
end
end
- parts = vim.tbl_filter(function(val) return #val > 0 end, parts)
+ parts = vim.tbl_filter(function(val)
+ return #val > 0
+ end, parts)
return parts, search_index
end
@@ -677,20 +715,20 @@ function vim._cs_remote(rcid, server_addr, connect_error, args)
local function connection_failure_errmsg(consequence)
local explanation
if server_addr == '' then
- explanation = "No server specified with --server"
+ explanation = 'No server specified with --server'
else
explanation = "Failed to connect to '" .. server_addr .. "'"
- if connect_error ~= "" then
- explanation = explanation .. ": " .. connect_error
+ if connect_error ~= '' then
+ explanation = explanation .. ': ' .. connect_error
end
end
- return "E247: " .. explanation .. ". " .. consequence
+ return 'E247: ' .. explanation .. '. ' .. consequence
end
local f_silent = false
local f_tab = false
- local subcmd = string.sub(args[1],10)
+ local subcmd = string.sub(args[1], 10)
if subcmd == 'tab' then
f_tab = true
elseif subcmd == 'silent' then
@@ -713,16 +751,18 @@ function vim._cs_remote(rcid, server_addr, connect_error, args)
print(vim.fn.rpcrequest(rcid, 'nvim_eval', args[2]))
return { should_exit = true, tabbed = false }
elseif subcmd ~= '' then
- return { errmsg='Unknown option argument: ' .. args[1] }
+ return { errmsg = 'Unknown option argument: ' .. args[1] }
end
if rcid == 0 then
if not f_silent then
- vim.notify(connection_failure_errmsg("Editing locally"), vim.log.levels.WARN)
+ vim.notify(connection_failure_errmsg('Editing locally'), vim.log.levels.WARN)
end
else
local command = {}
- if f_tab then table.insert(command, 'tab') end
+ if f_tab then
+ table.insert(command, 'tab')
+ end
table.insert(command, 'drop')
for i = 2, #args do
table.insert(command, vim.fn.fnameescape(args[i]))
@@ -745,11 +785,11 @@ end
---@param plugin string|nil Plugin name that the function will be removed
--- from. Defaults to "Nvim".
function vim.deprecate(name, alternative, version, plugin)
- local message = name .. ' is deprecated'
- plugin = plugin or "Nvim"
- message = alternative and (message .. ', use ' .. alternative .. ' instead.') or message
- message = message .. ' See :h deprecated\nThis function will be removed in ' .. plugin .. ' version ' .. version
- vim.notify_once(message, vim.log.levels.WARN)
+ local message = name .. ' is deprecated'
+ plugin = plugin or 'Nvim'
+ message = alternative and (message .. ', use ' .. alternative .. ' instead.') or message
+ message = message .. ' See :h deprecated\nThis function will be removed in ' .. plugin .. ' version ' .. version
+ vim.notify_once(message, vim.log.levels.WARN)
end
require('vim._meta')
diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua
index 7d27741f1b..7e3c73667e 100644
--- a/runtime/lua/vim/_init_packages.lua
+++ b/runtime/lua/vim/_init_packages.lua
@@ -3,8 +3,8 @@ local vim = assert(vim)
local pathtrails = {}
vim._so_trails = {}
-for s in (package.cpath..';'):gmatch('[^;]*;') do
- s = s:sub(1, -2) -- Strip trailing semicolon
+for s in (package.cpath .. ';'):gmatch('[^;]*;') do
+ s = s:sub(1, -2) -- Strip trailing semicolon
-- Find out path patterns. pathtrail should contain something like
-- /?.so, \?.dll. This allows not to bother determining what correct
-- suffixes are.
@@ -17,29 +17,29 @@ end
function vim._load_package(name)
local basename = name:gsub('%.', '/')
- local paths = {"lua/"..basename..".lua", "lua/"..basename.."/init.lua"}
- local found = vim.api.nvim__get_runtime(paths, false, {is_lua=true})
+ local paths = { 'lua/' .. basename .. '.lua', 'lua/' .. basename .. '/init.lua' }
+ local found = vim.api.nvim__get_runtime(paths, false, { is_lua = true })
if #found > 0 then
local f, err = loadfile(found[1])
return f or error(err)
end
local so_paths = {}
- for _,trail in ipairs(vim._so_trails) do
- local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
+ for _, trail in ipairs(vim._so_trails) do
+ local path = 'lua' .. trail:gsub('?', basename) -- so_trails contains a leading slash
table.insert(so_paths, path)
end
- found = vim.api.nvim__get_runtime(so_paths, false, {is_lua=true})
+ found = vim.api.nvim__get_runtime(so_paths, false, { is_lua = true })
if #found > 0 then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
-- a) strip prefix up to and including the first dash, if any
-- b) replace all dots by underscores
-- c) prepend "luaopen_"
-- So "foo-bar.baz" should result in "luaopen_bar_baz"
- local dash = name:find("-", 1, true)
+ local dash = name:find('-', 1, true)
local modname = dash and name:sub(dash + 1) or name
- local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
+ local f, err = package.loadlib(found[1], 'luaopen_' .. modname:gsub('%.', '_'))
return f or error(err)
end
return nil
@@ -49,15 +49,15 @@ end
table.insert(package.loaders, 2, vim._load_package)
-- builtin functions which always should be available
-require'vim.shared'
+require('vim.shared')
-vim._submodules = {inspect=true}
+vim._submodules = { inspect = true }
-- These are for loading runtime modules in the vim namespace lazily.
setmetatable(vim, {
__index = function(t, key)
if vim._submodules[key] then
- t[key] = require('vim.'..key)
+ t[key] = require('vim.' .. key)
return t[key]
elseif vim.startswith(key, 'uri_') then
local val = require('vim.uri')[key]
@@ -67,7 +67,7 @@ setmetatable(vim, {
return t[key]
end
end
- end
+ end,
})
--- <Docs described in |vim.empty_dict()| >
@@ -79,5 +79,5 @@ end
-- only on main thread: functions for interacting with editor state
if not vim.is_thread() then
- require'vim._editor'
+ require('vim._editor')
end
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index 522e26caa7..1706956bca 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -5,15 +5,17 @@ local a = vim.api
local validate = vim.validate
local SET_TYPES = setmetatable({
- SET = 0,
- LOCAL = 1,
+ SET = 0,
+ LOCAL = 1,
GLOBAL = 2,
}, { __index = error })
local options_info = {}
for _, v in pairs(a.nvim_get_all_options_info()) do
options_info[v.name] = v
- if v.shortname ~= "" then options_info[v.shortname] = v end
+ if v.shortname ~= '' then
+ options_info[v.shortname] = v
+ end
end
local get_scoped_options = function(scope)
@@ -27,19 +29,21 @@ local get_scoped_options = function(scope)
return result
end
-local buf_options = get_scoped_options("buf")
-local glb_options = get_scoped_options("global")
-local win_options = get_scoped_options("win")
+local buf_options = get_scoped_options('buf')
+local glb_options = get_scoped_options('global')
+local win_options = get_scoped_options('win')
local function make_meta_accessor(get, set, del, validator)
- validator = validator or function() return true end
+ validator = validator or function()
+ return true
+ end
- validate {
- get = {get, 'f'};
- set = {set, 'f'};
- del = {del, 'f', true};
- validator = {validator, 'f'};
- }
+ validate({
+ get = { get, 'f' },
+ set = { set, 'f' },
+ del = { del, 'f', true },
+ validator = { validator, 'f' },
+ })
local mt = {}
function mt:__newindex(k, v)
@@ -73,7 +77,7 @@ end, vim.fn.setenv)
do -- buffer option accessor
local function new_buf_opt_accessor(bufnr)
local function get(k)
- if bufnr == nil and type(k) == "number" then
+ if bufnr == nil and type(k) == 'number' then
return new_buf_opt_accessor(k)
end
@@ -103,7 +107,7 @@ end
do -- window option accessor
local function new_win_opt_accessor(winnr)
local function get(k)
- if winnr == nil and type(k) == "number" then
+ if winnr == nil and type(k) == 'number' then
return new_win_opt_accessor(k)
end
return a.nvim_win_get_option(winnr or 0, k)
@@ -131,17 +135,19 @@ end
-- vim global option
-- this ONLY sets the global option. like `setglobal`
-vim.go = make_meta_accessor(
- function(k) return a.nvim_get_option_value(k, {scope = "global"}) end,
- function(k, v) return a.nvim_set_option_value(k, v, {scope = "global"}) end
-)
+vim.go = make_meta_accessor(function(k)
+ return a.nvim_get_option_value(k, { scope = 'global' })
+end, function(k, v)
+ return a.nvim_set_option_value(k, v, { scope = 'global' })
+end)
-- vim `set` style options.
-- it has no additional metamethod magic.
-vim.o = make_meta_accessor(
- function(k) return a.nvim_get_option_value(k, {}) end,
- function(k, v) return a.nvim_set_option_value(k, v, {}) end
-)
+vim.o = make_meta_accessor(function(k)
+ return a.nvim_get_option_value(k, {})
+end, function(k, v)
+ return a.nvim_set_option_value(k, v, {})
+end)
---@brief [[
--- vim.opt, vim.opt_local and vim.opt_global implementation
@@ -154,7 +160,9 @@ vim.o = make_meta_accessor(
--- Preserves the order and does not mutate the original list
local remove_duplicate_values = function(t)
local result, seen = {}, {}
- if type(t) == "function" then error(debug.traceback("asdf")) end
+ if type(t) == 'function' then
+ error(debug.traceback('asdf'))
+ end
for _, v in ipairs(t) do
if not seen[v] then
table.insert(result, v)
@@ -171,37 +179,41 @@ end
local key_value_options = {
fillchars = true,
listchars = true,
- winhl = true,
+ winhl = true,
}
---@class OptionTypes
--- Option Type Enum
local OptionTypes = setmetatable({
BOOLEAN = 0,
- NUMBER = 1,
- STRING = 2,
- ARRAY = 3,
- MAP = 4,
- SET = 5,
+ NUMBER = 1,
+ STRING = 2,
+ ARRAY = 3,
+ MAP = 4,
+ SET = 5,
}, {
- __index = function(_, k) error("Not a valid OptionType: " .. k) end,
- __newindex = function(_, k) error("Cannot set a new OptionType: " .. k) end,
+ __index = function(_, k)
+ error('Not a valid OptionType: ' .. k)
+ end,
+ __newindex = function(_, k)
+ error('Cannot set a new OptionType: ' .. k)
+ end,
})
--- Convert a vimoption_T style dictionary to the correct OptionType associated with it.
---@return OptionType
local get_option_type = function(name, info)
- if info.type == "boolean" then
+ if info.type == 'boolean' then
return OptionTypes.BOOLEAN
- elseif info.type == "number" then
+ elseif info.type == 'number' then
return OptionTypes.NUMBER
- elseif info.type == "string" then
+ elseif info.type == 'string' then
if not info.commalist and not info.flaglist then
return OptionTypes.STRING
end
if key_value_options[name] then
- assert(info.commalist, "Must be a comma list to use key:value style")
+ assert(info.commalist, 'Must be a comma list to use key:value style')
return OptionTypes.MAP
end
@@ -211,13 +223,12 @@ local get_option_type = function(name, info)
return OptionTypes.ARRAY
end
- error("Fallthrough in OptionTypes")
+ error('Fallthrough in OptionTypes')
else
- error("Not a known info.type:" .. info.type)
+ error('Not a known info.type:' .. info.type)
end
end
-
-- Check whether the OptionTypes is allowed for vim.opt
-- If it does not match, throw an error which indicates which option causes the error.
local function assert_valid_value(name, value, types)
@@ -228,16 +239,18 @@ local function assert_valid_value(name, value, types)
end
end
- error(string.format("Invalid option type '%s' for '%s', should be %s", type_of_value, name, table.concat(types, " or ")))
+ error(
+ string.format("Invalid option type '%s' for '%s', should be %s", type_of_value, name, table.concat(types, ' or '))
+ )
end
local valid_types = {
- [OptionTypes.BOOLEAN] = { "boolean" },
- [OptionTypes.NUMBER] = { "number" },
- [OptionTypes.STRING] = { "string" },
- [OptionTypes.SET] = { "string", "table" },
- [OptionTypes.ARRAY] = { "string", "table" },
- [OptionTypes.MAP] = { "string", "table" },
+ [OptionTypes.BOOLEAN] = { 'boolean' },
+ [OptionTypes.NUMBER] = { 'number' },
+ [OptionTypes.STRING] = { 'string' },
+ [OptionTypes.SET] = { 'string', 'table' },
+ [OptionTypes.ARRAY] = { 'string', 'table' },
+ [OptionTypes.MAP] = { 'string', 'table' },
}
--- Convert a lua value to a vimoption_T value
@@ -245,12 +258,20 @@ local convert_value_to_vim = (function()
-- Map of functions to take a Lua style value and convert to vimoption_T style value.
-- Each function takes (info, lua_value) -> vim_value
local to_vim_value = {
- [OptionTypes.BOOLEAN] = function(_, value) return value end,
- [OptionTypes.NUMBER] = function(_, value) return value end,
- [OptionTypes.STRING] = function(_, value) return value end,
+ [OptionTypes.BOOLEAN] = function(_, value)
+ return value
+ end,
+ [OptionTypes.NUMBER] = function(_, value)
+ return value
+ end,
+ [OptionTypes.STRING] = function(_, value)
+ return value
+ end,
[OptionTypes.SET] = function(info, value)
- if type(value) == "string" then return value end
+ if type(value) == 'string' then
+ return value
+ end
if info.flaglist and info.commalist then
local keys = {}
@@ -261,7 +282,7 @@ local convert_value_to_vim = (function()
end
table.sort(keys)
- return table.concat(keys, ",")
+ return table.concat(keys, ',')
else
local result = ''
for k, v in pairs(value) do
@@ -275,23 +296,27 @@ local convert_value_to_vim = (function()
end,
[OptionTypes.ARRAY] = function(info, value)
- if type(value) == "string" then return value end
+ if type(value) == 'string' then
+ return value
+ end
if not info.allows_duplicates then
value = remove_duplicate_values(value)
end
- return table.concat(value, ",")
+ return table.concat(value, ',')
end,
[OptionTypes.MAP] = function(_, value)
- if type(value) == "string" then return value end
+ if type(value) == 'string' then
+ return value
+ end
local result = {}
for opt_key, opt_value in pairs(value) do
- table.insert(result, string.format("%s:%s", opt_key, opt_value))
+ table.insert(result, string.format('%s:%s', opt_key, opt_value))
end
table.sort(result)
- return table.concat(result, ",")
+ return table.concat(result, ',')
end,
}
@@ -312,12 +337,18 @@ local convert_value_to_lua = (function()
-- Map of OptionType to functions that take vimoption_T values and convert to lua values.
-- Each function takes (info, vim_value) -> lua_value
local to_lua_value = {
- [OptionTypes.BOOLEAN] = function(_, value) return value end,
- [OptionTypes.NUMBER] = function(_, value) return value end,
- [OptionTypes.STRING] = function(_, value) return value end,
+ [OptionTypes.BOOLEAN] = function(_, value)
+ return value
+ end,
+ [OptionTypes.NUMBER] = function(_, value)
+ return value
+ end,
+ [OptionTypes.STRING] = function(_, value)
+ return value
+ end,
[OptionTypes.ARRAY] = function(info, value)
- if type(value) == "table" then
+ if type(value) == 'table' then
if not info.allows_duplicates then
value = remove_duplicate_values(value)
end
@@ -332,41 +363,43 @@ local convert_value_to_lua = (function()
end
-- Handles unescaped commas in a list.
- if string.find(value, ",,,") then
- local comma_split = vim.split(value, ",,,")
+ if string.find(value, ',,,') then
+ local comma_split = vim.split(value, ',,,')
local left = comma_split[1]
local right = comma_split[2]
local result = {}
- vim.list_extend(result, vim.split(left, ","))
- table.insert(result, ",")
- vim.list_extend(result, vim.split(right, ","))
+ vim.list_extend(result, vim.split(left, ','))
+ table.insert(result, ',')
+ vim.list_extend(result, vim.split(right, ','))
table.sort(result)
return result
end
- if string.find(value, ",^,,", 1, true) then
- local comma_split = vim.split(value, ",^,,", true)
+ if string.find(value, ',^,,', 1, true) then
+ local comma_split = vim.split(value, ',^,,', true)
local left = comma_split[1]
local right = comma_split[2]
local result = {}
- vim.list_extend(result, vim.split(left, ","))
- table.insert(result, "^,")
- vim.list_extend(result, vim.split(right, ","))
+ vim.list_extend(result, vim.split(left, ','))
+ table.insert(result, '^,')
+ vim.list_extend(result, vim.split(right, ','))
table.sort(result)
return result
end
- return vim.split(value, ",")
+ return vim.split(value, ',')
end,
[OptionTypes.SET] = function(info, value)
- if type(value) == "table" then return value end
+ if type(value) == 'table' then
+ return value
+ end
-- Empty strings mean that there is nothing there,
-- so empty table should be returned.
@@ -374,10 +407,10 @@ local convert_value_to_lua = (function()
return {}
end
- assert(info.flaglist, "That is the only one I know how to handle")
+ assert(info.flaglist, 'That is the only one I know how to handle')
if info.flaglist and info.commalist then
- local split_value = vim.split(value, ",")
+ local split_value = vim.split(value, ',')
local result = {}
for _, v in ipairs(split_value) do
result[v] = true
@@ -395,15 +428,17 @@ local convert_value_to_lua = (function()
end,
[OptionTypes.MAP] = function(info, raw_value)
- if type(raw_value) == "table" then return raw_value end
+ if type(raw_value) == 'table' then
+ return raw_value
+ end
- assert(info.commalist, "Only commas are supported currently")
+ assert(info.commalist, 'Only commas are supported currently')
local result = {}
- local comma_split = vim.split(raw_value, ",")
+ local comma_split = vim.split(raw_value, ',')
for _, key_value_str in ipairs(comma_split) do
- local key, value = unpack(vim.split(key_value_str, ":"))
+ local key, value = unpack(vim.split(key_value_str, ':'))
key = vim.trim(key)
result[key] = value
@@ -443,17 +478,21 @@ local prepend_value = (function()
end,
[OptionTypes.MAP] = function(left, right)
- return vim.tbl_extend("force", left, right)
+ return vim.tbl_extend('force', left, right)
end,
[OptionTypes.SET] = function(left, right)
- return vim.tbl_extend("force", left, right)
+ return vim.tbl_extend('force', left, right)
end,
}
return function(name, info, current, new)
return value_mutator(
- name, info, convert_value_to_lua(name, info, current), convert_value_to_lua(name, info, new), methods
+ name,
+ info,
+ convert_value_to_lua(name, info, current),
+ convert_value_to_lua(name, info, new),
+ methods
)
end
end)()
@@ -478,17 +517,21 @@ local add_value = (function()
end,
[OptionTypes.MAP] = function(left, right)
- return vim.tbl_extend("force", left, right)
+ return vim.tbl_extend('force', left, right)
end,
[OptionTypes.SET] = function(left, right)
- return vim.tbl_extend("force", left, right)
+ return vim.tbl_extend('force', left, right)
end,
}
return function(name, info, current, new)
return value_mutator(
- name, info, convert_value_to_lua(name, info, current), convert_value_to_lua(name, info, new), methods
+ name,
+ info,
+ convert_value_to_lua(name, info, current),
+ convert_value_to_lua(name, info, new),
+ methods
)
end
end)()
@@ -518,11 +561,11 @@ local remove_value = (function()
end,
[OptionTypes.STRING] = function()
- error("Subtraction not supported for strings.")
+ error('Subtraction not supported for strings.')
end,
[OptionTypes.ARRAY] = function(left, right)
- if type(right) == "string" then
+ if type(right) == 'string' then
remove_one_item(left, right)
else
for _, v in ipairs(right) do
@@ -534,7 +577,7 @@ local remove_value = (function()
end,
[OptionTypes.MAP] = function(left, right)
- if type(right) == "string" then
+ if type(right) == 'string' then
left[right] = nil
else
for _, v in ipairs(right) do
@@ -546,7 +589,7 @@ local remove_value = (function()
end,
[OptionTypes.SET] = function(left, right)
- if type(right) == "string" then
+ if type(right) == 'string' then
left[right] = nil
else
for _, v in ipairs(right) do
@@ -567,9 +610,9 @@ local create_option_metatable = function(set_type)
local set_mt, option_mt
local make_option = function(name, value)
- local info = assert(options_info[name], "Not a valid option name: " .. name)
+ local info = assert(options_info[name], 'Not a valid option name: ' .. name)
- if type(value) == "table" and getmetatable(value) == option_mt then
+ if type(value) == 'table' and getmetatable(value) == option_mt then
assert(name == value._name, "must be the same value, otherwise that's weird.")
value = value._value
@@ -584,9 +627,9 @@ local create_option_metatable = function(set_type)
local scope
if set_type == SET_TYPES.GLOBAL then
- scope = "global"
+ scope = 'global'
elseif set_type == SET_TYPES.LOCAL then
- scope = "local"
+ scope = 'local'
end
option_mt = {
@@ -594,7 +637,7 @@ local create_option_metatable = function(set_type)
-- opt[my_option] = value
_set = function(self)
local value = convert_value_to_vim(self._name, self._info, self._value)
- a.nvim_set_option_value(self._name, value, {scope = scope})
+ a.nvim_set_option_value(self._name, value, { scope = scope })
return self
end,
@@ -625,13 +668,13 @@ local create_option_metatable = function(set_type)
__sub = function(self, right)
return make_option(self._name, remove_value(self._name, self._info, self._value, right))
- end
+ end,
}
option_mt.__index = option_mt
set_mt = {
__index = function(_, k)
- return make_option(k, a.nvim_get_option_value(k, {scope = scope}))
+ return make_option(k, a.nvim_get_option_value(k, { scope = scope }))
end,
__newindex = function(_, k, v)
diff --git a/runtime/lua/vim/compat.lua b/runtime/lua/vim/compat.lua
index 168979bb95..2c9786d491 100644
--- a/runtime/lua/vim/compat.lua
+++ b/runtime/lua/vim/compat.lua
@@ -7,6 +7,6 @@
local lua_version = _VERSION:sub(-3)
-if lua_version >= "5.2" then
- unpack = table.unpack -- luacheck: ignore 121 143
+if lua_version >= '5.2' then
+ unpack = table.unpack -- luacheck: ignore 121 143
end
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 80ce1f331d..bb12362234 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -28,7 +28,7 @@ local global_diagnostic_options = {
M.handlers = setmetatable({}, {
__newindex = function(t, name, handler)
- vim.validate { handler = {handler, "t" } }
+ vim.validate({ handler = { handler, 't' } })
rawset(t, name, handler)
if global_diagnostic_options[name] == nil then
global_diagnostic_options[name] = true
@@ -39,7 +39,7 @@ M.handlers = setmetatable({}, {
-- Metatable that automatically creates an empty table when assigning to a missing key
local bufnr_and_namespace_cacher_mt = {
__index = function(t, bufnr)
- assert(bufnr > 0, "Invalid buffer number")
+ assert(bufnr > 0, 'Invalid buffer number')
t[bufnr] = {}
return t[bufnr]
end,
@@ -47,11 +47,11 @@ local bufnr_and_namespace_cacher_mt = {
local diagnostic_cache = setmetatable({}, {
__index = function(t, bufnr)
- assert(bufnr > 0, "Invalid buffer number")
+ assert(bufnr > 0, 'Invalid buffer number')
vim.api.nvim_buf_attach(bufnr, false, {
on_detach = function()
rawset(t, bufnr, nil) -- clear cache
- end
+ end,
})
t[bufnr] = {}
return t[bufnr]
@@ -68,7 +68,7 @@ local all_namespaces = {}
---@private
local function to_severity(severity)
if type(severity) == 'string' then
- return assert(M.severity[string.upper(severity)], string.format("Invalid severity: %s", severity))
+ return assert(M.severity[string.upper(severity)], string.format('Invalid severity: %s', severity))
end
return severity
end
@@ -79,15 +79,19 @@ local function filter_by_severity(severity, diagnostics)
return diagnostics
end
- if type(severity) ~= "table" then
+ if type(severity) ~= 'table' then
severity = to_severity(severity)
- return vim.tbl_filter(function(t) return t.severity == severity end, diagnostics)
+ return vim.tbl_filter(function(t)
+ return t.severity == severity
+ end, diagnostics)
end
local min_severity = to_severity(severity.min) or M.severity.HINT
local max_severity = to_severity(severity.max) or M.severity.ERROR
- return vim.tbl_filter(function(t) return t.severity <= min_severity and t.severity >= max_severity end, diagnostics)
+ return vim.tbl_filter(function(t)
+ return t.severity <= min_severity and t.severity >= max_severity
+ end, diagnostics)
end
---@private
@@ -113,17 +117,17 @@ local function prefix_source(diagnostics)
end
local t = vim.deepcopy(d)
- t.message = string.format("%s: %s", d.source, d.message)
+ t.message = string.format('%s: %s', d.source, d.message)
return t
end, diagnostics)
end
---@private
local function reformat_diagnostics(format, diagnostics)
- vim.validate {
- format = {format, 'f'},
- diagnostics = {diagnostics, 't'},
- }
+ vim.validate({
+ format = { format, 'f' },
+ diagnostics = { diagnostics, 't' },
+ })
local formatted = vim.deepcopy(diagnostics)
for _, diagnostic in ipairs(formatted) do
@@ -135,11 +139,11 @@ end
---@private
local function enabled_value(option, namespace)
local ns = namespace and M.get_namespace(namespace) or {}
- if ns.opts and type(ns.opts[option]) == "table" then
+ if ns.opts and type(ns.opts[option]) == 'table' then
return ns.opts[option]
end
- if type(global_diagnostic_options[option]) == "table" then
+ if type(global_diagnostic_options[option]) == 'table' then
return global_diagnostic_options[option]
end
@@ -162,7 +166,7 @@ local function resolve_optional_value(option, value, namespace, bufnr)
elseif type(value) == 'table' then
return value
else
- error("Unexpected option type: " .. vim.inspect(value))
+ error('Unexpected option type: ' .. vim.inspect(value))
end
end
@@ -181,10 +185,10 @@ end
-- Default diagnostic highlights
local diagnostic_severities = {
- [M.severity.ERROR] = { ctermfg = 1, guifg = "Red" };
- [M.severity.WARN] = { ctermfg = 3, guifg = "Orange" };
- [M.severity.INFO] = { ctermfg = 4, guifg = "LightBlue" };
- [M.severity.HINT] = { ctermfg = 7, guifg = "LightGrey" };
+ [M.severity.ERROR] = { ctermfg = 1, guifg = 'Red' },
+ [M.severity.WARN] = { ctermfg = 3, guifg = 'Orange' },
+ [M.severity.INFO] = { ctermfg = 4, guifg = 'LightBlue' },
+ [M.severity.HINT] = { ctermfg = 7, guifg = 'LightGrey' },
}
-- Make a map from DiagnosticSeverity -> Highlight Name
@@ -194,16 +198,16 @@ local function make_highlight_map(base_name)
for k in pairs(diagnostic_severities) do
local name = M.severity[k]
name = name:sub(1, 1) .. name:sub(2):lower()
- result[k] = "Diagnostic" .. base_name .. name
+ result[k] = 'Diagnostic' .. base_name .. name
end
return result
end
-local virtual_text_highlight_map = make_highlight_map("VirtualText")
-local underline_highlight_map = make_highlight_map("Underline")
-local floating_highlight_map = make_highlight_map("Floating")
-local sign_highlight_map = make_highlight_map("Sign")
+local virtual_text_highlight_map = make_highlight_map('VirtualText')
+local underline_highlight_map = make_highlight_map('Underline')
+local floating_highlight_map = make_highlight_map('Floating')
+local sign_highlight_map = make_highlight_map('Sign')
---@private
local define_default_signs = (function()
@@ -244,7 +248,7 @@ local function is_disabled(namespace, bufnr)
return true
end
- if type(diagnostic_disabled[bufnr]) == "table" then
+ if type(diagnostic_disabled[bufnr]) == 'table' then
return diagnostic_disabled[bufnr][namespace]
end
return diagnostic_disabled[bufnr]
@@ -271,8 +275,8 @@ end
---@private
local function set_diagnostic_cache(namespace, bufnr, diagnostics)
for _, diagnostic in ipairs(diagnostics) do
- assert(diagnostic.lnum, "Diagnostic line number is required")
- assert(diagnostic.col, "Diagnostic column is required")
+ assert(diagnostic.lnum, 'Diagnostic line number is required')
+ assert(diagnostic.col, 'Diagnostic column is required')
diagnostic.severity = diagnostic.severity and to_severity(diagnostic.severity) or M.severity.ERROR
diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum
diagnostic.end_col = diagnostic.end_col or diagnostic.col
@@ -285,7 +289,7 @@ end
---@private
local function restore_extmarks(bufnr, last)
for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
- local extmarks_current = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true})
+ local extmarks_current = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, { details = true })
local found = {}
for _, extmark in ipairs(extmarks_current) do
-- nvim_buf_set_lines will move any extmark to the line after the last
@@ -314,10 +318,17 @@ local function save_extmarks(namespace, bufnr)
end,
on_detach = function()
diagnostic_cache_extmarks[bufnr] = nil
- end})
+ end,
+ })
diagnostic_attached_buffers[bufnr] = true
end
- diagnostic_cache_extmarks[bufnr][namespace] = vim.api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, {details = true})
+ diagnostic_cache_extmarks[bufnr][namespace] = vim.api.nvim_buf_get_extmarks(
+ bufnr,
+ namespace,
+ 0,
+ -1,
+ { details = true }
+ )
end
local registered_autocmds = {}
@@ -325,11 +336,11 @@ local registered_autocmds = {}
---@private
local function make_augroup_key(namespace, bufnr)
local ns = M.get_namespace(namespace)
- return string.format("DiagnosticInsertLeave:%s:%s", bufnr, ns.name)
+ return string.format('DiagnosticInsertLeave:%s:%s', bufnr, ns.name)
end
--- Table of autocmd events to fire the update for displaying new diagnostic information
-local insert_leave_auto_cmds = { "InsertLeave", "CursorHoldI" }
+local insert_leave_auto_cmds = { 'InsertLeave', 'CursorHoldI' }
---@private
local function schedule_display(namespace, bufnr, args)
@@ -337,15 +348,17 @@ local function schedule_display(namespace, bufnr, args)
local key = make_augroup_key(namespace, bufnr)
if not registered_autocmds[key] then
- vim.cmd(string.format([[augroup %s
+ vim.cmd(string.format(
+ [[augroup %s
au!
autocmd %s <buffer=%s> lua vim.diagnostic._execute_scheduled_display(%s, %s)
augroup END]],
key,
- table.concat(insert_leave_auto_cmds, ","),
+ table.concat(insert_leave_auto_cmds, ','),
bufnr,
namespace,
- bufnr))
+ bufnr
+ ))
registered_autocmds[key] = true
end
end
@@ -355,9 +368,12 @@ local function clear_scheduled_display(namespace, bufnr)
local key = make_augroup_key(namespace, bufnr)
if registered_autocmds[key] then
- vim.cmd(string.format([[augroup %s
+ vim.cmd(string.format(
+ [[augroup %s
au!
- augroup END]], key))
+ augroup END]],
+ key
+ ))
registered_autocmds[key] = nil
end
end
@@ -382,7 +398,7 @@ local function get_diagnostics(bufnr, opts, clamp)
if not opts.lnum or d.lnum == opts.lnum then
if clamp and vim.api.nvim_buf_is_loaded(b) then
local line_count = buf_line_count[b] - 1
- if (d.lnum > line_count or d.end_lnum > line_count or d.lnum < 0 or d.end_lnum < 0) then
+ if d.lnum > line_count or d.end_lnum > line_count or d.lnum < 0 or d.end_lnum < 0 then
d = vim.deepcopy(d)
d.lnum = math.max(math.min(d.lnum, line_count), 0)
d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0)
@@ -431,7 +447,7 @@ end
local function set_list(loclist, opts)
opts = opts or {}
local open = vim.F.if_nil(opts.open, true)
- local title = opts.title or "Diagnostics"
+ local title = opts.title or 'Diagnostics'
local winnr = opts.winnr or 0
local bufnr
if loclist then
@@ -447,7 +463,7 @@ local function set_list(loclist, opts)
vim.fn.setqflist({}, ' ', { title = title, items = items })
end
if open then
- vim.api.nvim_command(loclist and "lopen" or "botright copen")
+ vim.api.nvim_command(loclist and 'lopen' or 'botright copen')
end
end
@@ -457,7 +473,7 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
bufnr = get_bufnr(bufnr)
local wrap = vim.F.if_nil(opts.wrap, true)
local line_count = vim.api.nvim_buf_line_count(bufnr)
- local diagnostics = get_diagnostics(bufnr, vim.tbl_extend("keep", opts, {namespace = namespace}), true)
+ local diagnostics = get_diagnostics(bufnr, vim.tbl_extend('keep', opts, { namespace = namespace }), true)
local line_diagnostics = diagnostic_lines(diagnostics)
for i = 0, line_count do
local offset = i * (search_forward and 1 or -1)
@@ -469,14 +485,22 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
lnum = (lnum + line_count) % line_count
end
if line_diagnostics[lnum] and not vim.tbl_isempty(line_diagnostics[lnum]) then
- local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
+ local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
local sort_diagnostics, is_next
if search_forward then
- sort_diagnostics = function(a, b) return a.col < b.col end
- is_next = function(d) return math.min(d.col, line_length - 1) > position[2] end
+ sort_diagnostics = function(a, b)
+ return a.col < b.col
+ end
+ is_next = function(d)
+ return math.min(d.col, line_length - 1) > position[2]
+ end
else
- sort_diagnostics = function(a, b) return a.col > b.col end
- is_next = function(d) return math.min(d.col, line_length - 1) < position[2] end
+ sort_diagnostics = function(a, b)
+ return a.col > b.col
+ end
+ is_next = function(d)
+ return math.min(d.col, line_length - 1) < position[2]
+ end
end
table.sort(line_diagnostics[lnum], sort_diagnostics)
if i == 0 then
@@ -500,28 +524,26 @@ local function diagnostic_move_pos(opts, pos)
local win_id = opts.win_id or vim.api.nvim_get_current_win()
if not pos then
- vim.api.nvim_echo({{"No more valid diagnostics to move to", "WarningMsg"}}, true, {})
+ vim.api.nvim_echo({ { 'No more valid diagnostics to move to', 'WarningMsg' } }, true, {})
return
end
vim.api.nvim_win_call(win_id, function()
-- Save position in the window's jumplist
vim.cmd("normal! m'")
- vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
+ vim.api.nvim_win_set_cursor(win_id, { pos[1] + 1, pos[2] })
-- Open folds under the cursor
- vim.cmd("normal! zv")
+ vim.cmd('normal! zv')
end)
if float then
- local float_opts = type(float) == "table" and float or {}
+ local float_opts = type(float) == 'table' and float or {}
vim.schedule(function()
- M.open_float(
- vim.tbl_extend("keep", float_opts, {
- bufnr = vim.api.nvim_win_get_buf(win_id),
- scope = "cursor",
- focus = false,
- })
- )
+ M.open_float(vim.tbl_extend('keep', float_opts, {
+ bufnr = vim.api.nvim_win_get_buf(win_id),
+ scope = 'cursor',
+ focus = false,
+ }))
end)
end
end
@@ -599,10 +621,10 @@ end
---@param namespace number|nil Update the options for the given namespace. When omitted, update the
--- global diagnostic options.
function M.config(opts, namespace)
- vim.validate {
+ vim.validate({
opts = { opts, 't', true },
namespace = { namespace, 'n', true },
- }
+ })
local t
if namespace then
@@ -645,16 +667,16 @@ end
---@param diagnostics table A list of diagnostic items |diagnostic-structure|
---@param opts table|nil Display options to pass to |vim.diagnostic.show()|
function M.set(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
+ vim.validate({
+ namespace = { namespace, 'n' },
+ bufnr = { bufnr, 'n' },
diagnostics = {
diagnostics,
vim.tbl_islist,
- "a list of diagnostics",
+ 'a list of diagnostics',
},
- opts = {opts, 't', true},
- }
+ opts = { opts, 't', true },
+ })
bufnr = get_bufnr(bufnr)
@@ -668,7 +690,7 @@ function M.set(namespace, bufnr, diagnostics, opts)
M.show(namespace, bufnr, nil, opts)
end
- vim.api.nvim_exec_autocmds("DiagnosticChanged", {
+ vim.api.nvim_exec_autocmds('DiagnosticChanged', {
modeline = false,
buffer = bufnr,
})
@@ -679,7 +701,7 @@ end
---@param namespace number Diagnostic namespace
---@return table Namespace metadata
function M.get_namespace(namespace)
- vim.validate { namespace = { namespace, 'n' } }
+ vim.validate({ namespace = { namespace, 'n' } })
if not all_namespaces[namespace] then
local name
for k, v in pairs(vim.api.nvim_get_namespaces()) do
@@ -689,7 +711,7 @@ function M.get_namespace(namespace)
end
end
- assert(name, "namespace does not exist or is anonymous")
+ assert(name, 'namespace does not exist or is anonymous')
all_namespaces[namespace] = {
name = name,
@@ -717,10 +739,10 @@ end
--- - severity: See |diagnostic-severity|.
---@return table A list of diagnostic items |diagnostic-structure|.
function M.get(bufnr, opts)
- vim.validate {
+ vim.validate({
bufnr = { bufnr, 'n', true },
opts = { opts, 't', true },
- }
+ })
return get_diagnostics(bufnr, opts, false)
end
@@ -749,16 +771,13 @@ function M.get_prev_pos(opts)
return false
end
- return {prev.lnum, prev.col}
+ return { prev.lnum, prev.col }
end
--- Move to the previous diagnostic in the current buffer.
---@param opts table See |vim.diagnostic.goto_next()|
function M.goto_prev(opts)
- return diagnostic_move_pos(
- opts,
- M.get_prev_pos(opts)
- )
+ return diagnostic_move_pos(opts, M.get_prev_pos(opts))
end
--- Get the next diagnostic closest to the cursor position.
@@ -785,7 +804,7 @@ function M.get_next_pos(opts)
return false
end
- return {next.lnum, next.col}
+ return { next.lnum, next.col }
end
--- Move to the next diagnostic.
@@ -803,24 +822,21 @@ end
--- the "scope" option).
--- - win_id: (number, default 0) Window ID
function M.goto_next(opts)
- return diagnostic_move_pos(
- opts,
- M.get_next_pos(opts)
- )
+ return diagnostic_move_pos(opts, M.get_next_pos(opts))
end
M.handlers.signs = {
show = function(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
+ vim.validate({
+ namespace = { namespace, 'n' },
+ bufnr = { bufnr, 'n' },
diagnostics = {
diagnostics,
vim.tbl_islist,
- "a list of diagnostics",
+ 'a list of diagnostics',
},
- opts = {opts, 't', true},
- }
+ opts = { opts, 't', true },
+ })
bufnr = get_bufnr(bufnr)
opts = opts or {}
@@ -835,7 +851,7 @@ M.handlers.signs = {
local priority = opts.signs and opts.signs.priority or 10
local get_priority
if opts.severity_sort then
- if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then
+ if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
get_priority = function(severity)
return priority + (severity - vim.diagnostic.severity.ERROR)
end
@@ -852,43 +868,37 @@ M.handlers.signs = {
local ns = M.get_namespace(namespace)
if not ns.user_data.sign_group then
- ns.user_data.sign_group = string.format("vim.diagnostic.%s", ns.name)
+ ns.user_data.sign_group = string.format('vim.diagnostic.%s', ns.name)
end
local sign_group = ns.user_data.sign_group
for _, diagnostic in ipairs(diagnostics) do
- vim.fn.sign_place(
- 0,
- sign_group,
- sign_highlight_map[diagnostic.severity],
- bufnr,
- {
- priority = get_priority(diagnostic.severity),
- lnum = diagnostic.lnum + 1
- }
- )
+ vim.fn.sign_place(0, sign_group, sign_highlight_map[diagnostic.severity], bufnr, {
+ priority = get_priority(diagnostic.severity),
+ lnum = diagnostic.lnum + 1,
+ })
end
end,
hide = function(namespace, bufnr)
local ns = M.get_namespace(namespace)
if ns.user_data.sign_group then
- vim.fn.sign_unplace(ns.user_data.sign_group, {buffer=bufnr})
+ vim.fn.sign_unplace(ns.user_data.sign_group, { buffer = bufnr })
end
end,
}
M.handlers.underline = {
show = function(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
+ vim.validate({
+ namespace = { namespace, 'n' },
+ bufnr = { bufnr, 'n' },
diagnostics = {
diagnostics,
vim.tbl_islist,
- "a list of diagnostics",
+ 'a list of diagnostics',
},
- opts = {opts, 't', true},
- }
+ opts = { opts, 't', true },
+ })
bufnr = get_bufnr(bufnr)
opts = opts or {}
@@ -899,7 +909,7 @@ M.handlers.underline = {
local ns = M.get_namespace(namespace)
if not ns.user_data.underline_ns then
- ns.user_data.underline_ns = vim.api.nvim_create_namespace("")
+ ns.user_data.underline_ns = vim.api.nvim_create_namespace('')
end
local underline_ns = ns.user_data.underline_ns
@@ -928,21 +938,21 @@ M.handlers.underline = {
diagnostic_cache_extmarks[bufnr][ns.user_data.underline_ns] = {}
vim.api.nvim_buf_clear_namespace(bufnr, ns.user_data.underline_ns, 0, -1)
end
- end
+ end,
}
M.handlers.virtual_text = {
show = function(namespace, bufnr, diagnostics, opts)
- vim.validate {
- namespace = {namespace, 'n'},
- bufnr = {bufnr, 'n'},
+ vim.validate({
+ namespace = { namespace, 'n' },
+ bufnr = { bufnr, 'n' },
diagnostics = {
diagnostics,
vim.tbl_islist,
- "a list of diagnostics",
+ 'a list of diagnostics',
},
- opts = {opts, 't', true},
- }
+ opts = { opts, 't', true },
+ })
bufnr = get_bufnr(bufnr)
opts = opts or {}
@@ -952,10 +962,7 @@ M.handlers.virtual_text = {
if opts.virtual_text.format then
diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
end
- if
- opts.virtual_text.source
- and (opts.virtual_text.source ~= "if_many" or count_sources(bufnr) > 1)
- then
+ if opts.virtual_text.source and (opts.virtual_text.source ~= 'if_many' or count_sources(bufnr) > 1) then
diagnostics = prefix_source(diagnostics)
end
if opts.virtual_text.severity then
@@ -965,7 +972,7 @@ M.handlers.virtual_text = {
local ns = M.get_namespace(namespace)
if not ns.user_data.virt_text_ns then
- ns.user_data.virt_text_ns = vim.api.nvim_create_namespace("")
+ ns.user_data.virt_text_ns = vim.api.nvim_create_namespace('')
end
local virt_text_ns = ns.user_data.virt_text_ns
@@ -978,7 +985,7 @@ M.handlers.virtual_text = {
if virt_texts then
vim.api.nvim_buf_set_extmark(bufnr, virt_text_ns, line, 0, {
- hl_mode = "combine",
+ hl_mode = 'combine',
virt_text = virt_texts,
})
end
@@ -1006,27 +1013,24 @@ function M._get_virt_text_chunks(line_diags, opts)
end
opts = opts or {}
- local prefix = opts.prefix or "â– "
+ local prefix = opts.prefix or 'â– '
local spacing = opts.spacing or 4
-- Create a little more space between virtual text and contents
- local virt_texts = {{string.rep(" ", spacing)}}
+ local virt_texts = { { string.rep(' ', spacing) } }
for i = 1, #line_diags - 1 do
- table.insert(virt_texts, {prefix, virtual_text_highlight_map[line_diags[i].severity]})
+ table.insert(virt_texts, { prefix, virtual_text_highlight_map[line_diags[i].severity] })
end
local last = line_diags[#line_diags]
-- TODO(tjdevries): Allow different servers to be shown first somehow?
-- TODO(tjdevries): Display server name associated with these?
if last.message then
- table.insert(
- virt_texts,
- {
- string.format("%s %s", prefix, last.message:gsub("\r", ""):gsub("\n", " ")),
- virtual_text_highlight_map[last.severity]
- }
- )
+ table.insert(virt_texts, {
+ string.format('%s %s', prefix, last.message:gsub('\r', ''):gsub('\n', ' ')),
+ virtual_text_highlight_map[last.severity],
+ })
return virt_texts
end
@@ -1066,14 +1070,14 @@ end
---@param bufnr number|nil Buffer number, or 0 for current buffer. When
--- omitted, hide diagnostics in all buffers.
function M.hide(namespace, bufnr)
- vim.validate {
+ vim.validate({
namespace = { namespace, 'n', true },
bufnr = { bufnr, 'n', true },
- }
+ })
- local buffers = bufnr and {get_bufnr(bufnr)} or vim.tbl_keys(diagnostic_cache)
+ local buffers = bufnr and { get_bufnr(bufnr) } or vim.tbl_keys(diagnostic_cache)
for _, iter_bufnr in ipairs(buffers) do
- local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr])
+ local namespaces = namespace and { namespace } or vim.tbl_keys(diagnostic_cache[iter_bufnr])
for _, iter_namespace in ipairs(namespaces) do
for _, handler in pairs(M.handlers) do
if handler.hide then
@@ -1098,19 +1102,21 @@ end
--- or {bufnr} is nil.
---@param opts table|nil Display options. See |vim.diagnostic.config()|.
function M.show(namespace, bufnr, diagnostics, opts)
- vim.validate {
+ vim.validate({
namespace = { namespace, 'n', true },
bufnr = { bufnr, 'n', true },
diagnostics = {
diagnostics,
- function(v) return v == nil or vim.tbl_islist(v) end,
- "a list of diagnostics",
+ function(v)
+ return v == nil or vim.tbl_islist(v)
+ end,
+ 'a list of diagnostics',
},
opts = { opts, 't', true },
- }
+ })
if not bufnr or not namespace then
- assert(not diagnostics, "Cannot show diagnostics without a buffer and namespace")
+ assert(not diagnostics, 'Cannot show diagnostics without a buffer and namespace')
if not bufnr then
for iter_bufnr in pairs(diagnostic_cache) do
M.show(namespace, iter_bufnr, nil, opts)
@@ -1131,7 +1137,7 @@ function M.show(namespace, bufnr, diagnostics, opts)
M.hide(namespace, bufnr)
- diagnostics = diagnostics or get_diagnostics(bufnr, {namespace=namespace}, true)
+ diagnostics = diagnostics or get_diagnostics(bufnr, { namespace = namespace }, true)
if not diagnostics or vim.tbl_isempty(diagnostics) then
return
@@ -1150,10 +1156,14 @@ function M.show(namespace, bufnr, diagnostics, opts)
end
if vim.F.if_nil(opts.severity_sort, false) then
- if type(opts.severity_sort) == "table" and opts.severity_sort.reverse then
- table.sort(diagnostics, function(a, b) return a.severity < b.severity end)
+ if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
+ table.sort(diagnostics, function(a, b)
+ return a.severity < b.severity
+ end)
else
- table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
+ table.sort(diagnostics, function(a, b)
+ return a.severity > b.severity
+ end)
end
end
@@ -1209,13 +1219,13 @@ end
function M.open_float(opts, ...)
-- Support old (bufnr, opts) signature
local bufnr
- if opts == nil or type(opts) == "number" then
+ if opts == nil or type(opts) == 'number' then
bufnr = opts
opts = ...
else
- vim.validate {
+ vim.validate({
opts = { opts, 't', true },
- }
+ })
end
opts = opts or {}
@@ -1228,41 +1238,39 @@ function M.open_float(opts, ...)
-- with its `opts` table which also includes "keyword" parameters. So we create a dedicated
-- options table that inherits missing keys from the global configuration before resolving.
local t = global_diagnostic_options.float
- local float_opts = vim.tbl_extend("keep", opts, type(t) == "table" and t or {})
+ local float_opts = vim.tbl_extend('keep', opts, type(t) == 'table' and t or {})
opts = get_resolved_options({ float = float_opts }, nil, bufnr).float
end
- local scope = ({l = "line", c = "cursor", b = "buffer"})[opts.scope] or opts.scope or "line"
+ local scope = ({ l = 'line', c = 'cursor', b = 'buffer' })[opts.scope] or opts.scope or 'line'
local lnum, col
- if scope == "line" or scope == "cursor" then
+ if scope == 'line' or scope == 'cursor' then
if not opts.pos then
local pos = vim.api.nvim_win_get_cursor(0)
lnum = pos[1] - 1
col = pos[2]
- elseif type(opts.pos) == "number" then
+ elseif type(opts.pos) == 'number' then
lnum = opts.pos
- elseif type(opts.pos) == "table" then
+ elseif type(opts.pos) == 'table' then
lnum, col = unpack(opts.pos)
else
error("Invalid value for option 'pos'")
end
- elseif scope ~= "buffer" then
+ elseif scope ~= 'buffer' then
error("Invalid value for option 'scope'")
end
local diagnostics = get_diagnostics(bufnr, opts, true)
- if scope == "line" then
+ if scope == 'line' then
diagnostics = vim.tbl_filter(function(d)
return d.lnum == lnum
end, diagnostics)
- elseif scope == "cursor" then
+ elseif scope == 'cursor' then
-- LSP servers can send diagnostics with `end_col` past the length of the line
local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
diagnostics = vim.tbl_filter(function(d)
- return d.lnum == lnum
- and math.min(d.col, line_length - 1) <= col
- and (d.end_col >= col or d.end_lnum > lnum)
+ return d.lnum == lnum and math.min(d.col, line_length - 1) <= col and (d.end_col >= col or d.end_lnum > lnum)
end, diagnostics)
end
@@ -1272,29 +1280,39 @@ function M.open_float(opts, ...)
local severity_sort = vim.F.if_nil(opts.severity_sort, global_diagnostic_options.severity_sort)
if severity_sort then
- if type(severity_sort) == "table" and severity_sort.reverse then
- table.sort(diagnostics, function(a, b) return a.severity > b.severity end)
+ if type(severity_sort) == 'table' and severity_sort.reverse then
+ table.sort(diagnostics, function(a, b)
+ return a.severity > b.severity
+ end)
else
- table.sort(diagnostics, function(a, b) return a.severity < b.severity end)
+ table.sort(diagnostics, function(a, b)
+ return a.severity < b.severity
+ end)
end
end
local lines = {}
local highlights = {}
- local header = if_nil(opts.header, "Diagnostics:")
+ local header = if_nil(opts.header, 'Diagnostics:')
if header then
- vim.validate { header = { header, function(v)
- return type(v) == "string" or type(v) == "table"
- end, "'string' or 'table'" } }
- if type(header) == "table" then
+ vim.validate({
+ header = {
+ header,
+ function(v)
+ return type(v) == 'string' or type(v) == 'table'
+ end,
+ "'string' or 'table'",
+ },
+ })
+ if type(header) == 'table' then
-- Don't insert any lines for an empty string
- if string.len(if_nil(header[1], "")) > 0 then
+ if string.len(if_nil(header[1], '')) > 0 then
table.insert(lines, header[1])
- table.insert(highlights, {0, header[2] or "Bold"})
+ table.insert(highlights, { 0, header[2] or 'Bold' })
end
elseif #header > 0 then
table.insert(lines, header)
- table.insert(highlights, {0, "Bold"})
+ table.insert(highlights, { 0, 'Bold' })
end
end
@@ -1302,38 +1320,44 @@ function M.open_float(opts, ...)
diagnostics = reformat_diagnostics(opts.format, diagnostics)
end
- if opts.source and (opts.source ~= "if_many" or count_sources(bufnr) > 1) then
+ if opts.source and (opts.source ~= 'if_many' or count_sources(bufnr) > 1) then
diagnostics = prefix_source(diagnostics)
end
- local prefix_opt = if_nil(opts.prefix, (scope == "cursor" and #diagnostics <= 1) and "" or function(_, i)
- return string.format("%d. ", i)
+ local prefix_opt = if_nil(opts.prefix, (scope == 'cursor' and #diagnostics <= 1) and '' or function(_, i)
+ return string.format('%d. ', i)
end)
local prefix, prefix_hl_group
if prefix_opt then
- vim.validate { prefix = { prefix_opt, function(v)
- return type(v) == "string" or type(v) == "table" or type(v) == "function"
- end, "'string' or 'table' or 'function'" } }
- if type(prefix_opt) == "string" then
- prefix, prefix_hl_group = prefix_opt, "NormalFloat"
- elseif type(prefix_opt) == "table" then
- prefix, prefix_hl_group = prefix_opt[1] or "", prefix_opt[2] or "NormalFloat"
+ vim.validate({
+ prefix = {
+ prefix_opt,
+ function(v)
+ return type(v) == 'string' or type(v) == 'table' or type(v) == 'function'
+ end,
+ "'string' or 'table' or 'function'",
+ },
+ })
+ if type(prefix_opt) == 'string' then
+ prefix, prefix_hl_group = prefix_opt, 'NormalFloat'
+ elseif type(prefix_opt) == 'table' then
+ prefix, prefix_hl_group = prefix_opt[1] or '', prefix_opt[2] or 'NormalFloat'
end
end
for i, diagnostic in ipairs(diagnostics) do
- if prefix_opt and type(prefix_opt) == "function" then
+ if prefix_opt and type(prefix_opt) == 'function' then
prefix, prefix_hl_group = prefix_opt(diagnostic, i, #diagnostics)
- prefix, prefix_hl_group = prefix or "", prefix_hl_group or "NormalFloat"
+ prefix, prefix_hl_group = prefix or '', prefix_hl_group or 'NormalFloat'
end
local hiname = floating_highlight_map[diagnostic.severity]
local message_lines = vim.split(diagnostic.message, '\n')
- table.insert(lines, prefix..message_lines[1])
- table.insert(highlights, {#prefix, hiname, prefix_hl_group})
+ table.insert(lines, prefix .. message_lines[1])
+ table.insert(highlights, { #prefix, hiname, prefix_hl_group })
for j = 2, #message_lines do
table.insert(lines, string.rep(' ', #prefix) .. message_lines[j])
- table.insert(highlights, {0, hiname})
+ table.insert(highlights, { 0, hiname })
end
end
@@ -1345,9 +1369,9 @@ function M.open_float(opts, ...)
for i, hi in ipairs(highlights) do
local prefixlen, hiname, prefix_hiname = unpack(hi)
if prefix_hiname then
- vim.api.nvim_buf_add_highlight(float_bufnr, -1, prefix_hiname, i-1, 0, prefixlen)
+ vim.api.nvim_buf_add_highlight(float_bufnr, -1, prefix_hiname, i - 1, 0, prefixlen)
end
- vim.api.nvim_buf_add_highlight(float_bufnr, -1, hiname, i-1, prefixlen, -1)
+ vim.api.nvim_buf_add_highlight(float_bufnr, -1, hiname, i - 1, prefixlen, -1)
end
return float_bufnr, winnr
@@ -1365,20 +1389,20 @@ end
---@param bufnr number|nil Remove diagnostics for the given buffer. When omitted,
--- diagnostics are removed for all buffers.
function M.reset(namespace, bufnr)
- vim.validate {
- namespace = {namespace, 'n', true},
- bufnr = {bufnr, 'n', true},
- }
+ vim.validate({
+ namespace = { namespace, 'n', true },
+ bufnr = { bufnr, 'n', true },
+ })
- local buffers = bufnr and {get_bufnr(bufnr)} or vim.tbl_keys(diagnostic_cache)
+ local buffers = bufnr and { get_bufnr(bufnr) } or vim.tbl_keys(diagnostic_cache)
for _, iter_bufnr in ipairs(buffers) do
- local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr])
+ local namespaces = namespace and { namespace } or vim.tbl_keys(diagnostic_cache[iter_bufnr])
for _, iter_namespace in ipairs(namespaces) do
diagnostic_cache[iter_bufnr][iter_namespace] = nil
M.hide(iter_namespace, iter_bufnr)
end
- vim.api.nvim_exec_autocmds("DiagnosticChanged", {
+ vim.api.nvim_exec_autocmds('DiagnosticChanged', {
modeline = false,
buffer = iter_bufnr,
})
@@ -1414,7 +1438,7 @@ end
--- omitted, disable diagnostics in all buffers.
---@param namespace number|nil Only disable diagnostics for the given namespace.
function M.disable(bufnr, namespace)
- vim.validate { bufnr = {bufnr, 'n', true}, namespace = {namespace, 'n', true} }
+ vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
if bufnr == nil then
if namespace == nil then
-- Disable everything (including as yet non-existing buffers and
@@ -1422,7 +1446,9 @@ function M.disable(bufnr, namespace)
-- its metatable to always return true. This metatable is removed
-- in enable()
diagnostic_disabled = setmetatable({}, {
- __index = function() return true end,
+ __index = function()
+ return true
+ end,
})
else
local ns = M.get_namespace(namespace)
@@ -1433,7 +1459,7 @@ function M.disable(bufnr, namespace)
if namespace == nil then
diagnostic_disabled[bufnr] = true
else
- if type(diagnostic_disabled[bufnr]) ~= "table" then
+ if type(diagnostic_disabled[bufnr]) ~= 'table' then
diagnostic_disabled[bufnr] = {}
end
diagnostic_disabled[bufnr][namespace] = true
@@ -1449,7 +1475,7 @@ end
--- omitted, enable diagnostics in all buffers.
---@param namespace number|nil Only enable diagnostics for the given namespace.
function M.enable(bufnr, namespace)
- vim.validate { bufnr = {bufnr, 'n', true}, namespace = {namespace, 'n', true} }
+ vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
if bufnr == nil then
if namespace == nil then
-- Enable everything by setting diagnostic_disabled to an empty table
@@ -1463,7 +1489,7 @@ function M.enable(bufnr, namespace)
if namespace == nil then
diagnostic_disabled[bufnr] = nil
else
- if type(diagnostic_disabled[bufnr]) ~= "table" then
+ if type(diagnostic_disabled[bufnr]) ~= 'table' then
return
end
diagnostic_disabled[bufnr][namespace] = nil
@@ -1500,33 +1526,33 @@ end
--- ERROR.
---@return diagnostic |diagnostic-structure| or `nil` if {pat} fails to match {str}.
function M.match(str, pat, groups, severity_map, defaults)
- vim.validate {
+ vim.validate({
str = { str, 's' },
pat = { pat, 's' },
groups = { groups, 't' },
severity_map = { severity_map, 't', true },
defaults = { defaults, 't', true },
- }
+ })
severity_map = severity_map or M.severity
local diagnostic = {}
- local matches = {string.match(str, pat)}
+ local matches = { string.match(str, pat) }
if vim.tbl_isempty(matches) then
return
end
for i, match in ipairs(matches) do
local field = groups[i]
- if field == "severity" then
+ if field == 'severity' then
match = severity_map[match]
- elseif field == "lnum" or field == "end_lnum" or field == "col" or field == "end_col" then
+ elseif field == 'lnum' or field == 'end_lnum' or field == 'col' or field == 'end_col' then
match = assert(tonumber(match)) - 1
end
diagnostic[field] = match
end
- diagnostic = vim.tbl_extend("keep", diagnostic, defaults or {})
+ diagnostic = vim.tbl_extend('keep', diagnostic, defaults or {})
diagnostic.severity = diagnostic.severity or M.severity.ERROR
diagnostic.col = diagnostic.col or 0
diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum
@@ -1547,13 +1573,13 @@ local errlist_type_map = {
---@param diagnostics table List of diagnostics |diagnostic-structure|.
---@return array of quickfix list items |setqflist-what|
function M.toqflist(diagnostics)
- vim.validate {
+ vim.validate({
diagnostics = {
diagnostics,
vim.tbl_islist,
- "a list of diagnostics",
+ 'a list of diagnostics',
},
- }
+ })
local list = {}
for _, v in ipairs(diagnostics) do
@@ -1584,13 +1610,13 @@ end
--- |getloclist()|.
---@return array of diagnostics |diagnostic-structure|
function M.fromqflist(list)
- vim.validate {
+ vim.validate({
list = {
list,
vim.tbl_islist,
- "a list of quickfix items",
+ 'a list of quickfix items',
},
- }
+ })
local diagnostics = {}
for _, item in ipairs(list) do
@@ -1599,7 +1625,7 @@ function M.fromqflist(list)
local col = math.max(0, item.col - 1)
local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum
local end_col = item.end_col > 0 and (item.end_col - 1) or col
- local severity = item.type ~= "" and M.severity[item.type] or M.severity.ERROR
+ local severity = item.type ~= '' and M.severity[item.type] or M.severity.ERROR
table.insert(diagnostics, {
bufnr = item.bufnr,
lnum = lnum,
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 32f4f825c1..fed0231ae9 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -4,866 +4,1007 @@ local M = {}
---@private
local function starsetf(ft)
- return {function(path)
- if not vim.g.fg_ignore_pat then
- return ft
- end
+ return {
+ function(path)
+ if not vim.g.fg_ignore_pat then
+ return ft
+ end
- local re = vim.regex(vim.g.fg_ignore_pat)
- if re:match_str(path) then
- return ft
- end
- end, {
- -- Starset matches should always have lowest priority
- priority = -math.huge,
- }}
+ local re = vim.regex(vim.g.fg_ignore_pat)
+ if re:match_str(path) then
+ return ft
+ end
+ end,
+ {
+ -- Starset matches should always have lowest priority
+ priority = -math.huge,
+ },
+ }
end
---@private
local function getline(bufnr, lnum)
- return api.nvim_buf_get_lines(bufnr, lnum-1, lnum, false)[1] or ""
+ return api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1] or ''
end
-- Filetypes based on file extension
-- luacheck: push no unused args
local extension = {
-- BEGIN EXTENSION
- ["8th"] = "8th",
- ["a65"] = "a65",
- aap = "aap",
- abap = "abap",
- abc = "abc",
- abl = "abel",
- wrm = "acedb",
- ads = "ada",
- ada = "ada",
- gpr = "ada",
- adb = "ada",
- tdf = "ahdl",
- aidl = "aidl",
- aml = "aml",
- run = "ampl",
- scpt = "applescript",
- ino = "arduino",
- pde = "arduino",
- art = "art",
- asciidoc = "asciidoc",
- adoc = "asciidoc",
- ["asn1"] = "asn",
- asn = "asn",
- atl = "atlas",
- as = "atlas",
- ahk = "autohotkey",
- ["au3"] = "autoit",
- ave = "ave",
- gawk = "awk",
- awk = "awk",
- ref = "b",
- imp = "b",
- mch = "b",
- bc = "bc",
- bdf = "bdf",
- beancount = "beancount",
- bib = "bib",
- bicep = "bicep",
- bl = "blank",
- bsdl = "bsdl",
- bst = "bst",
- bzl = "bzl",
- bazel = "bzl",
- BUILD = "bzl",
- qc = "c",
- cabal = "cabal",
- cdl = "cdl",
- toc = "cdrtoc",
- cfc = "cf",
- cfm = "cf",
- cfi = "cf",
- hgrc = "cfg",
- chf = "ch",
- chai = "chaiscript",
- chs = "chaskell",
- chopro = "chordpro",
- crd = "chordpro",
- crdpro = "chordpro",
- cho = "chordpro",
- chordpro = "chordpro",
- eni = "cl",
- dcl = "clean",
- icl = "clean",
- cljx = "clojure",
- clj = "clojure",
- cljc = "clojure",
- cljs = "clojure",
- cook = "cook",
- cmake = "cmake",
- cmod = "cmod",
- lib = "cobol",
- cob = "cobol",
- cbl = "cobol",
- atg = "coco",
- recipe = "conaryrecipe",
+ ['8th'] = '8th',
+ ['a65'] = 'a65',
+ aap = 'aap',
+ abap = 'abap',
+ abc = 'abc',
+ abl = 'abel',
+ wrm = 'acedb',
+ ads = 'ada',
+ ada = 'ada',
+ gpr = 'ada',
+ adb = 'ada',
+ tdf = 'ahdl',
+ aidl = 'aidl',
+ aml = 'aml',
+ run = 'ampl',
+ scpt = 'applescript',
+ ino = 'arduino',
+ pde = 'arduino',
+ art = 'art',
+ asciidoc = 'asciidoc',
+ adoc = 'asciidoc',
+ ['asn1'] = 'asn',
+ asn = 'asn',
+ atl = 'atlas',
+ as = 'atlas',
+ ahk = 'autohotkey',
+ ['au3'] = 'autoit',
+ ave = 'ave',
+ gawk = 'awk',
+ awk = 'awk',
+ ref = 'b',
+ imp = 'b',
+ mch = 'b',
+ bc = 'bc',
+ bdf = 'bdf',
+ beancount = 'beancount',
+ bib = 'bib',
+ bicep = 'bicep',
+ bl = 'blank',
+ bsdl = 'bsdl',
+ bst = 'bst',
+ bzl = 'bzl',
+ bazel = 'bzl',
+ BUILD = 'bzl',
+ qc = 'c',
+ cabal = 'cabal',
+ cdl = 'cdl',
+ toc = 'cdrtoc',
+ cfc = 'cf',
+ cfm = 'cf',
+ cfi = 'cf',
+ hgrc = 'cfg',
+ chf = 'ch',
+ chai = 'chaiscript',
+ chs = 'chaskell',
+ chopro = 'chordpro',
+ crd = 'chordpro',
+ crdpro = 'chordpro',
+ cho = 'chordpro',
+ chordpro = 'chordpro',
+ eni = 'cl',
+ dcl = 'clean',
+ icl = 'clean',
+ cljx = 'clojure',
+ clj = 'clojure',
+ cljc = 'clojure',
+ cljs = 'clojure',
+ cook = 'cook',
+ cmake = 'cmake',
+ cmod = 'cmod',
+ lib = 'cobol',
+ cob = 'cobol',
+ cbl = 'cobol',
+ atg = 'coco',
+ recipe = 'conaryrecipe',
hook = function(path, bufnr)
if getline(bufnr, 1) == '[Trigger]' then
- return "conf"
+ return 'conf'
end
end,
- mklx = "context",
- mkiv = "context",
- mkii = "context",
- mkxl = "context",
- mkvi = "context",
- moc = "cpp",
- hh = "cpp",
- tlh = "cpp",
- inl = "cpp",
- ipp = "cpp",
- ["c++"] = "cpp",
- C = "cpp",
- cxx = "cpp",
- H = "cpp",
- tcc = "cpp",
- hxx = "cpp",
- hpp = "cpp",
+ mklx = 'context',
+ mkiv = 'context',
+ mkii = 'context',
+ mkxl = 'context',
+ mkvi = 'context',
+ moc = 'cpp',
+ hh = 'cpp',
+ tlh = 'cpp',
+ inl = 'cpp',
+ ipp = 'cpp',
+ ['c++'] = 'cpp',
+ C = 'cpp',
+ cxx = 'cpp',
+ H = 'cpp',
+ tcc = 'cpp',
+ hxx = 'cpp',
+ hpp = 'cpp',
cpp = function(path, bufnr)
if vim.g.cynlib_syntax_for_cc then
- return "cynlib"
+ return 'cynlib'
end
- return "cpp"
+ return 'cpp'
end,
cc = function(path, bufnr)
if vim.g.cynlib_syntax_for_cc then
- return "cynlib"
+ return 'cynlib'
end
- return "cpp"
- end,
- crm = "crm",
- csx = "cs",
- cs = "cs",
- csc = "csc",
- csdl = "csdl",
- cshtml = "html",
- fdr = "csp",
- csp = "csp",
- css = "css",
- con = "cterm",
- feature = "cucumber",
- cuh = "cuda",
- cu = "cuda",
- pld = "cupl",
- si = "cuplsim",
- cyn = "cynpp",
- dart = "dart",
- drt = "dart",
- ds = "datascript",
- dcd = "dcd",
- def = "def",
- desc = "desc",
- directory = "desktop",
- desktop = "desktop",
- diff = "diff",
- rej = "diff",
- Dockerfile = "dockerfile",
- bat = "dosbatch",
- wrap = "dosini",
- ini = "dosini",
- dot = "dot",
- gv = "dot",
- drac = "dracula",
- drc = "dracula",
- dtd = "dtd",
- dts = "dts",
- dtsi = "dts",
- dylan = "dylan",
- intr = "dylanintr",
- lid = "dylanlid",
- ecd = "ecd",
- eex = "eelixir",
- leex = "eelixir",
- exs = "elixir",
- elm = "elm",
- elv = "elvish",
- epp = "epuppet",
- erl = "erlang",
- hrl = "erlang",
- yaws = "erlang",
- erb = "eruby",
- rhtml = "eruby",
- ec = "esqlc",
- EC = "esqlc",
- strl = "esterel",
- exp = "expect",
- factor = "factor",
- fal = "falcon",
- fan = "fan",
- fwt = "fan",
- fnl = "fennel",
- ["m4gl"] = "fgl",
- ["4gl"] = "fgl",
- ["4gh"] = "fgl",
- fish = "fish",
- focexec = "focexec",
- fex = "focexec",
- fth = "forth",
- ft = "forth",
- FOR = "fortran",
- ["f77"] = "fortran",
- ["f03"] = "fortran",
- fortran = "fortran",
- ["F95"] = "fortran",
- ["f90"] = "fortran",
- ["F03"] = "fortran",
- fpp = "fortran",
- FTN = "fortran",
- ftn = "fortran",
- ["for"] = "fortran",
- ["F90"] = "fortran",
- ["F77"] = "fortran",
- ["f95"] = "fortran",
- FPP = "fortran",
- f = "fortran",
- F = "fortran",
- ["F08"] = "fortran",
- ["f08"] = "fortran",
- fpc = "fpcmake",
- fsl = "framescript",
- fb = "freebasic",
- fsi = "fsharp",
- fsx = "fsharp",
- fusion = "fusion",
- gdb = "gdb",
- gdmo = "gdmo",
- mo = "gdmo",
- tres = "gdresource",
- tscn = "gdresource",
- gd = "gdscript",
- ged = "gedcom",
- gmi = "gemtext",
- gemini = "gemtext",
- gift = "gift",
- gleam = "gleam",
- glsl = "glsl",
- gpi = "gnuplot",
- gnuplot = "gnuplot",
- go = "go",
- gp = "gp",
- gs = "grads",
- gql = "graphql",
- graphql = "graphql",
- graphqls = "graphql",
- gretl = "gretl",
- gradle = "groovy",
- groovy = "groovy",
- gsp = "gsp",
- gjs = "javascript.glimmer",
- gts = "typescript.glimmer",
- hack = "hack",
- hackpartial = "hack",
- haml = "haml",
- hsm = "hamster",
- hbs = "handlebars",
- ["hs-boot"] = "haskell",
- hsig = "haskell",
- hsc = "haskell",
- hs = "haskell",
- ht = "haste",
- htpp = "hastepreproc",
- hb = "hb",
- sum = "hercules",
- errsum = "hercules",
- ev = "hercules",
- vc = "hercules",
- hcl = "hcl",
- heex = "heex",
- hex = "hex",
- ["h32"] = "hex",
- hjson = "hjson",
- hog = "hog",
- hws = "hollywood",
- htt = "httest",
- htb = "httest",
- iba = "ibasic",
- ibi = "ibasic",
- icn = "icon",
- inf = "inform",
- INF = "inform",
- ii = "initng",
- iss = "iss",
- mst = "ist",
- ist = "ist",
- ijs = "j",
- JAL = "jal",
- jal = "jal",
- jpr = "jam",
- jpl = "jam",
- jav = "java",
- java = "java",
- jj = "javacc",
- jjt = "javacc",
- es = "javascript",
- mjs = "javascript",
- javascript = "javascript",
- js = "javascript",
- cjs = "javascript",
- jsx = "javascriptreact",
- clp = "jess",
- jgr = "jgraph",
- ["j73"] = "jovial",
- jov = "jovial",
- jovial = "jovial",
- properties = "jproperties",
- slnf = "json",
- json = "json",
- jsonp = "json",
- webmanifest = "json",
- ipynb = "json",
- ["json-patch"] = "json",
- json5 = "json5",
- jsonc = "jsonc",
- jsp = "jsp",
- jl = "julia",
- kv = "kivy",
- kix = "kix",
- kts = "kotlin",
- kt = "kotlin",
- ktm = "kotlin",
- ks = "kscript",
- k = "kwt",
- ACE = "lace",
- ace = "lace",
- latte = "latte",
- lte = "latte",
- ld = "ld",
- ldif = "ldif",
- journal = "ledger",
- ldg = "ledger",
- ledger = "ledger",
- less = "less",
- lex = "lex",
- lxx = "lex",
- ["l++"] = "lex",
- l = "lex",
- lhs = "lhaskell",
- ll = "lifelines",
- ly = "lilypond",
- ily = "lilypond",
- liquid = "liquid",
- cl = "lisp",
- L = "lisp",
- lisp = "lisp",
- el = "lisp",
- lsp = "lisp",
- asd = "lisp",
- lt = "lite",
- lite = "lite",
- lgt = "logtalk",
- lotos = "lotos",
- lot = "lotos",
- lout = "lout",
- lou = "lout",
- ulpc = "lpc",
- lpc = "lpc",
- sig = "lprolog",
- lsl = "lsl",
- lss = "lss",
- nse = "lua",
- rockspec = "lua",
- lua = "lua",
- quake = "m3quake",
- at = "m4",
- eml = "mail",
- mk = "make",
- mak = "make",
- dsp = "make",
- page = "mallard",
- map = "map",
- mws = "maple",
- mpl = "maple",
- mv = "maple",
- mkdn = "markdown",
- md = "markdown",
- mdwn = "markdown",
- mkd = "markdown",
- markdown = "markdown",
- mdown = "markdown",
- mhtml = "mason",
- comp = "mason",
- mason = "mason",
- master = "master",
- mas = "master",
- demo = "maxima",
- dm1 = "maxima",
- dm2 = "maxima",
- dm3 = "maxima",
- dmt = "maxima",
- wxm = "maxima",
- mel = "mel",
- mf = "mf",
- mgl = "mgl",
- mgp = "mgp",
- my = "mib",
- mib = "mib",
- mix = "mix",
- mixal = "mix",
- nb = "mma",
- mmp = "mmp",
- DEF = "modula2",
- ["m2"] = "modula2",
- mi = "modula2",
- ssc = "monk",
- monk = "monk",
- tsc = "monk",
- isc = "monk",
- moo = "moo",
- mp = "mp",
- mof = "msidl",
- odl = "msidl",
- msql = "msql",
- mu = "mupad",
- mush = "mush",
- mysql = "mysql",
- ["n1ql"] = "n1ql",
- nql = "n1ql",
- nanorc = "nanorc",
- ncf = "ncf",
- nginx = "nginx",
- ninja = "ninja",
- nix = "nix",
- nqc = "nqc",
- roff = "nroff",
- tmac = "nroff",
- man = "nroff",
- mom = "nroff",
- nr = "nroff",
- tr = "nroff",
- nsi = "nsis",
- nsh = "nsis",
- obj = "obj",
- mlt = "ocaml",
- mly = "ocaml",
- mll = "ocaml",
- mlp = "ocaml",
- mlip = "ocaml",
- mli = "ocaml",
- ml = "ocaml",
- occ = "occam",
- xom = "omnimark",
- xin = "omnimark",
- opam = "opam",
- ["or"] = "openroad",
- scad = "openscad",
- ora = "ora",
- org = "org",
- org_archive = "org",
- pxsl = "papp",
- papp = "papp",
- pxml = "papp",
- pas = "pascal",
- lpr = "pascal",
- dpr = "pascal",
- pbtxt = "pbtxt",
- g = "pccts",
- pcmk = "pcmk",
- pdf = "pdf",
- plx = "perl",
- prisma = "prisma",
- psgi = "perl",
- al = "perl",
- ctp = "php",
- php = "php",
- phpt = "php",
- phtml = "php",
- pike = "pike",
- pmod = "pike",
- rcp = "pilrc",
- pli = "pli",
- ["pl1"] = "pli",
- ["p36"] = "plm",
- plm = "plm",
- pac = "plm",
- plp = "plp",
- pls = "plsql",
- plsql = "plsql",
- po = "po",
- pot = "po",
- pod = "pod",
- pk = "poke",
- ps = "postscr",
- epsi = "postscr",
- afm = "postscr",
- epsf = "postscr",
- eps = "postscr",
- pfa = "postscr",
- ai = "postscr",
- pov = "pov",
- ppd = "ppd",
- it = "ppwiz",
- ih = "ppwiz",
- action = "privoxy",
- pc = "proc",
- pdb = "prolog",
- pml = "promela",
- proto = "proto",
- ["psd1"] = "ps1",
- ["psm1"] = "ps1",
- ["ps1"] = "ps1",
- pssc = "ps1",
- ["ps1xml"] = "ps1xml",
- psf = "psf",
- psl = "psl",
- pug = "pug",
- arr = "pyret",
- pxd = "pyrex",
- pyx = "pyrex",
- pyw = "python",
- py = "python",
- pyi = "python",
- ptl = "python",
- ql = "ql",
- qll = "ql",
- rad = "radiance",
- mat = "radiance",
- ["pod6"] = "raku",
- rakudoc = "raku",
- rakutest = "raku",
- rakumod = "raku",
- ["pm6"] = "raku",
- raku = "raku",
- ["t6"] = "raku",
- ["p6"] = "raku",
- raml = "raml",
- rbs = "rbs",
- rego = "rego",
- rem = "remind",
- remind = "remind",
- res = "rescript",
- resi = "rescript",
- frt = "reva",
- testUnit = "rexx",
- rex = "rexx",
- orx = "rexx",
- rexx = "rexx",
- jrexx = "rexx",
- rxj = "rexx",
- rexxj = "rexx",
- testGroup = "rexx",
- rxo = "rexx",
- Rd = "rhelp",
- rd = "rhelp",
- rib = "rib",
- Rmd = "rmd",
- rmd = "rmd",
- smd = "rmd",
- Smd = "rmd",
- rnc = "rnc",
- rng = "rng",
- rnw = "rnoweb",
- snw = "rnoweb",
- Rnw = "rnoweb",
- Snw = "rnoweb",
- robot = "robot",
- resource = "robot",
- rsc = "routeros",
- x = "rpcgen",
- rpl = "rpl",
- Srst = "rrst",
- srst = "rrst",
- Rrst = "rrst",
- rrst = "rrst",
- rst = "rst",
- rtf = "rtf",
- rjs = "ruby",
- rxml = "ruby",
- rb = "ruby",
- rant = "ruby",
- ru = "ruby",
- rbw = "ruby",
- gemspec = "ruby",
- builder = "ruby",
- rake = "ruby",
- rs = "rust",
- sas = "sas",
- sass = "sass",
- sa = "sather",
- sbt = "sbt",
- scala = "scala",
- ss = "scheme",
- scm = "scheme",
- sld = "scheme",
- rkt = "scheme",
- rktd = "scheme",
- rktl = "scheme",
- sce = "scilab",
- sci = "scilab",
- scss = "scss",
- sd = "sd",
- sdc = "sdc",
- pr = "sdl",
- sdl = "sdl",
- sed = "sed",
- sexp = "sexplib",
- sieve = "sieve",
- siv = "sieve",
- sil = "sil",
- sim = "simula",
- ["s85"] = "sinda",
- sin = "sinda",
- ssm = "sisu",
- sst = "sisu",
- ssi = "sisu",
- ["_sst"] = "sisu",
- ["-sst"] = "sisu",
- il = "skill",
- ils = "skill",
- cdf = "skill",
- sl = "slang",
- ice = "slice",
- score = "slrnsc",
- sol = "solidity",
- tpl = "smarty",
- ihlp = "smcl",
- smcl = "smcl",
- hlp = "smcl",
- smith = "smith",
- smt = "smith",
- sml = "sml",
- spt = "snobol4",
- sno = "snobol4",
- sln = "solution",
- sparql = "sparql",
- rq = "sparql",
- spec = "spec",
- spice = "spice",
- sp = "spice",
- spd = "spup",
- spdata = "spup",
- speedup = "spup",
- spi = "spyce",
- spy = "spyce",
- tyc = "sql",
- typ = "sql",
- pkb = "sql",
- tyb = "sql",
- pks = "sql",
- sqlj = "sqlj",
- sqi = "sqr",
- sqr = "sqr",
- nut = "squirrel",
- ["s28"] = "srec",
- ["s37"] = "srec",
- srec = "srec",
- mot = "srec",
- ["s19"] = "srec",
- st = "st",
- imata = "stata",
- ["do"] = "stata",
- mata = "stata",
- ado = "stata",
- stp = "stp",
- quark = "supercollider",
- sface = "surface",
- svelte = "svelte",
- svg = "svg",
- swift = "swift",
- svh = "systemverilog",
- sv = "systemverilog",
- tak = "tak",
- task = "taskedit",
- tm = "tcl",
- tcl = "tcl",
- itk = "tcl",
- itcl = "tcl",
- tk = "tcl",
- jacl = "tcl",
- tl = "teal",
- tmpl = "template",
- ti = "terminfo",
- dtx = "tex",
- ltx = "tex",
- bbl = "tex",
- latex = "tex",
- sty = "tex",
- texi = "texinfo",
- txi = "texinfo",
- texinfo = "texinfo",
- text = "text",
- tfvars = "terraform",
- tla = "tla",
- tli = "tli",
- toml = "toml",
- tpp = "tpp",
- treetop = "treetop",
- slt = "tsalt",
- tsscl = "tsscl",
- tssgm = "tssgm",
- tssop = "tssop",
- tutor = "tutor",
- twig = "twig",
+ return 'cpp'
+ end,
+ crm = 'crm',
+ csx = 'cs',
+ cs = 'cs',
+ csc = 'csc',
+ csdl = 'csdl',
+ cshtml = 'html',
+ fdr = 'csp',
+ csp = 'csp',
+ css = 'css',
+ con = 'cterm',
+ feature = 'cucumber',
+ cuh = 'cuda',
+ cu = 'cuda',
+ pld = 'cupl',
+ si = 'cuplsim',
+ cyn = 'cynpp',
+ dart = 'dart',
+ drt = 'dart',
+ ds = 'datascript',
+ dcd = 'dcd',
+ def = 'def',
+ desc = 'desc',
+ directory = 'desktop',
+ desktop = 'desktop',
+ diff = 'diff',
+ rej = 'diff',
+ Dockerfile = 'dockerfile',
+ bat = 'dosbatch',
+ wrap = 'dosini',
+ ini = 'dosini',
+ dot = 'dot',
+ gv = 'dot',
+ drac = 'dracula',
+ drc = 'dracula',
+ dtd = 'dtd',
+ dts = 'dts',
+ dtsi = 'dts',
+ dylan = 'dylan',
+ intr = 'dylanintr',
+ lid = 'dylanlid',
+ ecd = 'ecd',
+ eex = 'eelixir',
+ leex = 'eelixir',
+ exs = 'elixir',
+ elm = 'elm',
+ elv = 'elvish',
+ epp = 'epuppet',
+ erl = 'erlang',
+ hrl = 'erlang',
+ yaws = 'erlang',
+ erb = 'eruby',
+ rhtml = 'eruby',
+ ec = 'esqlc',
+ EC = 'esqlc',
+ strl = 'esterel',
+ exp = 'expect',
+ factor = 'factor',
+ fal = 'falcon',
+ fan = 'fan',
+ fwt = 'fan',
+ fnl = 'fennel',
+ ['m4gl'] = 'fgl',
+ ['4gl'] = 'fgl',
+ ['4gh'] = 'fgl',
+ fish = 'fish',
+ focexec = 'focexec',
+ fex = 'focexec',
+ fth = 'forth',
+ ft = 'forth',
+ FOR = 'fortran',
+ ['f77'] = 'fortran',
+ ['f03'] = 'fortran',
+ fortran = 'fortran',
+ ['F95'] = 'fortran',
+ ['f90'] = 'fortran',
+ ['F03'] = 'fortran',
+ fpp = 'fortran',
+ FTN = 'fortran',
+ ftn = 'fortran',
+ ['for'] = 'fortran',
+ ['F90'] = 'fortran',
+ ['F77'] = 'fortran',
+ ['f95'] = 'fortran',
+ FPP = 'fortran',
+ f = 'fortran',
+ F = 'fortran',
+ ['F08'] = 'fortran',
+ ['f08'] = 'fortran',
+ fpc = 'fpcmake',
+ fsl = 'framescript',
+ fb = 'freebasic',
+ fsi = 'fsharp',
+ fsx = 'fsharp',
+ fusion = 'fusion',
+ gdb = 'gdb',
+ gdmo = 'gdmo',
+ mo = 'gdmo',
+ tres = 'gdresource',
+ tscn = 'gdresource',
+ gd = 'gdscript',
+ ged = 'gedcom',
+ gmi = 'gemtext',
+ gemini = 'gemtext',
+ gift = 'gift',
+ gleam = 'gleam',
+ glsl = 'glsl',
+ gpi = 'gnuplot',
+ gnuplot = 'gnuplot',
+ go = 'go',
+ gp = 'gp',
+ gs = 'grads',
+ gql = 'graphql',
+ graphql = 'graphql',
+ graphqls = 'graphql',
+ gretl = 'gretl',
+ gradle = 'groovy',
+ groovy = 'groovy',
+ gsp = 'gsp',
+ gjs = 'javascript.glimmer',
+ gts = 'typescript.glimmer',
+ hack = 'hack',
+ hackpartial = 'hack',
+ haml = 'haml',
+ hsm = 'hamster',
+ hbs = 'handlebars',
+ ['hs-boot'] = 'haskell',
+ hsig = 'haskell',
+ hsc = 'haskell',
+ hs = 'haskell',
+ ht = 'haste',
+ htpp = 'hastepreproc',
+ hb = 'hb',
+ sum = 'hercules',
+ errsum = 'hercules',
+ ev = 'hercules',
+ vc = 'hercules',
+ hcl = 'hcl',
+ heex = 'heex',
+ hex = 'hex',
+ ['h32'] = 'hex',
+ hjson = 'hjson',
+ hog = 'hog',
+ hws = 'hollywood',
+ htt = 'httest',
+ htb = 'httest',
+ iba = 'ibasic',
+ ibi = 'ibasic',
+ icn = 'icon',
+ inf = 'inform',
+ INF = 'inform',
+ ii = 'initng',
+ iss = 'iss',
+ mst = 'ist',
+ ist = 'ist',
+ ijs = 'j',
+ JAL = 'jal',
+ jal = 'jal',
+ jpr = 'jam',
+ jpl = 'jam',
+ jav = 'java',
+ java = 'java',
+ jj = 'javacc',
+ jjt = 'javacc',
+ es = 'javascript',
+ mjs = 'javascript',
+ javascript = 'javascript',
+ js = 'javascript',
+ cjs = 'javascript',
+ jsx = 'javascriptreact',
+ clp = 'jess',
+ jgr = 'jgraph',
+ ['j73'] = 'jovial',
+ jov = 'jovial',
+ jovial = 'jovial',
+ properties = 'jproperties',
+ slnf = 'json',
+ json = 'json',
+ jsonp = 'json',
+ webmanifest = 'json',
+ ipynb = 'json',
+ ['json-patch'] = 'json',
+ json5 = 'json5',
+ jsonc = 'jsonc',
+ jsp = 'jsp',
+ jl = 'julia',
+ kv = 'kivy',
+ kix = 'kix',
+ kts = 'kotlin',
+ kt = 'kotlin',
+ ktm = 'kotlin',
+ ks = 'kscript',
+ k = 'kwt',
+ ACE = 'lace',
+ ace = 'lace',
+ latte = 'latte',
+ lte = 'latte',
+ ld = 'ld',
+ ldif = 'ldif',
+ journal = 'ledger',
+ ldg = 'ledger',
+ ledger = 'ledger',
+ less = 'less',
+ lex = 'lex',
+ lxx = 'lex',
+ ['l++'] = 'lex',
+ l = 'lex',
+ lhs = 'lhaskell',
+ ll = 'lifelines',
+ ly = 'lilypond',
+ ily = 'lilypond',
+ liquid = 'liquid',
+ cl = 'lisp',
+ L = 'lisp',
+ lisp = 'lisp',
+ el = 'lisp',
+ lsp = 'lisp',
+ asd = 'lisp',
+ lt = 'lite',
+ lite = 'lite',
+ lgt = 'logtalk',
+ lotos = 'lotos',
+ lot = 'lotos',
+ lout = 'lout',
+ lou = 'lout',
+ ulpc = 'lpc',
+ lpc = 'lpc',
+ sig = 'lprolog',
+ lsl = 'lsl',
+ lss = 'lss',
+ nse = 'lua',
+ rockspec = 'lua',
+ lua = 'lua',
+ quake = 'm3quake',
+ at = 'm4',
+ eml = 'mail',
+ mk = 'make',
+ mak = 'make',
+ dsp = 'make',
+ page = 'mallard',
+ map = 'map',
+ mws = 'maple',
+ mpl = 'maple',
+ mv = 'maple',
+ mkdn = 'markdown',
+ md = 'markdown',
+ mdwn = 'markdown',
+ mkd = 'markdown',
+ markdown = 'markdown',
+ mdown = 'markdown',
+ mhtml = 'mason',
+ comp = 'mason',
+ mason = 'mason',
+ master = 'master',
+ mas = 'master',
+ demo = 'maxima',
+ dm1 = 'maxima',
+ dm2 = 'maxima',
+ dm3 = 'maxima',
+ dmt = 'maxima',
+ wxm = 'maxima',
+ mel = 'mel',
+ mf = 'mf',
+ mgl = 'mgl',
+ mgp = 'mgp',
+ my = 'mib',
+ mib = 'mib',
+ mix = 'mix',
+ mixal = 'mix',
+ nb = 'mma',
+ mmp = 'mmp',
+ DEF = 'modula2',
+ ['m2'] = 'modula2',
+ mi = 'modula2',
+ ssc = 'monk',
+ monk = 'monk',
+ tsc = 'monk',
+ isc = 'monk',
+ moo = 'moo',
+ mp = 'mp',
+ mof = 'msidl',
+ odl = 'msidl',
+ msql = 'msql',
+ mu = 'mupad',
+ mush = 'mush',
+ mysql = 'mysql',
+ ['n1ql'] = 'n1ql',
+ nql = 'n1ql',
+ nanorc = 'nanorc',
+ ncf = 'ncf',
+ nginx = 'nginx',
+ ninja = 'ninja',
+ nix = 'nix',
+ nqc = 'nqc',
+ roff = 'nroff',
+ tmac = 'nroff',
+ man = 'nroff',
+ mom = 'nroff',
+ nr = 'nroff',
+ tr = 'nroff',
+ nsi = 'nsis',
+ nsh = 'nsis',
+ obj = 'obj',
+ mlt = 'ocaml',
+ mly = 'ocaml',
+ mll = 'ocaml',
+ mlp = 'ocaml',
+ mlip = 'ocaml',
+ mli = 'ocaml',
+ ml = 'ocaml',
+ occ = 'occam',
+ xom = 'omnimark',
+ xin = 'omnimark',
+ opam = 'opam',
+ ['or'] = 'openroad',
+ scad = 'openscad',
+ ora = 'ora',
+ org = 'org',
+ org_archive = 'org',
+ pxsl = 'papp',
+ papp = 'papp',
+ pxml = 'papp',
+ pas = 'pascal',
+ lpr = 'pascal',
+ dpr = 'pascal',
+ pbtxt = 'pbtxt',
+ g = 'pccts',
+ pcmk = 'pcmk',
+ pdf = 'pdf',
+ plx = 'perl',
+ prisma = 'prisma',
+ psgi = 'perl',
+ al = 'perl',
+ ctp = 'php',
+ php = 'php',
+ phpt = 'php',
+ phtml = 'php',
+ pike = 'pike',
+ pmod = 'pike',
+ rcp = 'pilrc',
+ pli = 'pli',
+ ['pl1'] = 'pli',
+ ['p36'] = 'plm',
+ plm = 'plm',
+ pac = 'plm',
+ plp = 'plp',
+ pls = 'plsql',
+ plsql = 'plsql',
+ po = 'po',
+ pot = 'po',
+ pod = 'pod',
+ pk = 'poke',
+ ps = 'postscr',
+ epsi = 'postscr',
+ afm = 'postscr',
+ epsf = 'postscr',
+ eps = 'postscr',
+ pfa = 'postscr',
+ ai = 'postscr',
+ pov = 'pov',
+ ppd = 'ppd',
+ it = 'ppwiz',
+ ih = 'ppwiz',
+ action = 'privoxy',
+ pc = 'proc',
+ pdb = 'prolog',
+ pml = 'promela',
+ proto = 'proto',
+ ['psd1'] = 'ps1',
+ ['psm1'] = 'ps1',
+ ['ps1'] = 'ps1',
+ pssc = 'ps1',
+ ['ps1xml'] = 'ps1xml',
+ psf = 'psf',
+ psl = 'psl',
+ pug = 'pug',
+ arr = 'pyret',
+ pxd = 'pyrex',
+ pyx = 'pyrex',
+ pyw = 'python',
+ py = 'python',
+ pyi = 'python',
+ ptl = 'python',
+ ql = 'ql',
+ qll = 'ql',
+ rad = 'radiance',
+ mat = 'radiance',
+ ['pod6'] = 'raku',
+ rakudoc = 'raku',
+ rakutest = 'raku',
+ rakumod = 'raku',
+ ['pm6'] = 'raku',
+ raku = 'raku',
+ ['t6'] = 'raku',
+ ['p6'] = 'raku',
+ raml = 'raml',
+ rbs = 'rbs',
+ rego = 'rego',
+ rem = 'remind',
+ remind = 'remind',
+ res = 'rescript',
+ resi = 'rescript',
+ frt = 'reva',
+ testUnit = 'rexx',
+ rex = 'rexx',
+ orx = 'rexx',
+ rexx = 'rexx',
+ jrexx = 'rexx',
+ rxj = 'rexx',
+ rexxj = 'rexx',
+ testGroup = 'rexx',
+ rxo = 'rexx',
+ Rd = 'rhelp',
+ rd = 'rhelp',
+ rib = 'rib',
+ Rmd = 'rmd',
+ rmd = 'rmd',
+ smd = 'rmd',
+ Smd = 'rmd',
+ rnc = 'rnc',
+ rng = 'rng',
+ rnw = 'rnoweb',
+ snw = 'rnoweb',
+ Rnw = 'rnoweb',
+ Snw = 'rnoweb',
+ robot = 'robot',
+ resource = 'robot',
+ rsc = 'routeros',
+ x = 'rpcgen',
+ rpl = 'rpl',
+ Srst = 'rrst',
+ srst = 'rrst',
+ Rrst = 'rrst',
+ rrst = 'rrst',
+ rst = 'rst',
+ rtf = 'rtf',
+ rjs = 'ruby',
+ rxml = 'ruby',
+ rb = 'ruby',
+ rant = 'ruby',
+ ru = 'ruby',
+ rbw = 'ruby',
+ gemspec = 'ruby',
+ builder = 'ruby',
+ rake = 'ruby',
+ rs = 'rust',
+ sas = 'sas',
+ sass = 'sass',
+ sa = 'sather',
+ sbt = 'sbt',
+ scala = 'scala',
+ ss = 'scheme',
+ scm = 'scheme',
+ sld = 'scheme',
+ rkt = 'scheme',
+ rktd = 'scheme',
+ rktl = 'scheme',
+ sce = 'scilab',
+ sci = 'scilab',
+ scss = 'scss',
+ sd = 'sd',
+ sdc = 'sdc',
+ pr = 'sdl',
+ sdl = 'sdl',
+ sed = 'sed',
+ sexp = 'sexplib',
+ sieve = 'sieve',
+ siv = 'sieve',
+ sil = 'sil',
+ sim = 'simula',
+ ['s85'] = 'sinda',
+ sin = 'sinda',
+ ssm = 'sisu',
+ sst = 'sisu',
+ ssi = 'sisu',
+ ['_sst'] = 'sisu',
+ ['-sst'] = 'sisu',
+ il = 'skill',
+ ils = 'skill',
+ cdf = 'skill',
+ sl = 'slang',
+ ice = 'slice',
+ score = 'slrnsc',
+ sol = 'solidity',
+ tpl = 'smarty',
+ ihlp = 'smcl',
+ smcl = 'smcl',
+ hlp = 'smcl',
+ smith = 'smith',
+ smt = 'smith',
+ sml = 'sml',
+ spt = 'snobol4',
+ sno = 'snobol4',
+ sln = 'solution',
+ sparql = 'sparql',
+ rq = 'sparql',
+ spec = 'spec',
+ spice = 'spice',
+ sp = 'spice',
+ spd = 'spup',
+ spdata = 'spup',
+ speedup = 'spup',
+ spi = 'spyce',
+ spy = 'spyce',
+ tyc = 'sql',
+ typ = 'sql',
+ pkb = 'sql',
+ tyb = 'sql',
+ pks = 'sql',
+ sqlj = 'sqlj',
+ sqi = 'sqr',
+ sqr = 'sqr',
+ nut = 'squirrel',
+ ['s28'] = 'srec',
+ ['s37'] = 'srec',
+ srec = 'srec',
+ mot = 'srec',
+ ['s19'] = 'srec',
+ st = 'st',
+ imata = 'stata',
+ ['do'] = 'stata',
+ mata = 'stata',
+ ado = 'stata',
+ stp = 'stp',
+ quark = 'supercollider',
+ sface = 'surface',
+ svelte = 'svelte',
+ svg = 'svg',
+ swift = 'swift',
+ svh = 'systemverilog',
+ sv = 'systemverilog',
+ tak = 'tak',
+ task = 'taskedit',
+ tm = 'tcl',
+ tcl = 'tcl',
+ itk = 'tcl',
+ itcl = 'tcl',
+ tk = 'tcl',
+ jacl = 'tcl',
+ tl = 'teal',
+ tmpl = 'template',
+ ti = 'terminfo',
+ dtx = 'tex',
+ ltx = 'tex',
+ bbl = 'tex',
+ latex = 'tex',
+ sty = 'tex',
+ texi = 'texinfo',
+ txi = 'texinfo',
+ texinfo = 'texinfo',
+ text = 'text',
+ tfvars = 'terraform',
+ tla = 'tla',
+ tli = 'tli',
+ toml = 'toml',
+ tpp = 'tpp',
+ treetop = 'treetop',
+ slt = 'tsalt',
+ tsscl = 'tsscl',
+ tssgm = 'tssgm',
+ tssop = 'tssop',
+ tutor = 'tutor',
+ twig = 'twig',
ts = function(path, bufnr)
- if getline(bufnr, 1):find("<%?xml") then
- return "xml"
+ if getline(bufnr, 1):find('<%?xml') then
+ return 'xml'
else
- return "typescript"
+ return 'typescript'
end
end,
- tsx = "typescriptreact",
- uc = "uc",
- uit = "uil",
- uil = "uil",
- sba = "vb",
- vb = "vb",
- dsm = "vb",
- ctl = "vb",
- vbs = "vb",
- vr = "vera",
- vri = "vera",
- vrh = "vera",
- v = "verilog",
- va = "verilogams",
- vams = "verilogams",
- vhdl = "vhdl",
- vst = "vhdl",
- vhd = "vhdl",
- hdl = "vhdl",
- vho = "vhdl",
- vbe = "vhdl",
- vim = "vim",
- vba = "vim",
- mar = "vmasm",
- cm = "voscm",
- wrl = "vrml",
- vroom = "vroom",
- vue = "vue",
- wat = "wast",
- wast = "wast",
- wm = "webmacro",
- wbt = "winbatch",
- wml = "wml",
- wsml = "wsml",
- ad = "xdefaults",
- xhtml = "xhtml",
- xht = "xhtml",
- msc = "xmath",
- msf = "xmath",
- ["psc1"] = "xml",
- tpm = "xml",
- xliff = "xml",
- atom = "xml",
- xul = "xml",
- cdxml = "xml",
- mpd = "xml",
- rss = "xml",
- fsproj = "xml",
- ui = "xml",
- vbproj = "xml",
- xlf = "xml",
- wsdl = "xml",
- csproj = "xml",
- wpl = "xml",
- xmi = "xml",
- ["xpm2"] = "xpm2",
- xqy = "xquery",
- xqm = "xquery",
- xquery = "xquery",
- xq = "xquery",
- xql = "xquery",
- xs = "xs",
- xsd = "xsd",
- xsl = "xslt",
- xslt = "xslt",
- yy = "yacc",
- ["y++"] = "yacc",
- yxx = "yacc",
- yml = "yaml",
- yaml = "yaml",
- yang = "yang",
- ["z8a"] = "z8a",
- zig = "zig",
- zu = "zimbu",
- zut = "zimbutempl",
- zsh = "zsh",
- vala = "vala",
- E = function() vim.fn["dist#ft#FTe"]() end,
- EU = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- EW = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- EX = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- EXU = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- EXW = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- PL = function() vim.fn["dist#ft#FTpl"]() end,
- R = function(path, bufnr) require("vim.filetype.detect").r(bufnr) end,
- asm = function() vim.fn["dist#ft#FTasm"]() end,
- bas = function() vim.fn["dist#ft#FTbas"]() end,
- bi = function() vim.fn["dist#ft#FTbas"]() end,
- bm = function() vim.fn["dist#ft#FTbas"]() end,
- bash = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- btm = function(path, bufnr) return require("vim.filetype.detect").btm(bufnr) end,
- c = function() vim.fn["dist#ft#FTlpc"]() end,
- ch = function() vim.fn["dist#ft#FTchange"]() end,
- com = function() vim.fn["dist#ft#BindzoneCheck"]('dcl') end,
- cpt = function() vim.fn["dist#ft#FThtml"]() end,
- csh = function() vim.fn["dist#ft#CSH"]() end,
- d = function() vim.fn["dist#ft#DtraceCheck"]() end,
- db = function() vim.fn["dist#ft#BindzoneCheck"]('') end,
- dtml = function() vim.fn["dist#ft#FThtml"]() end,
- e = function() vim.fn["dist#ft#FTe"]() end,
- ebuild = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- eclass = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ent = function(path, bufnr) return require("vim.filetype.detect").ent(bufnr) end,
- env = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- eu = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- ew = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- ex = function(path, bufnr) return require("vim.filetype.detect").ex(bufnr) end,
- exu = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- exw = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
- frm = function(path, bufnr) require("vim.filetype.detect").frm(bufnr) end,
- fs = function() vim.fn["dist#ft#FTfs"]() end,
- h = function(path, bufnr) require("vim.filetype.detect").header(bufnr) end,
- htm = function() vim.fn["dist#ft#FThtml"]() end,
- html = function() vim.fn["dist#ft#FThtml"]() end,
- i = function() vim.fn["dist#ft#FTprogress_asm"]() end,
- idl = function(path, bufnr) require("vim.filetype.detect").idl(bufnr) end,
- inc = function() vim.fn["dist#ft#FTinc"]() end,
- inp = function(path, bufnr) require("vim.filetype.detect").inp(bufnr) end,
- ksh = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end,
- lst = function() vim.fn["dist#ft#FTasm"]() end,
- m = function() vim.fn["dist#ft#FTm"]() end,
- mac = function() vim.fn["dist#ft#FTasm"]() end,
- mc = function(path, bufnr) require("vim.filetype.detect").mc(bufnr) end,
- mm = function() vim.fn["dist#ft#FTmm"]() end,
- mms = function(path, bufnr) require("vim.filetype.detect").mms(bufnr) end,
- p = function() vim.fn["dist#ft#FTprogress_pascal"]() end,
+ tsx = 'typescriptreact',
+ uc = 'uc',
+ uit = 'uil',
+ uil = 'uil',
+ sba = 'vb',
+ vb = 'vb',
+ dsm = 'vb',
+ ctl = 'vb',
+ vbs = 'vb',
+ vr = 'vera',
+ vri = 'vera',
+ vrh = 'vera',
+ v = 'verilog',
+ va = 'verilogams',
+ vams = 'verilogams',
+ vhdl = 'vhdl',
+ vst = 'vhdl',
+ vhd = 'vhdl',
+ hdl = 'vhdl',
+ vho = 'vhdl',
+ vbe = 'vhdl',
+ vim = 'vim',
+ vba = 'vim',
+ mar = 'vmasm',
+ cm = 'voscm',
+ wrl = 'vrml',
+ vroom = 'vroom',
+ vue = 'vue',
+ wat = 'wast',
+ wast = 'wast',
+ wm = 'webmacro',
+ wbt = 'winbatch',
+ wml = 'wml',
+ wsml = 'wsml',
+ ad = 'xdefaults',
+ xhtml = 'xhtml',
+ xht = 'xhtml',
+ msc = 'xmath',
+ msf = 'xmath',
+ ['psc1'] = 'xml',
+ tpm = 'xml',
+ xliff = 'xml',
+ atom = 'xml',
+ xul = 'xml',
+ cdxml = 'xml',
+ mpd = 'xml',
+ rss = 'xml',
+ fsproj = 'xml',
+ ui = 'xml',
+ vbproj = 'xml',
+ xlf = 'xml',
+ wsdl = 'xml',
+ csproj = 'xml',
+ wpl = 'xml',
+ xmi = 'xml',
+ ['xpm2'] = 'xpm2',
+ xqy = 'xquery',
+ xqm = 'xquery',
+ xquery = 'xquery',
+ xq = 'xquery',
+ xql = 'xquery',
+ xs = 'xs',
+ xsd = 'xsd',
+ xsl = 'xslt',
+ xslt = 'xslt',
+ yy = 'yacc',
+ ['y++'] = 'yacc',
+ yxx = 'yacc',
+ yml = 'yaml',
+ yaml = 'yaml',
+ yang = 'yang',
+ ['z8a'] = 'z8a',
+ zig = 'zig',
+ zu = 'zimbu',
+ zut = 'zimbutempl',
+ zsh = 'zsh',
+ vala = 'vala',
+ E = function()
+ vim.fn['dist#ft#FTe']()
+ end,
+ EU = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ EW = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ EX = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ EXU = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ EXW = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ PL = function()
+ vim.fn['dist#ft#FTpl']()
+ end,
+ R = function(path, bufnr)
+ require('vim.filetype.detect').r(bufnr)
+ end,
+ asm = function()
+ vim.fn['dist#ft#FTasm']()
+ end,
+ bas = function()
+ vim.fn['dist#ft#FTbas']()
+ end,
+ bi = function()
+ vim.fn['dist#ft#FTbas']()
+ end,
+ bm = function()
+ vim.fn['dist#ft#FTbas']()
+ end,
+ bash = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ btm = function(path, bufnr)
+ return require('vim.filetype.detect').btm(bufnr)
+ end,
+ c = function()
+ vim.fn['dist#ft#FTlpc']()
+ end,
+ ch = function()
+ vim.fn['dist#ft#FTchange']()
+ end,
+ com = function()
+ vim.fn['dist#ft#BindzoneCheck']('dcl')
+ end,
+ cpt = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ csh = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ d = function()
+ vim.fn['dist#ft#DtraceCheck']()
+ end,
+ db = function()
+ vim.fn['dist#ft#BindzoneCheck']('')
+ end,
+ dtml = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ e = function()
+ vim.fn['dist#ft#FTe']()
+ end,
+ ebuild = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ eclass = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ent = function(path, bufnr)
+ return require('vim.filetype.detect').ent(bufnr)
+ end,
+ env = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ eu = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ ew = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ ex = function(path, bufnr)
+ return require('vim.filetype.detect').ex(bufnr)
+ end,
+ exu = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ exw = function(path, bufnr)
+ return require('vim.filetype.detect').euphoria(bufnr)
+ end,
+ frm = function(path, bufnr)
+ require('vim.filetype.detect').frm(bufnr)
+ end,
+ fs = function()
+ vim.fn['dist#ft#FTfs']()
+ end,
+ h = function(path, bufnr)
+ require('vim.filetype.detect').header(bufnr)
+ end,
+ htm = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ html = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ i = function()
+ vim.fn['dist#ft#FTprogress_asm']()
+ end,
+ idl = function(path, bufnr)
+ require('vim.filetype.detect').idl(bufnr)
+ end,
+ inc = function()
+ vim.fn['dist#ft#FTinc']()
+ end,
+ inp = function(path, bufnr)
+ require('vim.filetype.detect').inp(bufnr)
+ end,
+ ksh = function()
+ vim.fn['dist#ft#SetFileTypeSH']('ksh')
+ end,
+ lst = function()
+ vim.fn['dist#ft#FTasm']()
+ end,
+ m = function()
+ vim.fn['dist#ft#FTm']()
+ end,
+ mac = function()
+ vim.fn['dist#ft#FTasm']()
+ end,
+ mc = function(path, bufnr)
+ require('vim.filetype.detect').mc(bufnr)
+ end,
+ mm = function()
+ vim.fn['dist#ft#FTmm']()
+ end,
+ mms = function(path, bufnr)
+ require('vim.filetype.detect').mms(bufnr)
+ end,
+ p = function()
+ vim.fn['dist#ft#FTprogress_pascal']()
+ end,
patch = function(path, bufnr)
local firstline = getline(bufnr, 1)
- if string.find(firstline, "^From " .. string.rep("%x", 40) .. "+ Mon Sep 17 00:00:00 2001$") then
- return "gitsendemail"
+ if string.find(firstline, '^From ' .. string.rep('%x', 40) .. '+ Mon Sep 17 00:00:00 2001$') then
+ return 'gitsendemail'
else
- return "diff"
+ return 'diff'
end
end,
- pl = function() vim.fn["dist#ft#FTpl"]() end,
- pp = function() vim.fn["dist#ft#FTpp"]() end,
- pro = function() vim.fn["dist#ft#ProtoCheck"]('idlang') end,
- pt = function() vim.fn["dist#ft#FThtml"]() end,
- r = function(path, bufnr) require("vim.filetype.detect").r(bufnr) end,
- rdf = function(path, bufnr) require("vim.filetype.detect").redif(bufnr) end,
- rules = function() vim.fn["dist#ft#FTRules"]() end,
- sc = function(path, bufnr) require("vim.filetype.detect").sc(bufnr) end,
- scd = function(path, bufnr) require("vim.filetype.detect").scd(bufnr) end,
- sh = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- shtml = function() vim.fn["dist#ft#FThtml"]() end,
- sql = function(path, bufnr) require("vim.filetype.detect").sql(bufnr) end,
- stm = function() vim.fn["dist#ft#FThtml"]() end,
- tcsh = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
- tex = function() vim.fn["dist#ft#FTtex"]() end,
- tf = function(path, bufnr) require("vim.filetype.detect").tf(bufnr) end,
- w = function(path, bufnr) require("vim.filetype.detect").progress_cweb(bufnr) end,
- xml = function(path, bufnr) require("vim.filetype.detect").xml(bufnr) end,
- y = function(path, bufnr) require("vim.filetype.detect").y(bufnr) end,
- zsql = function(path, bufnr) require("vim.filetype.detect").sql(bufnr) end,
+ pl = function()
+ vim.fn['dist#ft#FTpl']()
+ end,
+ pp = function()
+ vim.fn['dist#ft#FTpp']()
+ end,
+ pro = function()
+ vim.fn['dist#ft#ProtoCheck']('idlang')
+ end,
+ pt = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ r = function(path, bufnr)
+ require('vim.filetype.detect').r(bufnr)
+ end,
+ rdf = function(path, bufnr)
+ require('vim.filetype.detect').redif(bufnr)
+ end,
+ rules = function()
+ vim.fn['dist#ft#FTRules']()
+ end,
+ sc = function(path, bufnr)
+ require('vim.filetype.detect').sc(bufnr)
+ end,
+ scd = function(path, bufnr)
+ require('vim.filetype.detect').scd(bufnr)
+ end,
+ sh = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ shtml = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ sql = function(path, bufnr)
+ require('vim.filetype.detect').sql(bufnr)
+ end,
+ stm = function()
+ vim.fn['dist#ft#FThtml']()
+ end,
+ tcsh = function()
+ vim.fn['dist#ft#SetFileTypeShell']('tcsh')
+ end,
+ tex = function()
+ vim.fn['dist#ft#FTtex']()
+ end,
+ tf = function(path, bufnr)
+ require('vim.filetype.detect').tf(bufnr)
+ end,
+ w = function(path, bufnr)
+ require('vim.filetype.detect').progress_cweb(bufnr)
+ end,
+ xml = function(path, bufnr)
+ require('vim.filetype.detect').xml(bufnr)
+ end,
+ y = function(path, bufnr)
+ require('vim.filetype.detect').y(bufnr)
+ end,
+ zsql = function(path, bufnr)
+ require('vim.filetype.detect').sql(bufnr)
+ end,
txt = function(path, bufnr)
--helpfiles match *.txt, but should have a modeline as last line
- if not getline(bufnr, -1):match("vim:.*ft=help") then
- return "text"
+ if not getline(bufnr, -1):match('vim:.*ft=help') then
+ return 'text'
end
end,
-- END EXTENSION
@@ -871,593 +1012,695 @@ local extension = {
local filename = {
-- BEGIN FILENAME
- ["a2psrc"] = "a2ps",
- ["/etc/a2ps.cfg"] = "a2ps",
- [".a2psrc"] = "a2ps",
- [".asoundrc"] = "alsaconf",
- ["/usr/share/alsa/alsa.conf"] = "alsaconf",
- ["/etc/asound.conf"] = "alsaconf",
- ["build.xml"] = "ant",
- [".htaccess"] = "apache",
- ["apt.conf"] = "aptconf",
- ["/.aptitude/config"] = "aptconf",
- ["=tagging-method"] = "arch",
- [".arch-inventory"] = "arch",
- ["GNUmakefile.am"] = "automake",
- ["named.root"] = "bindzone",
- WORKSPACE = "bzl",
- BUILD = "bzl",
- ["cabal.config"] = "cabalconfig",
- ["cabal.project"] = "cabalproject",
- calendar = "calendar",
- catalog = "catalog",
- ["/etc/cdrdao.conf"] = "cdrdaoconf",
- [".cdrdao"] = "cdrdaoconf",
- ["/etc/default/cdrdao"] = "cdrdaoconf",
- ["/etc/defaults/cdrdao"] = "cdrdaoconf",
- ["cfengine.conf"] = "cfengine",
- ["CMakeLists.txt"] = "cmake",
- ["auto.master"] = "conf",
- ["configure.in"] = "config",
- ["configure.ac"] = "config",
- [".cvsrc"] = "cvsrc",
- ["/debian/changelog"] = "debchangelog",
- ["changelog.dch"] = "debchangelog",
- ["changelog.Debian"] = "debchangelog",
- ["NEWS.dch"] = "debchangelog",
- ["NEWS.Debian"] = "debchangelog",
- ["/debian/control"] = "debcontrol",
- ["/debian/copyright"] = "debcopyright",
- ["/etc/apt/sources.list"] = "debsources",
- ["denyhosts.conf"] = "denyhosts",
- ["dict.conf"] = "dictconf",
- [".dictrc"] = "dictconf",
- ["/etc/DIR_COLORS"] = "dircolors",
- [".dir_colors"] = "dircolors",
- [".dircolors"] = "dircolors",
- ["/etc/dnsmasq.conf"] = "dnsmasq",
- Containerfile = "dockerfile",
- Dockerfile = "dockerfile",
- npmrc = "dosini",
- ["/etc/yum.conf"] = "dosini",
- ["/etc/pacman.conf"] = "conf",
- [".npmrc"] = "dosini",
- [".editorconfig"] = "dosini",
- dune = "dune",
- jbuild = "dune",
- ["dune-workspace"] = "dune",
- ["dune-project"] = "dune",
- ["elinks.conf"] = "elinks",
- ["mix.lock"] = "elixir",
- ["filter-rules"] = "elmfilt",
- ["exim.conf"] = "exim",
- exports = "exports",
- [".fetchmailrc"] = "fetchmail",
- fvSchemes = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- fvSolution = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- fvConstraints = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- fvModels = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- fstab = "fstab",
- mtab = "fstab",
- [".gdbinit"] = "gdb",
- gdbinit = "gdb",
- [".gdbearlyinit"] = "gdb",
- gdbearlyinit = "gdb",
- ["lltxxxxx.txt"] = "gedcom",
- ["TAG_EDITMSG"] = "gitcommit",
- ["MERGE_MSG"] = "gitcommit",
- ["COMMIT_EDITMSG"] = "gitcommit",
- ["NOTES_EDITMSG"] = "gitcommit",
- ["EDIT_DESCRIPTION"] = "gitcommit",
- [".gitconfig"] = "gitconfig",
- [".gitmodules"] = "gitconfig",
- ["gitolite.conf"] = "gitolite",
- ["git-rebase-todo"] = "gitrebase",
- gkrellmrc = "gkrellmrc",
- [".gnashrc"] = "gnash",
- [".gnashpluginrc"] = "gnash",
- gnashpluginrc = "gnash",
- gnashrc = "gnash",
- ["go.work"] = "gowork",
- [".gprc"] = "gp",
- ["/.gnupg/gpg.conf"] = "gpg",
- ["/.gnupg/options"] = "gpg",
- ["/var/backups/gshadow.bak"] = "group",
- ["/etc/gshadow"] = "group",
- ["/etc/group-"] = "group",
- ["/etc/gshadow.edit"] = "group",
- ["/etc/gshadow-"] = "group",
- ["/etc/group"] = "group",
- ["/var/backups/group.bak"] = "group",
- ["/etc/group.edit"] = "group",
- ["/boot/grub/menu.lst"] = "grub",
- ["/etc/grub.conf"] = "grub",
- ["/boot/grub/grub.conf"] = "grub",
- [".gtkrc"] = "gtkrc",
- gtkrc = "gtkrc",
- ["snort.conf"] = "hog",
- ["vision.conf"] = "hog",
- ["/etc/host.conf"] = "hostconf",
- ["/etc/hosts.allow"] = "hostsaccess",
- ["/etc/hosts.deny"] = "hostsaccess",
- ["/i3/config"] = "i3config",
- ["/sway/config"] = "i3config",
- ["/.sway/config"] = "i3config",
- ["/.i3/config"] = "i3config",
- ["/.icewm/menu"] = "icemenu",
- [".indent.pro"] = "indent",
- indentrc = "indent",
- inittab = "inittab",
- ["ipf.conf"] = "ipfilter",
- ["ipf6.conf"] = "ipfilter",
- ["ipf.rules"] = "ipfilter",
- [".eslintrc"] = "json",
- [".babelrc"] = "json",
- ["Pipfile.lock"] = "json",
- [".firebaserc"] = "json",
- [".prettierrc"] = "json",
- Kconfig = "kconfig",
- ["Kconfig.debug"] = "kconfig",
- ["lftp.conf"] = "lftp",
- [".lftprc"] = "lftp",
- ["/.libao"] = "libao",
- ["/etc/libao.conf"] = "libao",
- ["lilo.conf"] = "lilo",
- ["/etc/limits"] = "limits",
- [".emacs"] = "lisp",
- sbclrc = "lisp",
- [".sbclrc"] = "lisp",
- [".sawfishrc"] = "lisp",
- ["/etc/login.access"] = "loginaccess",
- ["/etc/login.defs"] = "logindefs",
- ["lynx.cfg"] = "lynx",
- ["m3overrides"] = "m3build",
- ["m3makefile"] = "m3build",
- ["cm3.cfg"] = "m3quake",
- [".followup"] = "mail",
- [".article"] = "mail",
- [".letter"] = "mail",
- ["/etc/aliases"] = "mailaliases",
- ["/etc/mail/aliases"] = "mailaliases",
- mailcap = "mailcap",
- [".mailcap"] = "mailcap",
- ["/etc/man.conf"] = "manconf",
- ["man.config"] = "manconf",
- ["maxima-init.mac"] = "maxima",
- ["meson.build"] = "meson",
- ["meson_options.txt"] = "meson",
- ["/etc/conf.modules"] = "modconf",
- ["/etc/modules"] = "modconf",
- ["/etc/modules.conf"] = "modconf",
- ["/.mplayer/config"] = "mplayerconf",
- ["mplayer.conf"] = "mplayerconf",
- mrxvtrc = "mrxvtrc",
- [".mrxvtrc"] = "mrxvtrc",
- ["/etc/nanorc"] = "nanorc",
- Neomuttrc = "neomuttrc",
- [".netrc"] = "netrc",
- [".ocamlinit"] = "ocaml",
- [".octaverc"] = "octave",
- octaverc = "octave",
- ["octave.conf"] = "octave",
- opam = "opam",
- ["/etc/pam.conf"] = "pamconf",
- ["pam_env.conf"] = "pamenv",
- [".pam_environment"] = "pamenv",
- ["/var/backups/passwd.bak"] = "passwd",
- ["/var/backups/shadow.bak"] = "passwd",
- ["/etc/passwd"] = "passwd",
- ["/etc/passwd-"] = "passwd",
- ["/etc/shadow.edit"] = "passwd",
- ["/etc/shadow-"] = "passwd",
- ["/etc/shadow"] = "passwd",
- ["/etc/passwd.edit"] = "passwd",
- ["pf.conf"] = "pf",
- ["main.cf"] = "pfmain",
- pinerc = "pine",
- [".pinercex"] = "pine",
- [".pinerc"] = "pine",
- pinercex = "pine",
- ["/etc/pinforc"] = "pinfo",
- ["/.pinforc"] = "pinfo",
- [".povrayrc"] = "povini",
- [".procmailrc"] = "procmail",
- [".procmail"] = "procmail",
- ["/etc/protocols"] = "protocols",
- [".pythonstartup"] = "python",
- [".pythonrc"] = "python",
- SConstruct = "python",
- ratpoisonrc = "ratpoison",
- [".ratpoisonrc"] = "ratpoison",
- v = "rcs",
- inputrc = "readline",
- [".inputrc"] = "readline",
- [".reminders"] = "remind",
- ["resolv.conf"] = "resolv",
- ["robots.txt"] = "robots",
- Gemfile = "ruby",
- Puppetfile = "ruby",
- [".irbrc"] = "ruby",
- irbrc = "ruby",
- Vagrantfile = "ruby",
- ["smb.conf"] = "samba",
- screenrc = "screen",
- [".screenrc"] = "screen",
- ["/etc/sensors3.conf"] = "sensors",
- ["/etc/sensors.conf"] = "sensors",
- ["/etc/services"] = "services",
- ["/etc/serial.conf"] = "setserial",
- ["/etc/udev/cdsymlinks.conf"] = "sh",
- ["/etc/slp.conf"] = "slpconf",
- ["/etc/slp.reg"] = "slpreg",
- ["/etc/slp.spi"] = "slpspi",
- [".slrnrc"] = "slrnrc",
- ["sendmail.cf"] = "sm",
- ["squid.conf"] = "squid",
- ["/.ssh/config"] = "sshconfig",
- ["ssh_config"] = "sshconfig",
- ["sshd_config"] = "sshdconfig",
- ["/etc/sudoers"] = "sudoers",
- ["sudoers.tmp"] = "sudoers",
- ["/etc/sysctl.conf"] = "sysctl",
- tags = "tags",
- [".tclshrc"] = "tcl",
- [".wishrc"] = "tcl",
- ["tclsh.rc"] = "tcl",
- ["texmf.cnf"] = "texmf",
- COPYING = "text",
- README = "text",
- LICENSE = "text",
- AUTHORS = "text",
- tfrc = "tf",
- [".tfrc"] = "tf",
- ["tidy.conf"] = "tidy",
- tidyrc = "tidy",
- [".tidyrc"] = "tidy",
- [".tmux.conf"] = "tmux",
- ["/.cargo/config"] = "toml",
- Pipfile = "toml",
- ["Gopkg.lock"] = "toml",
- ["/.cargo/credentials"] = "toml",
- ["Cargo.lock"] = "toml",
- ["trustees.conf"] = "trustees",
- ["/etc/udev/udev.conf"] = "udevconf",
- ["/etc/updatedb.conf"] = "updatedb",
- ["fdrupstream.log"] = "upstreamlog",
- vgrindefs = "vgrindefs",
- [".exrc"] = "vim",
- ["_exrc"] = "vim",
- ["_viminfo"] = "viminfo",
- [".viminfo"] = "viminfo",
- [".wgetrc"] = "wget",
- [".wget2rc"] = "wget2",
- wgetrc = "wget",
- wget2rc = "wget2",
- [".wvdialrc"] = "wvdial",
- ["wvdial.conf"] = "wvdial",
- [".Xresources"] = "xdefaults",
- [".Xpdefaults"] = "xdefaults",
- ["xdm-config"] = "xdefaults",
- [".Xdefaults"] = "xdefaults",
- ["/etc/xinetd.conf"] = "xinetd",
- fglrxrc = "xml",
- ["/etc/blkid.tab"] = "xml",
- ["/etc/blkid.tab.old"] = "xml",
- ["/etc/zprofile"] = "zsh",
- [".zlogin"] = "zsh",
- [".zlogout"] = "zsh",
- [".zshrc"] = "zsh",
- [".zprofile"] = "zsh",
- [".zcompdump"] = "zsh",
- [".zshenv"] = "zsh",
- [".zfbfmarks"] = "zsh",
- [".alias"] = function() vim.fn["dist#ft#CSH"]() end,
- [".bashrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- [".cshrc"] = function() vim.fn["dist#ft#CSH"]() end,
- [".env"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- [".kshrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end,
- [".login"] = function() vim.fn["dist#ft#CSH"]() end,
- [".profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- [".tcshrc"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
- ["/etc/profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- APKBUILD = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- PKGBUILD = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ["bash.bashrc"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- bashrc = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
+ ['a2psrc'] = 'a2ps',
+ ['/etc/a2ps.cfg'] = 'a2ps',
+ ['.a2psrc'] = 'a2ps',
+ ['.asoundrc'] = 'alsaconf',
+ ['/usr/share/alsa/alsa.conf'] = 'alsaconf',
+ ['/etc/asound.conf'] = 'alsaconf',
+ ['build.xml'] = 'ant',
+ ['.htaccess'] = 'apache',
+ ['apt.conf'] = 'aptconf',
+ ['/.aptitude/config'] = 'aptconf',
+ ['=tagging-method'] = 'arch',
+ ['.arch-inventory'] = 'arch',
+ ['GNUmakefile.am'] = 'automake',
+ ['named.root'] = 'bindzone',
+ WORKSPACE = 'bzl',
+ BUILD = 'bzl',
+ ['cabal.config'] = 'cabalconfig',
+ ['cabal.project'] = 'cabalproject',
+ calendar = 'calendar',
+ catalog = 'catalog',
+ ['/etc/cdrdao.conf'] = 'cdrdaoconf',
+ ['.cdrdao'] = 'cdrdaoconf',
+ ['/etc/default/cdrdao'] = 'cdrdaoconf',
+ ['/etc/defaults/cdrdao'] = 'cdrdaoconf',
+ ['cfengine.conf'] = 'cfengine',
+ ['CMakeLists.txt'] = 'cmake',
+ ['auto.master'] = 'conf',
+ ['configure.in'] = 'config',
+ ['configure.ac'] = 'config',
+ ['.cvsrc'] = 'cvsrc',
+ ['/debian/changelog'] = 'debchangelog',
+ ['changelog.dch'] = 'debchangelog',
+ ['changelog.Debian'] = 'debchangelog',
+ ['NEWS.dch'] = 'debchangelog',
+ ['NEWS.Debian'] = 'debchangelog',
+ ['/debian/control'] = 'debcontrol',
+ ['/debian/copyright'] = 'debcopyright',
+ ['/etc/apt/sources.list'] = 'debsources',
+ ['denyhosts.conf'] = 'denyhosts',
+ ['dict.conf'] = 'dictconf',
+ ['.dictrc'] = 'dictconf',
+ ['/etc/DIR_COLORS'] = 'dircolors',
+ ['.dir_colors'] = 'dircolors',
+ ['.dircolors'] = 'dircolors',
+ ['/etc/dnsmasq.conf'] = 'dnsmasq',
+ Containerfile = 'dockerfile',
+ Dockerfile = 'dockerfile',
+ npmrc = 'dosini',
+ ['/etc/yum.conf'] = 'dosini',
+ ['/etc/pacman.conf'] = 'conf',
+ ['.npmrc'] = 'dosini',
+ ['.editorconfig'] = 'dosini',
+ dune = 'dune',
+ jbuild = 'dune',
+ ['dune-workspace'] = 'dune',
+ ['dune-project'] = 'dune',
+ ['elinks.conf'] = 'elinks',
+ ['mix.lock'] = 'elixir',
+ ['filter-rules'] = 'elmfilt',
+ ['exim.conf'] = 'exim',
+ exports = 'exports',
+ ['.fetchmailrc'] = 'fetchmail',
+ fvSchemes = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ fvSolution = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ fvConstraints = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ fvModels = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ fstab = 'fstab',
+ mtab = 'fstab',
+ ['.gdbinit'] = 'gdb',
+ gdbinit = 'gdb',
+ ['.gdbearlyinit'] = 'gdb',
+ gdbearlyinit = 'gdb',
+ ['lltxxxxx.txt'] = 'gedcom',
+ ['TAG_EDITMSG'] = 'gitcommit',
+ ['MERGE_MSG'] = 'gitcommit',
+ ['COMMIT_EDITMSG'] = 'gitcommit',
+ ['NOTES_EDITMSG'] = 'gitcommit',
+ ['EDIT_DESCRIPTION'] = 'gitcommit',
+ ['.gitconfig'] = 'gitconfig',
+ ['.gitmodules'] = 'gitconfig',
+ ['gitolite.conf'] = 'gitolite',
+ ['git-rebase-todo'] = 'gitrebase',
+ gkrellmrc = 'gkrellmrc',
+ ['.gnashrc'] = 'gnash',
+ ['.gnashpluginrc'] = 'gnash',
+ gnashpluginrc = 'gnash',
+ gnashrc = 'gnash',
+ ['go.work'] = 'gowork',
+ ['.gprc'] = 'gp',
+ ['/.gnupg/gpg.conf'] = 'gpg',
+ ['/.gnupg/options'] = 'gpg',
+ ['/var/backups/gshadow.bak'] = 'group',
+ ['/etc/gshadow'] = 'group',
+ ['/etc/group-'] = 'group',
+ ['/etc/gshadow.edit'] = 'group',
+ ['/etc/gshadow-'] = 'group',
+ ['/etc/group'] = 'group',
+ ['/var/backups/group.bak'] = 'group',
+ ['/etc/group.edit'] = 'group',
+ ['/boot/grub/menu.lst'] = 'grub',
+ ['/etc/grub.conf'] = 'grub',
+ ['/boot/grub/grub.conf'] = 'grub',
+ ['.gtkrc'] = 'gtkrc',
+ gtkrc = 'gtkrc',
+ ['snort.conf'] = 'hog',
+ ['vision.conf'] = 'hog',
+ ['/etc/host.conf'] = 'hostconf',
+ ['/etc/hosts.allow'] = 'hostsaccess',
+ ['/etc/hosts.deny'] = 'hostsaccess',
+ ['/i3/config'] = 'i3config',
+ ['/sway/config'] = 'i3config',
+ ['/.sway/config'] = 'i3config',
+ ['/.i3/config'] = 'i3config',
+ ['/.icewm/menu'] = 'icemenu',
+ ['.indent.pro'] = 'indent',
+ indentrc = 'indent',
+ inittab = 'inittab',
+ ['ipf.conf'] = 'ipfilter',
+ ['ipf6.conf'] = 'ipfilter',
+ ['ipf.rules'] = 'ipfilter',
+ ['.eslintrc'] = 'json',
+ ['.babelrc'] = 'json',
+ ['Pipfile.lock'] = 'json',
+ ['.firebaserc'] = 'json',
+ ['.prettierrc'] = 'json',
+ Kconfig = 'kconfig',
+ ['Kconfig.debug'] = 'kconfig',
+ ['lftp.conf'] = 'lftp',
+ ['.lftprc'] = 'lftp',
+ ['/.libao'] = 'libao',
+ ['/etc/libao.conf'] = 'libao',
+ ['lilo.conf'] = 'lilo',
+ ['/etc/limits'] = 'limits',
+ ['.emacs'] = 'lisp',
+ sbclrc = 'lisp',
+ ['.sbclrc'] = 'lisp',
+ ['.sawfishrc'] = 'lisp',
+ ['/etc/login.access'] = 'loginaccess',
+ ['/etc/login.defs'] = 'logindefs',
+ ['lynx.cfg'] = 'lynx',
+ ['m3overrides'] = 'm3build',
+ ['m3makefile'] = 'm3build',
+ ['cm3.cfg'] = 'm3quake',
+ ['.followup'] = 'mail',
+ ['.article'] = 'mail',
+ ['.letter'] = 'mail',
+ ['/etc/aliases'] = 'mailaliases',
+ ['/etc/mail/aliases'] = 'mailaliases',
+ mailcap = 'mailcap',
+ ['.mailcap'] = 'mailcap',
+ ['/etc/man.conf'] = 'manconf',
+ ['man.config'] = 'manconf',
+ ['maxima-init.mac'] = 'maxima',
+ ['meson.build'] = 'meson',
+ ['meson_options.txt'] = 'meson',
+ ['/etc/conf.modules'] = 'modconf',
+ ['/etc/modules'] = 'modconf',
+ ['/etc/modules.conf'] = 'modconf',
+ ['/.mplayer/config'] = 'mplayerconf',
+ ['mplayer.conf'] = 'mplayerconf',
+ mrxvtrc = 'mrxvtrc',
+ ['.mrxvtrc'] = 'mrxvtrc',
+ ['/etc/nanorc'] = 'nanorc',
+ Neomuttrc = 'neomuttrc',
+ ['.netrc'] = 'netrc',
+ ['.ocamlinit'] = 'ocaml',
+ ['.octaverc'] = 'octave',
+ octaverc = 'octave',
+ ['octave.conf'] = 'octave',
+ opam = 'opam',
+ ['/etc/pam.conf'] = 'pamconf',
+ ['pam_env.conf'] = 'pamenv',
+ ['.pam_environment'] = 'pamenv',
+ ['/var/backups/passwd.bak'] = 'passwd',
+ ['/var/backups/shadow.bak'] = 'passwd',
+ ['/etc/passwd'] = 'passwd',
+ ['/etc/passwd-'] = 'passwd',
+ ['/etc/shadow.edit'] = 'passwd',
+ ['/etc/shadow-'] = 'passwd',
+ ['/etc/shadow'] = 'passwd',
+ ['/etc/passwd.edit'] = 'passwd',
+ ['pf.conf'] = 'pf',
+ ['main.cf'] = 'pfmain',
+ pinerc = 'pine',
+ ['.pinercex'] = 'pine',
+ ['.pinerc'] = 'pine',
+ pinercex = 'pine',
+ ['/etc/pinforc'] = 'pinfo',
+ ['/.pinforc'] = 'pinfo',
+ ['.povrayrc'] = 'povini',
+ ['.procmailrc'] = 'procmail',
+ ['.procmail'] = 'procmail',
+ ['/etc/protocols'] = 'protocols',
+ ['.pythonstartup'] = 'python',
+ ['.pythonrc'] = 'python',
+ SConstruct = 'python',
+ ratpoisonrc = 'ratpoison',
+ ['.ratpoisonrc'] = 'ratpoison',
+ v = 'rcs',
+ inputrc = 'readline',
+ ['.inputrc'] = 'readline',
+ ['.reminders'] = 'remind',
+ ['resolv.conf'] = 'resolv',
+ ['robots.txt'] = 'robots',
+ Gemfile = 'ruby',
+ Puppetfile = 'ruby',
+ ['.irbrc'] = 'ruby',
+ irbrc = 'ruby',
+ Vagrantfile = 'ruby',
+ ['smb.conf'] = 'samba',
+ screenrc = 'screen',
+ ['.screenrc'] = 'screen',
+ ['/etc/sensors3.conf'] = 'sensors',
+ ['/etc/sensors.conf'] = 'sensors',
+ ['/etc/services'] = 'services',
+ ['/etc/serial.conf'] = 'setserial',
+ ['/etc/udev/cdsymlinks.conf'] = 'sh',
+ ['/etc/slp.conf'] = 'slpconf',
+ ['/etc/slp.reg'] = 'slpreg',
+ ['/etc/slp.spi'] = 'slpspi',
+ ['.slrnrc'] = 'slrnrc',
+ ['sendmail.cf'] = 'sm',
+ ['squid.conf'] = 'squid',
+ ['/.ssh/config'] = 'sshconfig',
+ ['ssh_config'] = 'sshconfig',
+ ['sshd_config'] = 'sshdconfig',
+ ['/etc/sudoers'] = 'sudoers',
+ ['sudoers.tmp'] = 'sudoers',
+ ['/etc/sysctl.conf'] = 'sysctl',
+ tags = 'tags',
+ ['.tclshrc'] = 'tcl',
+ ['.wishrc'] = 'tcl',
+ ['tclsh.rc'] = 'tcl',
+ ['texmf.cnf'] = 'texmf',
+ COPYING = 'text',
+ README = 'text',
+ LICENSE = 'text',
+ AUTHORS = 'text',
+ tfrc = 'tf',
+ ['.tfrc'] = 'tf',
+ ['tidy.conf'] = 'tidy',
+ tidyrc = 'tidy',
+ ['.tidyrc'] = 'tidy',
+ ['.tmux.conf'] = 'tmux',
+ ['/.cargo/config'] = 'toml',
+ Pipfile = 'toml',
+ ['Gopkg.lock'] = 'toml',
+ ['/.cargo/credentials'] = 'toml',
+ ['Cargo.lock'] = 'toml',
+ ['trustees.conf'] = 'trustees',
+ ['/etc/udev/udev.conf'] = 'udevconf',
+ ['/etc/updatedb.conf'] = 'updatedb',
+ ['fdrupstream.log'] = 'upstreamlog',
+ vgrindefs = 'vgrindefs',
+ ['.exrc'] = 'vim',
+ ['_exrc'] = 'vim',
+ ['_viminfo'] = 'viminfo',
+ ['.viminfo'] = 'viminfo',
+ ['.wgetrc'] = 'wget',
+ ['.wget2rc'] = 'wget2',
+ wgetrc = 'wget',
+ wget2rc = 'wget2',
+ ['.wvdialrc'] = 'wvdial',
+ ['wvdial.conf'] = 'wvdial',
+ ['.Xresources'] = 'xdefaults',
+ ['.Xpdefaults'] = 'xdefaults',
+ ['xdm-config'] = 'xdefaults',
+ ['.Xdefaults'] = 'xdefaults',
+ ['/etc/xinetd.conf'] = 'xinetd',
+ fglrxrc = 'xml',
+ ['/etc/blkid.tab'] = 'xml',
+ ['/etc/blkid.tab.old'] = 'xml',
+ ['/etc/zprofile'] = 'zsh',
+ ['.zlogin'] = 'zsh',
+ ['.zlogout'] = 'zsh',
+ ['.zshrc'] = 'zsh',
+ ['.zprofile'] = 'zsh',
+ ['.zcompdump'] = 'zsh',
+ ['.zshenv'] = 'zsh',
+ ['.zfbfmarks'] = 'zsh',
+ ['.alias'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['.bashrc'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['.cshrc'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['.env'] = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ ['.kshrc'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('ksh')
+ end,
+ ['.login'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['.profile'] = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ ['.tcshrc'] = function()
+ vim.fn['dist#ft#SetFileTypeShell']('tcsh')
+ end,
+ ['/etc/profile'] = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ APKBUILD = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ PKGBUILD = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['bash.bashrc'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ bashrc = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
crontab = starsetf('crontab'),
- ["csh.cshrc"] = function() vim.fn["dist#ft#CSH"]() end,
- ["csh.login"] = function() vim.fn["dist#ft#CSH"]() end,
- ["csh.logout"] = function() vim.fn["dist#ft#CSH"]() end,
- ["indent.pro"] = function() vim.fn["dist#ft#ProtoCheck"]('indent') end,
- ["tcsh.login"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
- ["tcsh.tcshrc"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
+ ['csh.cshrc'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['csh.login'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['csh.logout'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['indent.pro'] = function()
+ vim.fn['dist#ft#ProtoCheck']('indent')
+ end,
+ ['tcsh.login'] = function()
+ vim.fn['dist#ft#SetFileTypeShell']('tcsh')
+ end,
+ ['tcsh.tcshrc'] = function()
+ vim.fn['dist#ft#SetFileTypeShell']('tcsh')
+ end,
-- END FILENAME
}
local pattern = {
-- BEGIN PATTERN
- [".*/etc/a2ps/.*%.cfg"] = "a2ps",
- [".*/etc/a2ps%.cfg"] = "a2ps",
- [".*/usr/share/alsa/alsa%.conf"] = "alsaconf",
- [".*/etc/asound%.conf"] = "alsaconf",
- [".*/etc/apache2/sites%-.*/.*%.com"] = "apache",
- [".*/etc/httpd/.*%.conf"] = "apache",
- [".*/%.aptitude/config"] = "aptconf",
- ["[mM]akefile%.am"] = "automake",
- [".*bsd"] = "bsdl",
- ["bzr_log%..*"] = "bzr",
- [".*enlightenment/.*%.cfg"] = "c",
- [".*/etc/defaults/cdrdao"] = "cdrdaoconf",
- [".*/etc/cdrdao%.conf"] = "cdrdaoconf",
- [".*/etc/default/cdrdao"] = "cdrdaoconf",
- [".*hgrc"] = "cfg",
- [".*%.%.ch"] = "chill",
- [".*%.cmake%.in"] = "cmake",
- [".*/debian/changelog"] = "debchangelog",
- [".*/debian/control"] = "debcontrol",
- [".*/debian/copyright"] = "debcopyright",
- [".*/etc/apt/sources%.list%.d/.*%.list"] = "debsources",
- [".*/etc/apt/sources%.list"] = "debsources",
- ["dictd.*%.conf"] = "dictdconf",
- [".*/etc/DIR_COLORS"] = "dircolors",
- [".*/etc/dnsmasq%.conf"] = "dnsmasq",
- ["php%.ini%-.*"] = "dosini",
- [".*/etc/pacman%.conf"] = "conf",
- [".*/etc/yum%.conf"] = "dosini",
- [".*lvs"] = "dracula",
- [".*lpe"] = "dracula",
- [".*/dtrace/.*%.d"] = "dtrace",
- [".*esmtprc"] = "esmtprc",
- [".*Eterm/.*%.cfg"] = "eterm",
- [".*%.git/modules/.*/config"] = "gitconfig",
- [".*%.git/config"] = "gitconfig",
- [".*/etc/gitconfig"] = "gitconfig",
- [".*/%.config/git/config"] = "gitconfig",
- [".*%.git/config%.worktree"] = "gitconfig",
- [".*%.git/worktrees/.*/config%.worktree"] = "gitconfig",
- ["%.gitsendemail%.msg%......."] = "gitsendemail",
- ["gkrellmrc_."] = "gkrellmrc",
- [".*/usr/.*/gnupg/options%.skel"] = "gpg",
- [".*/%.gnupg/options"] = "gpg",
- [".*/%.gnupg/gpg%.conf"] = "gpg",
- [".*/etc/group"] = "group",
- [".*/etc/gshadow"] = "group",
- [".*/etc/group%.edit"] = "group",
- [".*/var/backups/gshadow%.bak"] = "group",
- [".*/etc/group-"] = "group",
- [".*/etc/gshadow-"] = "group",
- [".*/var/backups/group%.bak"] = "group",
- [".*/etc/gshadow%.edit"] = "group",
- [".*/boot/grub/grub%.conf"] = "grub",
- [".*/boot/grub/menu%.lst"] = "grub",
- [".*/etc/grub%.conf"] = "grub",
- ["hg%-editor%-.*%.txt"] = "hgcommit",
- [".*/etc/host%.conf"] = "hostconf",
- [".*/etc/hosts%.deny"] = "hostsaccess",
- [".*/etc/hosts%.allow"] = "hostsaccess",
- [".*%.html%.m4"] = "htmlm4",
- [".*/%.i3/config"] = "i3config",
- [".*/sway/config"] = "i3config",
- [".*/i3/config"] = "i3config",
- [".*/%.sway/config"] = "i3config",
- [".*/%.icewm/menu"] = "icemenu",
- [".*/etc/initng/.*/.*%.i"] = "initng",
- [".*%.properties_.."] = "jproperties",
- [".*%.properties_.._.."] = "jproperties",
- [".*lftp/rc"] = "lftp",
- [".*/%.libao"] = "libao",
- [".*/etc/libao%.conf"] = "libao",
- [".*/etc/.*limits%.conf"] = "limits",
- [".*/etc/limits"] = "limits",
- [".*/etc/.*limits%.d/.*%.conf"] = "limits",
- [".*/LiteStep/.*/.*%.rc"] = "litestep",
- [".*/etc/login%.access"] = "loginaccess",
- [".*/etc/login%.defs"] = "logindefs",
- [".*/etc/mail/aliases"] = "mailaliases",
- [".*/etc/aliases"] = "mailaliases",
- [".*[mM]akefile"] = "make",
- [".*/etc/man%.conf"] = "manconf",
- [".*/etc/modules%.conf"] = "modconf",
- [".*/etc/conf%.modules"] = "modconf",
- [".*/etc/modules"] = "modconf",
- [".*%.[mi][3g]"] = "modula3",
- [".*/%.mplayer/config"] = "mplayerconf",
- ["rndc.*%.conf"] = "named",
- ["rndc.*%.key"] = "named",
- ["named.*%.conf"] = "named",
- [".*/etc/nanorc"] = "nanorc",
- [".*%.NS[ACGLMNPS]"] = "natural",
- ["nginx.*%.conf"] = "nginx",
- [".*/etc/nginx/.*"] = "nginx",
- [".*nginx%.conf"] = "nginx",
- [".*/nginx/.*%.conf"] = "nginx",
- [".*/usr/local/nginx/conf/.*"] = "nginx",
- [".*%.ml%.cppo"] = "ocaml",
- [".*%.mli%.cppo"] = "ocaml",
- [".*%.opam%.template"] = "opam",
- [".*%.[Oo][Pp][Ll]"] = "opl",
- [".*/etc/pam%.conf"] = "pamconf",
- [".*/etc/passwd-"] = "passwd",
- [".*/etc/shadow"] = "passwd",
- [".*/etc/shadow%.edit"] = "passwd",
- [".*/var/backups/shadow%.bak"] = "passwd",
- [".*/var/backups/passwd%.bak"] = "passwd",
- [".*/etc/passwd"] = "passwd",
- [".*/etc/passwd%.edit"] = "passwd",
- [".*/etc/shadow-"] = "passwd",
- [".*/%.pinforc"] = "pinfo",
- [".*/etc/pinforc"] = "pinfo",
- [".*/etc/protocols"] = "protocols",
- [".*baseq[2-3]/.*%.cfg"] = "quake",
- [".*quake[1-3]/.*%.cfg"] = "quake",
- [".*id1/.*%.cfg"] = "quake",
- ["[rR]antfile"] = "ruby",
- ["[rR]akefile"] = "ruby",
- [".*/etc/sensors%.conf"] = "sensors",
- [".*/etc/sensors3%.conf"] = "sensors",
- [".*/etc/services"] = "services",
- [".*/etc/serial%.conf"] = "setserial",
- [".*/etc/udev/cdsymlinks%.conf"] = "sh",
- [".*%._sst%.meta"] = "sisu",
- [".*%.%-sst%.meta"] = "sisu",
- [".*%.sst%.meta"] = "sisu",
- [".*/etc/slp%.conf"] = "slpconf",
- [".*/etc/slp%.reg"] = "slpreg",
- [".*/etc/slp%.spi"] = "slpspi",
- [".*/etc/ssh/ssh_config%.d/.*%.conf"] = "sshconfig",
- [".*/%.ssh/config"] = "sshconfig",
- [".*/etc/ssh/sshd_config%.d/.*%.conf"] = "sshdconfig",
- [".*/etc/sudoers"] = "sudoers",
- ["svn%-commit.*%.tmp"] = "svn",
- [".*%.swift%.gyb"] = "swiftgyb",
- [".*/etc/sysctl%.conf"] = "sysctl",
- [".*/etc/sysctl%.d/.*%.conf"] = "sysctl",
- [".*/etc/systemd/.*%.conf%.d/.*%.conf"] = "systemd",
- [".*/%.config/systemd/user/.*%.d/.*%.conf"] = "systemd",
- [".*/etc/systemd/system/.*%.d/.*%.conf"] = "systemd",
- [".*%.t%.html"] = "tilde",
- ["%.?tmux.*%.conf"] = "tmux",
- ["%.?tmux.*%.conf.*"] = { "tmux", { priority = -1 } },
- [".*/%.cargo/config"] = "toml",
- [".*/%.cargo/credentials"] = "toml",
- [".*/etc/udev/udev%.conf"] = "udevconf",
- [".*/etc/udev/permissions%.d/.*%.permissions"] = "udevperm",
- [".*/etc/updatedb%.conf"] = "updatedb",
- [".*/%.init/.*%.override"] = "upstart",
- [".*/usr/share/upstart/.*%.conf"] = "upstart",
- [".*/%.config/upstart/.*%.override"] = "upstart",
- [".*/etc/init/.*%.conf"] = "upstart",
- [".*/etc/init/.*%.override"] = "upstart",
- [".*/%.config/upstart/.*%.conf"] = "upstart",
- [".*/%.init/.*%.conf"] = "upstart",
- [".*/usr/share/upstart/.*%.override"] = "upstart",
- [".*%.ws[fc]"] = "wsh",
- [".*/etc/xinetd%.conf"] = "xinetd",
- [".*/etc/blkid%.tab"] = "xml",
- [".*/etc/blkid%.tab%.old"] = "xml",
- [".*%.vbproj%.user"] = "xml",
- [".*%.fsproj%.user"] = "xml",
- [".*%.csproj%.user"] = "xml",
- [".*/etc/xdg/menus/.*%.menu"] = "xml",
- [".*Xmodmap"] = "xmodmap",
- [".*/etc/zprofile"] = "zsh",
- ["%.bash[_-]aliases"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ["%.bash[_-]logout"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ["%.bash[_-]profile"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ["%.cshrc.*"] = function() vim.fn["dist#ft#CSH"]() end,
- ["%.gtkrc.*"] = starsetf('gtkrc'),
- ["%.kshrc.*"] = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end,
- ["%.login.*"] = function() vim.fn["dist#ft#CSH"]() end,
- ["%.neomuttrc.*"] = starsetf('neomuttrc'),
- ["%.profile.*"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- ["%.reminders.*"] = starsetf('remind'),
- ["%.tcshrc.*"] = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
- ["%.zcompdump.*"] = starsetf('zsh'),
- ["%.zlog.*"] = starsetf('zsh'),
- ["%.zsh.*"] = starsetf('zsh'),
- [".*%.[1-9]"] = function(path, bufnr) return require("vim.filetype.detect").nroff(bufnr) end,
- [".*%.[aA]"] = function() vim.fn["dist#ft#FTasm"]() end,
- [".*%.[sS]"] = function() vim.fn["dist#ft#FTasm"]() end,
- [".*%.properties_.._.._.*"] = starsetf('jproperties'),
- [".*%.vhdl_[0-9].*"] = starsetf('vhdl'),
- [".*/%.fvwm/.*"] = starsetf('fvwm'),
- [".*/%.gitconfig%.d/.*"] = starsetf('gitconfig'),
- [".*/%.neomutt/neomuttrc.*"] = starsetf('neomuttrc'),
- [".*/Xresources/.*"] = starsetf('xdefaults'),
- [".*/app%-defaults/.*"] = starsetf('xdefaults'),
- [".*/bind/db%..*"] = starsetf('bindzone'),
- [".*/debian/patches/.*"] = function() vim.fn["dist#ft#Dep3patch"]() end,
- [".*/etc/Muttrc%.d/.*"] = starsetf('muttrc'),
- [".*/etc/apache2/.*%.conf.*"] = starsetf('apache'),
- [".*/etc/apache2/conf%..*/.*"] = starsetf('apache'),
- [".*/etc/apache2/mods%-.*/.*"] = starsetf('apache'),
- [".*/etc/apache2/sites%-.*/.*"] = starsetf('apache'),
- [".*/etc/cron%.d/.*"] = starsetf('crontab'),
- [".*/etc/dnsmasq%.d/.*"] = starsetf('dnsmasq'),
- [".*/etc/httpd/conf%..*/.*"] = starsetf('apache'),
- [".*/etc/httpd/conf%.d/.*%.conf.*"] = starsetf('apache'),
- [".*/etc/httpd/mods%-.*/.*"] = starsetf('apache'),
- [".*/etc/httpd/sites%-.*/.*"] = starsetf('apache'),
- [".*/etc/logcheck/.*%.d.*/.*"] = starsetf('logcheck'),
- [".*/etc/modprobe%..*"] = starsetf('modconf'),
- [".*/etc/pam%.d/.*"] = starsetf('pamconf'),
- [".*/etc/profile"] = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- [".*/etc/proftpd/.*%.conf.*"] = starsetf('apachestyle'),
- [".*/etc/proftpd/conf%..*/.*"] = starsetf('apachestyle'),
- [".*/etc/sudoers%.d/.*"] = starsetf('sudoers'),
- [".*/etc/xinetd%.d/.*"] = starsetf('xinetd'),
- [".*/etc/yum%.repos%.d/.*"] = starsetf('dosini'),
- [".*/gitolite%-admin/conf/.*"] = starsetf('gitolite'),
- [".*/named/db%..*"] = starsetf('bindzone'),
- [".*/tmp/lltmp.*"] = starsetf('gedcom'),
- [".*asterisk.*/.*voicemail%.conf.*"] = starsetf('asteriskvm'),
- [".*asterisk/.*%.conf.*"] = starsetf('asterisk'),
- [".*vimrc.*"] = starsetf('vim'),
- [".*xmodmap.*"] = starsetf('xmodmap'),
- ["/etc/gitconfig%.d/.*"] = starsetf('gitconfig'),
- ["/etc/hostname%..*"] = starsetf('config'),
- ["Containerfile%..*"] = starsetf('dockerfile'),
- ["Dockerfile%..*"] = starsetf('dockerfile'),
- ["JAM.*%..*"] = starsetf('jam'),
- ["Kconfig%..*"] = starsetf('kconfig'),
- ["Neomuttrc.*"] = starsetf('neomuttrc'),
- ["Prl.*%..*"] = starsetf('jam'),
- ["Xresources.*"] = starsetf('xdefaults'),
- ["[mM]akefile.*"] = starsetf('make'),
- ["[rR]akefile.*"] = starsetf('ruby'),
- ["access%.conf.*"] = starsetf('apache'),
- ["apache%.conf.*"] = starsetf('apache'),
- ["apache2%.conf.*"] = starsetf('apache'),
- ["bash%-fc[-%.]"] = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ["cabal%.project%..*"] = starsetf('cabalproject'),
- ["crontab%..*"] = starsetf('crontab'),
- ["drac%..*"] = starsetf('dracula'),
- ["gtkrc.*"] = starsetf('gtkrc'),
- ["httpd%.conf.*"] = starsetf('apache'),
- ["lilo%.conf.*"] = starsetf('lilo'),
- ["neomuttrc.*"] = starsetf('neomuttrc'),
- ["proftpd%.conf.*"] = starsetf('apachestyle'),
- ["reportbug%-.*"] = starsetf('mail'),
- ["sgml%.catalog.*"] = starsetf('catalog'),
- ["srm%.conf.*"] = starsetf('apache'),
- ["tmac%..*"] = starsetf('nroff'),
- ["zlog.*"] = starsetf('zsh'),
- ["zsh.*"] = starsetf('zsh'),
- ["ae%d+%.txt"] = 'mail',
- ["snd%.%d+"] = "mail",
- ["%.letter%.%d+"] = "mail",
- ["%.article%.%d+"] = "mail",
- ["pico%.%d+"] = "mail",
- ["mutt%-.*%-%w+"] = "mail",
- ["neomutt%-.*%-%w+"] = "mail",
- ["muttng%-.*%-%w+"] = "mail",
- ["mutt" .. string.rep("[%w_-]", 6)] = "mail",
- ["neomutt" .. string.rep("[%w_-]", 6)] = "mail",
- ["/tmp/SLRN[0-9A-Z.]+"] = "mail",
- ["[a-zA-Z0-9].*Dict"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- ["[a-zA-Z0-9].*Dict%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- ["[a-zA-Z].*Properties"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- ["[a-zA-Z].*Properties%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- [".*Transport%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- [".*/constant/g"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- [".*/0/.*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- [".*/0%.orig/.*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
- [".*/etc/sensors%.d/[^.].*"] = starsetf('sensors'),
- [".*%.git/.*"] = function(path, bufnr)
+ ['.*/etc/a2ps/.*%.cfg'] = 'a2ps',
+ ['.*/etc/a2ps%.cfg'] = 'a2ps',
+ ['.*/usr/share/alsa/alsa%.conf'] = 'alsaconf',
+ ['.*/etc/asound%.conf'] = 'alsaconf',
+ ['.*/etc/apache2/sites%-.*/.*%.com'] = 'apache',
+ ['.*/etc/httpd/.*%.conf'] = 'apache',
+ ['.*/%.aptitude/config'] = 'aptconf',
+ ['[mM]akefile%.am'] = 'automake',
+ ['.*bsd'] = 'bsdl',
+ ['bzr_log%..*'] = 'bzr',
+ ['.*enlightenment/.*%.cfg'] = 'c',
+ ['.*/etc/defaults/cdrdao'] = 'cdrdaoconf',
+ ['.*/etc/cdrdao%.conf'] = 'cdrdaoconf',
+ ['.*/etc/default/cdrdao'] = 'cdrdaoconf',
+ ['.*hgrc'] = 'cfg',
+ ['.*%.%.ch'] = 'chill',
+ ['.*%.cmake%.in'] = 'cmake',
+ ['.*/debian/changelog'] = 'debchangelog',
+ ['.*/debian/control'] = 'debcontrol',
+ ['.*/debian/copyright'] = 'debcopyright',
+ ['.*/etc/apt/sources%.list%.d/.*%.list'] = 'debsources',
+ ['.*/etc/apt/sources%.list'] = 'debsources',
+ ['dictd.*%.conf'] = 'dictdconf',
+ ['.*/etc/DIR_COLORS'] = 'dircolors',
+ ['.*/etc/dnsmasq%.conf'] = 'dnsmasq',
+ ['php%.ini%-.*'] = 'dosini',
+ ['.*/etc/pacman%.conf'] = 'conf',
+ ['.*/etc/yum%.conf'] = 'dosini',
+ ['.*lvs'] = 'dracula',
+ ['.*lpe'] = 'dracula',
+ ['.*/dtrace/.*%.d'] = 'dtrace',
+ ['.*esmtprc'] = 'esmtprc',
+ ['.*Eterm/.*%.cfg'] = 'eterm',
+ ['.*%.git/modules/.*/config'] = 'gitconfig',
+ ['.*%.git/config'] = 'gitconfig',
+ ['.*/etc/gitconfig'] = 'gitconfig',
+ ['.*/%.config/git/config'] = 'gitconfig',
+ ['.*%.git/config%.worktree'] = 'gitconfig',
+ ['.*%.git/worktrees/.*/config%.worktree'] = 'gitconfig',
+ ['%.gitsendemail%.msg%.......'] = 'gitsendemail',
+ ['gkrellmrc_.'] = 'gkrellmrc',
+ ['.*/usr/.*/gnupg/options%.skel'] = 'gpg',
+ ['.*/%.gnupg/options'] = 'gpg',
+ ['.*/%.gnupg/gpg%.conf'] = 'gpg',
+ ['.*/etc/group'] = 'group',
+ ['.*/etc/gshadow'] = 'group',
+ ['.*/etc/group%.edit'] = 'group',
+ ['.*/var/backups/gshadow%.bak'] = 'group',
+ ['.*/etc/group-'] = 'group',
+ ['.*/etc/gshadow-'] = 'group',
+ ['.*/var/backups/group%.bak'] = 'group',
+ ['.*/etc/gshadow%.edit'] = 'group',
+ ['.*/boot/grub/grub%.conf'] = 'grub',
+ ['.*/boot/grub/menu%.lst'] = 'grub',
+ ['.*/etc/grub%.conf'] = 'grub',
+ ['hg%-editor%-.*%.txt'] = 'hgcommit',
+ ['.*/etc/host%.conf'] = 'hostconf',
+ ['.*/etc/hosts%.deny'] = 'hostsaccess',
+ ['.*/etc/hosts%.allow'] = 'hostsaccess',
+ ['.*%.html%.m4'] = 'htmlm4',
+ ['.*/%.i3/config'] = 'i3config',
+ ['.*/sway/config'] = 'i3config',
+ ['.*/i3/config'] = 'i3config',
+ ['.*/%.sway/config'] = 'i3config',
+ ['.*/%.icewm/menu'] = 'icemenu',
+ ['.*/etc/initng/.*/.*%.i'] = 'initng',
+ ['.*%.properties_..'] = 'jproperties',
+ ['.*%.properties_.._..'] = 'jproperties',
+ ['.*lftp/rc'] = 'lftp',
+ ['.*/%.libao'] = 'libao',
+ ['.*/etc/libao%.conf'] = 'libao',
+ ['.*/etc/.*limits%.conf'] = 'limits',
+ ['.*/etc/limits'] = 'limits',
+ ['.*/etc/.*limits%.d/.*%.conf'] = 'limits',
+ ['.*/LiteStep/.*/.*%.rc'] = 'litestep',
+ ['.*/etc/login%.access'] = 'loginaccess',
+ ['.*/etc/login%.defs'] = 'logindefs',
+ ['.*/etc/mail/aliases'] = 'mailaliases',
+ ['.*/etc/aliases'] = 'mailaliases',
+ ['.*[mM]akefile'] = 'make',
+ ['.*/etc/man%.conf'] = 'manconf',
+ ['.*/etc/modules%.conf'] = 'modconf',
+ ['.*/etc/conf%.modules'] = 'modconf',
+ ['.*/etc/modules'] = 'modconf',
+ ['.*%.[mi][3g]'] = 'modula3',
+ ['.*/%.mplayer/config'] = 'mplayerconf',
+ ['rndc.*%.conf'] = 'named',
+ ['rndc.*%.key'] = 'named',
+ ['named.*%.conf'] = 'named',
+ ['.*/etc/nanorc'] = 'nanorc',
+ ['.*%.NS[ACGLMNPS]'] = 'natural',
+ ['nginx.*%.conf'] = 'nginx',
+ ['.*/etc/nginx/.*'] = 'nginx',
+ ['.*nginx%.conf'] = 'nginx',
+ ['.*/nginx/.*%.conf'] = 'nginx',
+ ['.*/usr/local/nginx/conf/.*'] = 'nginx',
+ ['.*%.ml%.cppo'] = 'ocaml',
+ ['.*%.mli%.cppo'] = 'ocaml',
+ ['.*%.opam%.template'] = 'opam',
+ ['.*%.[Oo][Pp][Ll]'] = 'opl',
+ ['.*/etc/pam%.conf'] = 'pamconf',
+ ['.*/etc/passwd-'] = 'passwd',
+ ['.*/etc/shadow'] = 'passwd',
+ ['.*/etc/shadow%.edit'] = 'passwd',
+ ['.*/var/backups/shadow%.bak'] = 'passwd',
+ ['.*/var/backups/passwd%.bak'] = 'passwd',
+ ['.*/etc/passwd'] = 'passwd',
+ ['.*/etc/passwd%.edit'] = 'passwd',
+ ['.*/etc/shadow-'] = 'passwd',
+ ['.*/%.pinforc'] = 'pinfo',
+ ['.*/etc/pinforc'] = 'pinfo',
+ ['.*/etc/protocols'] = 'protocols',
+ ['.*baseq[2-3]/.*%.cfg'] = 'quake',
+ ['.*quake[1-3]/.*%.cfg'] = 'quake',
+ ['.*id1/.*%.cfg'] = 'quake',
+ ['[rR]antfile'] = 'ruby',
+ ['[rR]akefile'] = 'ruby',
+ ['.*/etc/sensors%.conf'] = 'sensors',
+ ['.*/etc/sensors3%.conf'] = 'sensors',
+ ['.*/etc/services'] = 'services',
+ ['.*/etc/serial%.conf'] = 'setserial',
+ ['.*/etc/udev/cdsymlinks%.conf'] = 'sh',
+ ['.*%._sst%.meta'] = 'sisu',
+ ['.*%.%-sst%.meta'] = 'sisu',
+ ['.*%.sst%.meta'] = 'sisu',
+ ['.*/etc/slp%.conf'] = 'slpconf',
+ ['.*/etc/slp%.reg'] = 'slpreg',
+ ['.*/etc/slp%.spi'] = 'slpspi',
+ ['.*/etc/ssh/ssh_config%.d/.*%.conf'] = 'sshconfig',
+ ['.*/%.ssh/config'] = 'sshconfig',
+ ['.*/etc/ssh/sshd_config%.d/.*%.conf'] = 'sshdconfig',
+ ['.*/etc/sudoers'] = 'sudoers',
+ ['svn%-commit.*%.tmp'] = 'svn',
+ ['.*%.swift%.gyb'] = 'swiftgyb',
+ ['.*/etc/sysctl%.conf'] = 'sysctl',
+ ['.*/etc/sysctl%.d/.*%.conf'] = 'sysctl',
+ ['.*/etc/systemd/.*%.conf%.d/.*%.conf'] = 'systemd',
+ ['.*/%.config/systemd/user/.*%.d/.*%.conf'] = 'systemd',
+ ['.*/etc/systemd/system/.*%.d/.*%.conf'] = 'systemd',
+ ['.*%.t%.html'] = 'tilde',
+ ['%.?tmux.*%.conf'] = 'tmux',
+ ['%.?tmux.*%.conf.*'] = { 'tmux', { priority = -1 } },
+ ['.*/%.cargo/config'] = 'toml',
+ ['.*/%.cargo/credentials'] = 'toml',
+ ['.*/etc/udev/udev%.conf'] = 'udevconf',
+ ['.*/etc/udev/permissions%.d/.*%.permissions'] = 'udevperm',
+ ['.*/etc/updatedb%.conf'] = 'updatedb',
+ ['.*/%.init/.*%.override'] = 'upstart',
+ ['.*/usr/share/upstart/.*%.conf'] = 'upstart',
+ ['.*/%.config/upstart/.*%.override'] = 'upstart',
+ ['.*/etc/init/.*%.conf'] = 'upstart',
+ ['.*/etc/init/.*%.override'] = 'upstart',
+ ['.*/%.config/upstart/.*%.conf'] = 'upstart',
+ ['.*/%.init/.*%.conf'] = 'upstart',
+ ['.*/usr/share/upstart/.*%.override'] = 'upstart',
+ ['.*%.ws[fc]'] = 'wsh',
+ ['.*/etc/xinetd%.conf'] = 'xinetd',
+ ['.*/etc/blkid%.tab'] = 'xml',
+ ['.*/etc/blkid%.tab%.old'] = 'xml',
+ ['.*%.vbproj%.user'] = 'xml',
+ ['.*%.fsproj%.user'] = 'xml',
+ ['.*%.csproj%.user'] = 'xml',
+ ['.*/etc/xdg/menus/.*%.menu'] = 'xml',
+ ['.*Xmodmap'] = 'xmodmap',
+ ['.*/etc/zprofile'] = 'zsh',
+ ['%.bash[_-]aliases'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['%.bash[_-]logout'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['%.bash[_-]profile'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['%.cshrc.*'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['%.gtkrc.*'] = starsetf('gtkrc'),
+ ['%.kshrc.*'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('ksh')
+ end,
+ ['%.login.*'] = function()
+ vim.fn['dist#ft#CSH']()
+ end,
+ ['%.neomuttrc.*'] = starsetf('neomuttrc'),
+ ['%.profile.*'] = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ ['%.reminders.*'] = starsetf('remind'),
+ ['%.tcshrc.*'] = function()
+ vim.fn['dist#ft#SetFileTypeShell']('tcsh')
+ end,
+ ['%.zcompdump.*'] = starsetf('zsh'),
+ ['%.zlog.*'] = starsetf('zsh'),
+ ['%.zsh.*'] = starsetf('zsh'),
+ ['.*%.[1-9]'] = function(path, bufnr)
+ return require('vim.filetype.detect').nroff(bufnr)
+ end,
+ ['.*%.[aA]'] = function()
+ vim.fn['dist#ft#FTasm']()
+ end,
+ ['.*%.[sS]'] = function()
+ vim.fn['dist#ft#FTasm']()
+ end,
+ ['.*%.properties_.._.._.*'] = starsetf('jproperties'),
+ ['.*%.vhdl_[0-9].*'] = starsetf('vhdl'),
+ ['.*/%.fvwm/.*'] = starsetf('fvwm'),
+ ['.*/%.gitconfig%.d/.*'] = starsetf('gitconfig'),
+ ['.*/%.neomutt/neomuttrc.*'] = starsetf('neomuttrc'),
+ ['.*/Xresources/.*'] = starsetf('xdefaults'),
+ ['.*/app%-defaults/.*'] = starsetf('xdefaults'),
+ ['.*/bind/db%..*'] = starsetf('bindzone'),
+ ['.*/debian/patches/.*'] = function()
+ vim.fn['dist#ft#Dep3patch']()
+ end,
+ ['.*/etc/Muttrc%.d/.*'] = starsetf('muttrc'),
+ ['.*/etc/apache2/.*%.conf.*'] = starsetf('apache'),
+ ['.*/etc/apache2/conf%..*/.*'] = starsetf('apache'),
+ ['.*/etc/apache2/mods%-.*/.*'] = starsetf('apache'),
+ ['.*/etc/apache2/sites%-.*/.*'] = starsetf('apache'),
+ ['.*/etc/cron%.d/.*'] = starsetf('crontab'),
+ ['.*/etc/dnsmasq%.d/.*'] = starsetf('dnsmasq'),
+ ['.*/etc/httpd/conf%..*/.*'] = starsetf('apache'),
+ ['.*/etc/httpd/conf%.d/.*%.conf.*'] = starsetf('apache'),
+ ['.*/etc/httpd/mods%-.*/.*'] = starsetf('apache'),
+ ['.*/etc/httpd/sites%-.*/.*'] = starsetf('apache'),
+ ['.*/etc/logcheck/.*%.d.*/.*'] = starsetf('logcheck'),
+ ['.*/etc/modprobe%..*'] = starsetf('modconf'),
+ ['.*/etc/pam%.d/.*'] = starsetf('pamconf'),
+ ['.*/etc/profile'] = function()
+ vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1))
+ end,
+ ['.*/etc/proftpd/.*%.conf.*'] = starsetf('apachestyle'),
+ ['.*/etc/proftpd/conf%..*/.*'] = starsetf('apachestyle'),
+ ['.*/etc/sudoers%.d/.*'] = starsetf('sudoers'),
+ ['.*/etc/xinetd%.d/.*'] = starsetf('xinetd'),
+ ['.*/etc/yum%.repos%.d/.*'] = starsetf('dosini'),
+ ['.*/gitolite%-admin/conf/.*'] = starsetf('gitolite'),
+ ['.*/named/db%..*'] = starsetf('bindzone'),
+ ['.*/tmp/lltmp.*'] = starsetf('gedcom'),
+ ['.*asterisk.*/.*voicemail%.conf.*'] = starsetf('asteriskvm'),
+ ['.*asterisk/.*%.conf.*'] = starsetf('asterisk'),
+ ['.*vimrc.*'] = starsetf('vim'),
+ ['.*xmodmap.*'] = starsetf('xmodmap'),
+ ['/etc/gitconfig%.d/.*'] = starsetf('gitconfig'),
+ ['/etc/hostname%..*'] = starsetf('config'),
+ ['Containerfile%..*'] = starsetf('dockerfile'),
+ ['Dockerfile%..*'] = starsetf('dockerfile'),
+ ['JAM.*%..*'] = starsetf('jam'),
+ ['Kconfig%..*'] = starsetf('kconfig'),
+ ['Neomuttrc.*'] = starsetf('neomuttrc'),
+ ['Prl.*%..*'] = starsetf('jam'),
+ ['Xresources.*'] = starsetf('xdefaults'),
+ ['[mM]akefile.*'] = starsetf('make'),
+ ['[rR]akefile.*'] = starsetf('ruby'),
+ ['access%.conf.*'] = starsetf('apache'),
+ ['apache%.conf.*'] = starsetf('apache'),
+ ['apache2%.conf.*'] = starsetf('apache'),
+ ['bash%-fc[-%.]'] = function()
+ vim.fn['dist#ft#SetFileTypeSH']('bash')
+ end,
+ ['cabal%.project%..*'] = starsetf('cabalproject'),
+ ['crontab%..*'] = starsetf('crontab'),
+ ['drac%..*'] = starsetf('dracula'),
+ ['gtkrc.*'] = starsetf('gtkrc'),
+ ['httpd%.conf.*'] = starsetf('apache'),
+ ['lilo%.conf.*'] = starsetf('lilo'),
+ ['neomuttrc.*'] = starsetf('neomuttrc'),
+ ['proftpd%.conf.*'] = starsetf('apachestyle'),
+ ['reportbug%-.*'] = starsetf('mail'),
+ ['sgml%.catalog.*'] = starsetf('catalog'),
+ ['srm%.conf.*'] = starsetf('apache'),
+ ['tmac%..*'] = starsetf('nroff'),
+ ['zlog.*'] = starsetf('zsh'),
+ ['zsh.*'] = starsetf('zsh'),
+ ['ae%d+%.txt'] = 'mail',
+ ['snd%.%d+'] = 'mail',
+ ['%.letter%.%d+'] = 'mail',
+ ['%.article%.%d+'] = 'mail',
+ ['pico%.%d+'] = 'mail',
+ ['mutt%-.*%-%w+'] = 'mail',
+ ['neomutt%-.*%-%w+'] = 'mail',
+ ['muttng%-.*%-%w+'] = 'mail',
+ ['mutt' .. string.rep('[%w_-]', 6)] = 'mail',
+ ['neomutt' .. string.rep('[%w_-]', 6)] = 'mail',
+ ['/tmp/SLRN[0-9A-Z.]+'] = 'mail',
+ ['[a-zA-Z0-9].*Dict'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['[a-zA-Z0-9].*Dict%..*'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['[a-zA-Z].*Properties'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['[a-zA-Z].*Properties%..*'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['.*Transport%..*'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['.*/constant/g'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['.*/0/.*'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['.*/0%.orig/.*'] = function(path, bufnr)
+ require('vim.filetype.detect').foam(bufnr)
+ end,
+ ['.*/etc/sensors%.d/[^.].*'] = starsetf('sensors'),
+ ['.*%.git/.*'] = function(path, bufnr)
local firstline = getline(bufnr, 1)
- if firstline:find("^" .. string.rep("%x", 40) .. "+ ") or firstline:sub(1, 5) == "ref: " then
- return "git"
+ if firstline:find('^' .. string.rep('%x', 40) .. '+ ') or firstline:sub(1, 5) == 'ref: ' then
+ return 'git'
end
end,
- [".*%.[Cc][Ff][Gg]"] = function() vim.fn["dist#ft#FTcfg"]() end,
- [".*%.[Dd][Aa][Tt]"] = function() vim.fn["dist#ft#FTdat"]() end,
- [".*%.[Mm][Oo][Dd]"] = function() vim.fn["dist#ft#FTmod"]() end,
- [".*%.[Ss][Rr][Cc]"] = function() vim.fn["dist#ft#FTsrc"]() end,
- [".*%.[Ss][Uu][Bb]"] = "krl",
- [".*%.[Pp][Rr][Gg]"] = function() vim.fn["dist#ft#FTprg"]() end,
- [".*%.[Ss][Yy][Ss]"] = function() vim.fn["dist#ft#FTsys"]() end,
+ ['.*%.[Cc][Ff][Gg]'] = function()
+ vim.fn['dist#ft#FTcfg']()
+ end,
+ ['.*%.[Dd][Aa][Tt]'] = function()
+ vim.fn['dist#ft#FTdat']()
+ end,
+ ['.*%.[Mm][Oo][Dd]'] = function()
+ vim.fn['dist#ft#FTmod']()
+ end,
+ ['.*%.[Ss][Rr][Cc]'] = function()
+ vim.fn['dist#ft#FTsrc']()
+ end,
+ ['.*%.[Ss][Uu][Bb]'] = 'krl',
+ ['.*%.[Pp][Rr][Gg]'] = function()
+ vim.fn['dist#ft#FTprg']()
+ end,
+ ['.*%.[Ss][Yy][Ss]'] = function()
+ vim.fn['dist#ft#FTsys']()
+ end,
-- Neovim only
- [".*/queries/.*%.scm"] = "query", -- tree-sitter queries
+ ['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries
-- END PATTERN
}
-- luacheck: pop
@@ -1466,10 +1709,10 @@ local pattern = {
local function sort_by_priority(t)
local sorted = {}
for k, v in pairs(t) do
- local ft = type(v) == "table" and v[1] or v
- assert(type(ft) == "string" or type(ft) == "function", "Expected string or function for filetype")
+ local ft = type(v) == 'table' and v[1] or v
+ assert(type(ft) == 'string' or type(ft) == 'function', 'Expected string or function for filetype')
- local opts = (type(v) == "table" and type(v[2]) == "table") and v[2] or {}
+ local opts = (type(v) == 'table' and type(v[2]) == 'table') and v[2] or {}
if not opts.priority then
opts.priority = 0
end
@@ -1485,7 +1728,7 @@ local pattern_sorted = sort_by_priority(pattern)
---@private
local function normalize_path(path, as_pattern)
- local normal = path:gsub("\\", '/')
+ local normal = path:gsub('\\', '/')
if normal:find('^~') then
if as_pattern then
-- Escape Lua's metacharacters when $HOME is used in a pattern.
@@ -1574,12 +1817,12 @@ end
---@private
local function dispatch(ft, path, bufnr, ...)
- if type(ft) == "function" then
+ if type(ft) == 'function' then
ft = ft(path, bufnr, ...)
end
- if type(ft) == "string" then
- api.nvim_buf_set_option(bufnr, "filetype", ft)
+ if type(ft) == 'string' then
+ api.nvim_buf_set_option(bufnr, 'filetype', ft)
return true
end
@@ -1592,9 +1835,9 @@ end
---@private
local function match_pattern(name, path, tail, pat)
-- If the pattern contains a / match against the full path, otherwise just the tail
- local fullpat = "^" .. pat .. "$"
+ local fullpat = '^' .. pat .. '$'
local matches
- if pat:find("/") then
+ if pat:find('/') then
-- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
-- both the short file name (as typed) and the full file name (after expanding to full path
-- and resolving symlinks)
@@ -1618,13 +1861,13 @@ function M.match(name, bufnr)
name = normalize_path(name)
-- First check for the simple case where the full path exists as a key
- local path = vim.fn.resolve(vim.fn.fnamemodify(name, ":p"))
+ local path = vim.fn.resolve(vim.fn.fnamemodify(name, ':p'))
if dispatch(filename[path], path, bufnr) then
return
end
-- Next check against just the file name
- local tail = vim.fn.fnamemodify(name, ":t")
+ local tail = vim.fn.fnamemodify(name, ':t')
if dispatch(filename[tail], path, bufnr) then
return
end
@@ -1649,7 +1892,7 @@ function M.match(name, bufnr)
end
-- Next, check file extension
- local ext = vim.fn.fnamemodify(name, ":e")
+ local ext = vim.fn.fnamemodify(name, ':e')
if dispatch(extension[ext], path, bufnr) then
return
end
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index 787b335251..4c363e7403 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -9,7 +9,7 @@ local function getlines(bufnr, start_lnum, end_lnum, opts)
local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
opts = opts or {}
- return opts.concat and (table.concat(lines) or "") or lines
+ return opts.concat and (table.concat(lines) or '') or lines
end
---@private
@@ -35,23 +35,23 @@ function M.bindzone(path, bufnr) end
function M.btm(bufnr)
if vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0 then
- vim.bo[bufnr].filetype = "dosbatch"
+ vim.bo[bufnr].filetype = 'dosbatch'
else
- vim.bo[bufnr].filetype = "btm"
+ vim.bo[bufnr].filetype = 'btm'
end
end
-- Returns true if file content looks like RAPID
local function is_rapid(bufnr, extension)
- if extension == "cfg" then
+ if extension == 'cfg' then
local line = getlines(bufnr, 1):lower()
- return findany(line, { "eio:cfg", "mmc:cfg", "moc:cfg", "proc:cfg", "sio:cfg", "sys:cfg" })
+ return findany(line, { 'eio:cfg', 'mmc:cfg', 'moc:cfg', 'proc:cfg', 'sio:cfg', 'sys:cfg' })
end
- local first = "^%s*module%s+%S+%s*"
+ local first = '^%s*module%s+%S+%s*'
-- Called from mod, prg or sys functions
for _, line in ipairs(getlines(bufnr, 1, -1)) do
- if not line:find("^%s*$") then
- return findany(line:lower(), { "^%s*%%%%%%", first .. "(", first .. "$" })
+ if not line:find('^%s*$') then
+ return findany(line:lower(), { '^%s*%%%%%%', first .. '(', first .. '$' })
end
end
-- Only found blank lines
@@ -61,10 +61,10 @@ end
function M.cfg(bufnr)
if vim.g.filetype_cfg then
vim.bo[bufnr].filetype = vim.g.filetype_cfg
- elseif is_rapid(bufnr, "cfg") then
- vim.bo[bufnr].filetype = "rapid"
+ elseif is_rapid(bufnr, 'cfg') then
+ vim.bo[bufnr].filetype = 'rapid'
else
- vim.bo[bufnr].filetype = "cfg"
+ vim.bo[bufnr].filetype = 'cfg'
end
end
@@ -85,23 +85,23 @@ function M.e(path, bufnr) end
-- If not found, assume SGML.
function M.ent(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 5)) do
- if line:find("^%s*[#{]") then
- vim.bo[bufnr].filetype = "cl"
+ if line:find('^%s*[#{]') then
+ vim.bo[bufnr].filetype = 'cl'
return
- elseif not line:find("^%s*$") then
+ elseif not line:find('^%s*$') then
-- Not a blank line, not a comment, and not a block start,
-- so doesn't look like valid cl code.
break
end
end
- vim.bo[bufnr].filetype = "dtd"
+ vim.bo[bufnr].filetype = 'dtd'
end
function M.euphoria(bufnr)
if vim.g.filetype_euphoria then
vim.bo[bufnr].filetype = vim.g.filetype_euphoria
else
- vim.bo[bufnr].filetype = "euphoria3"
+ vim.bo[bufnr].filetype = 'euphoria3'
end
end
@@ -111,12 +111,12 @@ function M.ex(bufnr)
else
for _, line in ipairs(getlines(bufnr, 1, 100)) do
-- TODO: in the Vim regex, \> is used to match the end of the word, can this be omitted?
- if findany(line, { "^%-%-", "^ifdef", "^include" }) then
- vim.bo[bufnr].filetype = "euphoria3"
+ if findany(line, { '^%-%-', '^ifdef', '^include' }) then
+ vim.bo[bufnr].filetype = 'euphoria3'
return
end
end
- vim.bo[bufnr].filetype = "elixir"
+ vim.bo[bufnr].filetype = 'elixir'
end
end
@@ -126,10 +126,10 @@ end
function M.foam(bufnr)
local foam_file = false
for _, line in ipairs(getlines(bufnr, 1, 15)) do
- if line:find("^FoamFile") then
+ if line:find('^FoamFile') then
foam_file = true
- elseif foam_file and line:find("^%s*object") then
- vim.bo[bufnr].filetype = "foam"
+ elseif foam_file and line:find('^%s*object') then
+ vim.bo[bufnr].filetype = 'foam'
return
end
end
@@ -141,10 +141,10 @@ function M.frm(bufnr)
else
-- Always ignore case
local lines = getlines(bufnr, 1, 5, { concat = true }):lower()
- if findany(lines, { "vb_name", "begin vb%.form", "begin vb%.mdiform" }) then
- vim.bo[bufnr].filetype = "vb"
+ if findany(lines, { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform' }) then
+ vim.bo[bufnr].filetype = 'vb'
else
- vim.bo[bufnr].filetype = "form"
+ vim.bo[bufnr].filetype = 'form'
end
end
end
@@ -153,21 +153,21 @@ function M.fs(path, bufnr) end
function M.header(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 200)) do
- if findany(line, { "^@interface", "^@end", "^@class" }) then
+ if findany(line, { '^@interface', '^@end', '^@class' }) then
if vim.g.c_syntax_for_h then
- vim.bo[bufnr].filetype = "objc"
+ vim.bo[bufnr].filetype = 'objc'
else
- vim.bo[bufnr].filetype = "objcpp"
+ vim.bo[bufnr].filetype = 'objcpp'
end
return
end
end
if vim.g.c_syntax_for_h then
- vim.bo[bufnr].filetype = "c"
+ vim.bo[bufnr].filetype = 'c'
elseif vim.g.ch_syntax_for_h then
- vim.bo[bufnr].filetype = "ch"
+ vim.bo[bufnr].filetype = 'ch'
else
- vim.bo[bufnr].filetype = "cpp"
+ vim.bo[bufnr].filetype = 'cpp'
end
end
@@ -176,22 +176,22 @@ function M.idl(bufnr)
-- Always ignore case
line = line:lower()
if findany(line, { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then
- vim.bo[bufnr].filetype = "msidl"
+ vim.bo[bufnr].filetype = 'msidl'
return
end
end
- vim.bo[bufnr].filetype = "idl"
+ vim.bo[bufnr].filetype = 'idl'
end
function M.inc(path, bufnr) end
function M.inp(bufnr)
- if getlines(bufnr, 1):find("^%*") then
- vim.bo[bufnr].filetype = "abaqus"
+ if getlines(bufnr, 1):find('^%*') then
+ vim.bo[bufnr].filetype = 'abaqus'
else
for _, line in ipairs(getlines(bufnr, 1, 500)) do
- if line:lower():find("^header surface data") then
- vim.bo[bufnr].filetype = "trasys"
+ if line:lower():find('^header surface data') then
+ vim.bo[bufnr].filetype = 'trasys'
return
end
end
@@ -208,32 +208,32 @@ function M.m(path, bufnr) end
-- MS message text files use ';', Sendmail files use '#' or 'dnl'
function M.mc(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 20)) do
- if findany(line:lower(), { "^%s*#", "^%s*dnl" }) then
+ if findany(line:lower(), { '^%s*#', '^%s*dnl' }) then
-- Sendmail .mc file
- vim.bo[bufnr].filetype = "m4"
+ vim.bo[bufnr].filetype = 'm4'
return
- elseif line:find("^%s*;") then
- vim.bo[bufnr].filetype = "msmessages"
+ elseif line:find('^%s*;') then
+ vim.bo[bufnr].filetype = 'msmessages'
return
end
end
-- Default: Sendmail .mc file
- vim.bo[bufnr].filetype = "m4"
+ vim.bo[bufnr].filetype = 'm4'
end
function M.mm(path, bufnr) end
function M.mms(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 20)) do
- if findany(line, { "^%s*%%", "^%s*//", "^%*" }) then
- vim.bo[bufnr].filetype = "mmix"
+ if findany(line, { '^%s*%%', '^%s*//', '^%*' }) then
+ vim.bo[bufnr].filetype = 'mmix'
return
- elseif line:find("^%s*#") then
- vim.bo[bufnr].filetype = "make"
+ elseif line:find('^%s*#') then
+ vim.bo[bufnr].filetype = 'make'
return
end
end
- vim.bo[bufnr].filetype = "mmix"
+ vim.bo[bufnr].filetype = 'mmix'
end
function M.mod(path, bufnr) end
@@ -242,8 +242,8 @@ function M.mod(path, bufnr) end
-- that case it is probably an nroff file: 'filetype' is set and 1 is returned.
function M.nroff(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 5)) do
- if line:find("^%.") then
- vim.bo[bufnr].filetype = "nroff"
+ if line:find('^%.') then
+ vim.bo[bufnr].filetype = 'nroff'
return 1
end
end
@@ -264,10 +264,10 @@ function M.progress_cweb(bufnr)
if vim.g.filetype_w then
vim.bo[bufnr].filetype = vim.g.filetype_w
else
- if getlines(bufnr, 1):find("^&ANALYZE") or getlines(bufnr, 3):find("^&GLOBAL%-DEFINE") then
- vim.bo[bufnr].filetype = "progress"
+ if getlines(bufnr, 1):find('^&ANALYZE') or getlines(bufnr, 3):find('^&GLOBAL%-DEFINE') then
+ vim.bo[bufnr].filetype = 'progress'
else
- vim.bo[bufnr].filetype = "cweb"
+ vim.bo[bufnr].filetype = 'cweb'
end
end
end
@@ -280,20 +280,20 @@ function M.r(bufnr)
local lines = getlines(bufnr, 1, 50)
-- TODO: \< / \> which match the beginning / end of a word
-- Rebol is easy to recognize, check for that first
- if table.concat(lines):lower():find("rebol") then
- vim.bo[bufnr].filetype = "rebol"
+ if table.concat(lines):lower():find('rebol') then
+ vim.bo[bufnr].filetype = 'rebol'
return
end
for _, line in ipairs(lines) do
-- R has # comments
- if line:find("^%s*#") then
- vim.bo[bufnr].filetype = "r"
+ if line:find('^%s*#') then
+ vim.bo[bufnr].filetype = 'r'
return
end
-- Rexx has /* comments */
- if line:find("^%s*/%*") then
- vim.bo[bufnr].filetype = "rexx"
+ if line:find('^%s*/%*') then
+ vim.bo[bufnr].filetype = 'rexx'
return
end
end
@@ -303,14 +303,14 @@ function M.r(bufnr)
vim.bo[bufnr].filetype = vim.g.filetype_r
else
-- Rexx used to be the default, but R appears to be much more popular.
- vim.bo[bufnr].filetype = "r"
+ vim.bo[bufnr].filetype = 'r'
end
end
function M.redif(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 5)) do
- if line:lower():find("^template%-type:") then
- vim.bo[bufnr].filetype = "redif"
+ if line:lower():find('^template%-type:') then
+ vim.bo[bufnr].filetype = 'redif'
end
end
end
@@ -321,24 +321,29 @@ function M.rules(path, bufnr) end
-- detection between scala and SuperCollider
function M.sc(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 25)) do
- if findany(line, { "[A-Za-z0-9]*%s:%s[A-Za-z0-9]", "var%s<", "classvar%s<", "%^this.*", "|%w*|", "%+%s%w*%s{", "%*ar%s" }) then
- vim.bo[bufnr].filetype = "supercollider"
+ if
+ findany(
+ line,
+ { '[A-Za-z0-9]*%s:%s[A-Za-z0-9]', 'var%s<', 'classvar%s<', '%^this.*', '|%w*|', '%+%s%w*%s{', '%*ar%s' }
+ )
+ then
+ vim.bo[bufnr].filetype = 'supercollider'
return
end
end
- vim.bo[bufnr].filetype = "scala"
+ vim.bo[bufnr].filetype = 'scala'
end
-- This function checks the first line of file extension "scd" to resolve
-- detection between scdoc and SuperCollider
function M.scd(bufnr)
- local first = "^%S+%(%d[0-9A-Za-z]*%)"
+ local first = '^%S+%(%d[0-9A-Za-z]*%)'
local opt = [[%s+"[^"]*"]]
local line = getlines(bufnr, 1)
- if findany(line, { first .. "$", first .. opt .. "$", first .. opt .. opt .. "$" }) then
- vim.bo[bufnr].filetype = "scdoc"
+ if findany(line, { first .. '$', first .. opt .. '$', first .. opt .. opt .. '$' }) then
+ vim.bo[bufnr].filetype = 'scdoc'
else
- vim.bo[bufnr].filetype = "supercollider"
+ vim.bo[bufnr].filetype = 'supercollider'
end
end
@@ -350,7 +355,7 @@ function M.sql(bufnr)
if vim.g.filetype_sql then
vim.bo[bufnr].filetype = vim.g.filetype_sql
else
- vim.bo[bufnr].filetype = "sql"
+ vim.bo[bufnr].filetype = 'sql'
end
end
@@ -365,46 +370,46 @@ function M.tf(bufnr)
for _, line in ipairs(getlines(bufnr, 1, -1)) do
-- Assume terraform file on a non-empty line (not whitespace-only)
-- and when the first non-whitespace character is not a ; or /
- if not line:find("^%s*$") and not line:find("^%s*[;/]") then
- vim.bo[bufnr].filetype = "terraform"
+ if not line:find('^%s*$') and not line:find('^%s*[;/]') then
+ vim.bo[bufnr].filetype = 'terraform'
return
end
end
- vim.bo[bufnr].filetype = "tf"
+ vim.bo[bufnr].filetype = 'tf'
end
function M.xml(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 100)) do
line = line:lower()
- local is_docbook4 = line:find("<!doctype.*docbook")
+ local is_docbook4 = line:find('<!doctype.*docbook')
local is_docbook5 = line:find([[ xmlns="http://docbook.org/ns/docbook"]])
if is_docbook4 or is_docbook5 then
- vim.b[bufnr].docbk_type = "xml"
+ vim.b[bufnr].docbk_type = 'xml'
vim.b[bufnr].docbk_ver = is_docbook4 and 4 or 5
- vim.bo[bufnr].filetype = "docbk"
+ vim.bo[bufnr].filetype = 'docbk'
return
end
if line:find([[xmlns:xbl="http://www.mozilla.org/xbl"]]) then
- vim.bo[bufnr].filetype = "xbl"
+ vim.bo[bufnr].filetype = 'xbl'
return
end
end
- vim.bo[bufnr].filetype = "xml"
+ vim.bo[bufnr].filetype = 'xml'
end
function M.y(bufnr)
for _, line in ipairs(getlines(bufnr, 1, 100)) do
- if line:find("^%s*%%") then
- vim.bo[bufnr].filetype = "yacc"
+ if line:find('^%s*%%') then
+ vim.bo[bufnr].filetype = 'yacc'
return
end
-- TODO: in the Vim regex, \> is used to match the end of the word after "class",
-- can this be omitted?
- if findany(line, { "^%s*#", "^%class", "^%s*#%s*include" }) then
- vim.bo[bufnr].filetype = "racc"
+ if findany(line, { '^%s*#', '^%class', '^%s*#%s*include' }) then
+ vim.bo[bufnr].filetype = 'racc'
end
end
- vim.bo[bufnr].filetype = "yacc"
+ vim.bo[bufnr].filetype = 'yacc'
end
-- luacheck: pop
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index 4105ef0675..22b67aee88 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -14,14 +14,14 @@ function M.create(higroup, hi_info, default)
local options = {}
-- TODO: Add validation
for k, v in pairs(hi_info) do
- table.insert(options, string.format("%s=%s", k, v))
+ table.insert(options, string.format('%s=%s', k, v))
end
- vim.cmd(string.format([[highlight %s %s %s]], default and "default" or "", higroup, table.concat(options, " ")))
+ vim.cmd(string.format([[highlight %s %s %s]], default and 'default' or '', higroup, table.concat(options, ' ')))
end
---@private
function M.link(higroup, link_to, force)
- vim.cmd(string.format([[highlight%s link %s %s]], force and "!" or " default", higroup, link_to))
+ vim.cmd(string.format([[highlight%s link %s %s]], force and '!' or ' default', higroup, link_to))
end
--- Highlight range between two positions
@@ -37,7 +37,7 @@ end
-- - priority number indicating priority of highlight (default priorities.user)
function M.range(bufnr, ns, higroup, start, finish, opts)
opts = opts or {}
- local regtype = opts.regtype or "v"
+ local regtype = opts.regtype or 'v'
local inclusive = opts.inclusive or false
local priority = opts.priority or M.priorities.user
@@ -63,7 +63,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
end
end
-local yank_ns = api.nvim_create_namespace("hlyank")
+local yank_ns = api.nvim_create_namespace('hlyank')
--- Highlight the yanked region
---
--- use from init.vim via
@@ -87,10 +87,10 @@ function M.on_yank(opts)
if t == nil then
return true
else
- return type(t) == "table"
+ return type(t) == 'table'
end
end,
- "a table or nil to configure options (see `:h highlight.on_yank`)",
+ 'a table or nil to configure options (see `:h highlight.on_yank`)',
},
})
opts = opts or {}
@@ -98,17 +98,17 @@ function M.on_yank(opts)
local on_macro = opts.on_macro or false
local on_visual = (opts.on_visual ~= false)
- if not on_macro and vim.fn.reg_executing() ~= "" then
+ if not on_macro and vim.fn.reg_executing() ~= '' then
return
end
- if event.operator ~= "y" or event.regtype == "" then
+ if event.operator ~= 'y' or event.regtype == '' then
return
end
if not on_visual and event.visual then
return
end
- local higroup = opts.higroup or "IncSearch"
+ local higroup = opts.higroup or 'IncSearch'
local timeout = opts.timeout or 150
local bufnr = api.nvim_get_current_buf()
diff --git a/runtime/lua/vim/inspect.lua b/runtime/lua/vim/inspect.lua
index b19c215dbb..c19e55fb37 100644
--- a/runtime/lua/vim/inspect.lua
+++ b/runtime/lua/vim/inspect.lua
@@ -1,7 +1,7 @@
local inspect = {
- _VERSION = "inspect.lua 3.1.0",
- _URL = "http://github.com/kikito/inspect.lua",
- _DESCRIPTION = "human-readable representations of tables",
+ _VERSION = 'inspect.lua 3.1.0',
+ _URL = 'http://github.com/kikito/inspect.lua',
+ _DESCRIPTION = 'human-readable representations of tables',
_LICENSE = [[
MIT LICENSE
@@ -30,12 +30,12 @@ local inspect = {
inspect.KEY = setmetatable({}, {
__tostring = function()
- return "inspect.KEY"
+ return 'inspect.KEY'
end,
})
inspect.METATABLE = setmetatable({}, {
__tostring = function()
- return "inspect.METATABLE"
+ return 'inspect.METATABLE'
end,
})
@@ -61,52 +61,52 @@ end
-- \a => '\\a', \0 => '\\0', 31 => '\31'
local shortControlCharEscapes = {
- ["\a"] = "\\a",
- ["\b"] = "\\b",
- ["\f"] = "\\f",
- ["\n"] = "\\n",
- ["\r"] = "\\r",
- ["\t"] = "\\t",
- ["\v"] = "\\v",
- ["\127"] = "\\127",
+ ['\a'] = '\\a',
+ ['\b'] = '\\b',
+ ['\f'] = '\\f',
+ ['\n'] = '\\n',
+ ['\r'] = '\\r',
+ ['\t'] = '\\t',
+ ['\v'] = '\\v',
+ ['\127'] = '\\127',
}
-local longControlCharEscapes = { ["\127"] = "\127" }
+local longControlCharEscapes = { ['\127'] = '\127' }
for i = 0, 31 do
local ch = char(i)
if not shortControlCharEscapes[ch] then
- shortControlCharEscapes[ch] = "\\" .. i
- longControlCharEscapes[ch] = fmt("\\%03d", i)
+ shortControlCharEscapes[ch] = '\\' .. i
+ longControlCharEscapes[ch] = fmt('\\%03d', i)
end
end
local function escape(str)
- return (gsub(gsub(gsub(str, "\\", "\\\\"), "(%c)%f[0-9]", longControlCharEscapes), "%c", shortControlCharEscapes))
+ return (gsub(gsub(gsub(str, '\\', '\\\\'), '(%c)%f[0-9]', longControlCharEscapes), '%c', shortControlCharEscapes))
end
local function isIdentifier(str)
- return type(str) == "string" and not not str:match("^[_%a][_%a%d]*$")
+ return type(str) == 'string' and not not str:match('^[_%a][_%a%d]*$')
end
local flr = math.floor
local function isSequenceKey(k, sequenceLength)
- return type(k) == "number" and flr(k) == k and 1 <= k and k <= sequenceLength
+ return type(k) == 'number' and flr(k) == k and 1 <= k and k <= sequenceLength
end
local defaultTypeOrders = {
- ["number"] = 1,
- ["boolean"] = 2,
- ["string"] = 3,
- ["table"] = 4,
- ["function"] = 5,
- ["userdata"] = 6,
- ["thread"] = 7,
+ ['number'] = 1,
+ ['boolean'] = 2,
+ ['string'] = 3,
+ ['table'] = 4,
+ ['function'] = 5,
+ ['userdata'] = 6,
+ ['thread'] = 7,
}
local function sortKeys(a, b)
local ta, tb = type(a), type(b)
-- strings and numbers are sorted numerically/alphabetically
- if ta == tb and (ta == "string" or ta == "number") then
+ if ta == tb and (ta == 'string' or ta == 'number') then
return a < b
end
@@ -137,7 +137,7 @@ local function getKeys(t)
end
local function countCycles(x, cycles)
- if type(x) == "table" then
+ if type(x) == 'table' then
if cycles[x] then
cycles[x] = cycles[x] + 1
else
@@ -173,7 +173,7 @@ local function processRecursive(process, item, path, visited)
end
local processed = process(item, path)
- if type(processed) == "table" then
+ if type(processed) == 'table' then
local processedCopy = {}
visited[item] = processedCopy
local processedKey
@@ -186,7 +186,7 @@ local function processRecursive(process, item, path, visited)
end
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
- if type(mt) ~= "table" then
+ if type(mt) ~= 'table' then
mt = nil
end
setmetatable(processedCopy, mt)
@@ -222,27 +222,27 @@ end
function Inspector:putValue(v)
local buf = self.buf
local tv = type(v)
- if tv == "string" then
+ if tv == 'string' then
puts(buf, smartQuote(escape(v)))
elseif
- tv == "number"
- or tv == "boolean"
- or tv == "nil"
- or tv == "cdata"
- or tv == "ctype"
+ tv == 'number'
+ or tv == 'boolean'
+ or tv == 'nil'
+ or tv == 'cdata'
+ or tv == 'ctype'
or (vim and v == vim.NIL)
then
puts(buf, tostring(v))
- elseif tv == "table" and not self.ids[v] then
+ elseif tv == 'table' and not self.ids[v] then
local t = v
if t == inspect.KEY or t == inspect.METATABLE then
puts(buf, tostring(t))
elseif self.level >= self.depth then
- puts(buf, "{...}")
+ puts(buf, '{...}')
else
if self.cycles[t] > 1 then
- puts(buf, fmt("<%d>", self:getId(t)))
+ puts(buf, fmt('<%d>', self:getId(t)))
end
local keys, keysLen, seqLen = getKeys(t)
@@ -253,15 +253,15 @@ function Inspector:putValue(v)
return
end
- puts(buf, "{")
+ puts(buf, '{')
self.level = self.level + 1
for i = 1, seqLen + keysLen do
if i > 1 then
- puts(buf, ",")
+ puts(buf, ',')
end
if i <= seqLen then
- puts(buf, " ")
+ puts(buf, ' ')
self:putValue(t[i])
else
local k = keys[i - seqLen]
@@ -269,36 +269,36 @@ function Inspector:putValue(v)
if isIdentifier(k) then
puts(buf, k)
else
- puts(buf, "[")
+ puts(buf, '[')
self:putValue(k)
- puts(buf, "]")
+ puts(buf, ']')
end
- puts(buf, " = ")
+ puts(buf, ' = ')
self:putValue(t[k])
end
end
- if type(mt) == "table" then
+ if type(mt) == 'table' then
if seqLen + keysLen > 0 then
- puts(buf, ",")
+ puts(buf, ',')
end
tabify(self)
- puts(buf, "<metatable> = ")
+ puts(buf, '<metatable> = ')
self:putValue(mt)
end
self.level = self.level - 1
- if keysLen > 0 or type(mt) == "table" then
+ if keysLen > 0 or type(mt) == 'table' then
tabify(self)
elseif seqLen > 0 then
- puts(buf, " ")
+ puts(buf, ' ')
end
- puts(buf, "}")
+ puts(buf, '}')
end
else
- puts(buf, fmt("<%s %d>", tv, self:getId(v)))
+ puts(buf, fmt('<%s %d>', tv, self:getId(v)))
end
end
@@ -306,8 +306,8 @@ function inspect.inspect(root, options)
options = options or {}
local depth = options.depth or math.huge
- local newline = options.newline or "\n"
- local indent = options.indent or " "
+ local newline = options.newline or '\n'
+ local indent = options.indent or ' '
local process = options.process
if process then
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index d07232f52f..f4c2b507a9 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -49,20 +49,20 @@ local keymap = {}
--- Default `false`.
---@see |nvim_set_keymap()|
function keymap.set(mode, lhs, rhs, opts)
- vim.validate {
- mode = {mode, {'s', 't'}},
- lhs = {lhs, 's'},
- rhs = {rhs, {'s', 'f'}},
- opts = {opts, 't', true}
- }
+ vim.validate({
+ mode = { mode, { 's', 't' } },
+ lhs = { lhs, 's' },
+ rhs = { rhs, { 's', 'f' } },
+ opts = { opts, 't', true },
+ })
opts = vim.deepcopy(opts) or {}
- local is_rhs_luaref = type(rhs) == "function"
- mode = type(mode) == 'string' and {mode} or mode
+ local is_rhs_luaref = type(rhs) == 'function'
+ mode = type(mode) == 'string' and { mode } or mode
if is_rhs_luaref and opts.expr then
local user_rhs = rhs
- rhs = function ()
+ rhs = function()
local res = user_rhs()
if res == nil then
-- TODO(lewis6991): Handle this in C?
@@ -118,14 +118,14 @@ end
---@see |vim.keymap.set()|
---
function keymap.del(modes, lhs, opts)
- vim.validate {
- mode = {modes, {'s', 't'}},
- lhs = {lhs, 's'},
- opts = {opts, 't', true}
- }
+ vim.validate({
+ mode = { modes, { 's', 't' } },
+ lhs = { lhs, 's' },
+ opts = { opts, 't', true },
+ })
opts = opts or {}
- modes = type(modes) == 'string' and {modes} or modes
+ modes = type(modes) == 'string' and { modes } or modes
local buffer = false
if opts.buffer ~= nil then
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index a541b63ee9..e99a7c282c 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -1,58 +1,58 @@
local if_nil = vim.F.if_nil
-local default_handlers = require 'vim.lsp.handlers'
-local log = require 'vim.lsp.log'
-local lsp_rpc = require 'vim.lsp.rpc'
-local protocol = require 'vim.lsp.protocol'
-local util = require 'vim.lsp.util'
-local sync = require 'vim.lsp.sync'
+local default_handlers = require('vim.lsp.handlers')
+local log = require('vim.lsp.log')
+local lsp_rpc = require('vim.lsp.rpc')
+local protocol = require('vim.lsp.protocol')
+local util = require('vim.lsp.util')
+local sync = require('vim.lsp.sync')
local vim = vim
-local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option
- = vim.api.nvim_err_writeln, vim.api.nvim_buf_get_lines, vim.api.nvim_command, vim.api.nvim_buf_get_option
+local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option =
+ vim.api.nvim_err_writeln, vim.api.nvim_buf_get_lines, vim.api.nvim_command, vim.api.nvim_buf_get_option
local uv = vim.loop
local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend
local validate = vim.validate
local lsp = {
- protocol = protocol;
+ protocol = protocol,
- handlers = default_handlers;
+ handlers = default_handlers,
- buf = require'vim.lsp.buf';
- diagnostic = require'vim.lsp.diagnostic';
- codelens = require'vim.lsp.codelens';
- util = util;
+ buf = require('vim.lsp.buf'),
+ diagnostic = require('vim.lsp.diagnostic'),
+ codelens = require('vim.lsp.codelens'),
+ util = util,
-- Allow raw RPC access.
- rpc = lsp_rpc;
+ rpc = lsp_rpc,
-- Export these directly from rpc.
- rpc_response_error = lsp_rpc.rpc_response_error;
+ rpc_response_error = lsp_rpc.rpc_response_error,
}
-- maps request name to the required server_capability in the client.
lsp._request_name_to_capability = {
- ['textDocument/hover'] = { 'hoverProvider' };
- ['textDocument/signatureHelp'] = { 'signatureHelpProvider' };
- ['textDocument/definition'] = { 'definitionProvider' };
- ['textDocument/implementation'] = { 'implementationProvider' };
- ['textDocument/declaration'] = { 'declarationProvider' };
- ['textDocument/typeDefinition'] = { 'typeDefinitionProvider' };
- ['textDocument/documentSymbol'] = { 'documentSymbolProvider' };
- ['textDocument/prepareCallHierarchy'] = { 'callHierarchyProvider' };
- ['textDocument/rename'] = { 'renameProvider' };
- ['textDocument/prepareRename'] = { 'renameProvider', 'prepareProvider'} ;
- ['textDocument/codeAction'] = { 'codeActionProvider' };
- ['textDocument/codeLens'] = { 'codeLensProvider' };
- ['codeLens/resolve'] = { 'codeLensProvider', 'resolveProvider' };
- ['workspace/executeCommand'] = { 'executeCommandProvider' };
- ['workspace/symbol'] = { 'workspaceSymbolProvider' };
- ['textDocument/references'] = { 'referencesProvider' };
- ['textDocument/rangeFormatting'] = { 'documentRangeFormattingProvider' };
- ['textDocument/formatting'] = { 'documentFormattingProvider' };
- ['textDocument/completion'] = { 'completionProvider' };
- ['textDocument/documentHighlight'] = { 'documentHighlightProvider' };
+ ['textDocument/hover'] = { 'hoverProvider' },
+ ['textDocument/signatureHelp'] = { 'signatureHelpProvider' },
+ ['textDocument/definition'] = { 'definitionProvider' },
+ ['textDocument/implementation'] = { 'implementationProvider' },
+ ['textDocument/declaration'] = { 'declarationProvider' },
+ ['textDocument/typeDefinition'] = { 'typeDefinitionProvider' },
+ ['textDocument/documentSymbol'] = { 'documentSymbolProvider' },
+ ['textDocument/prepareCallHierarchy'] = { 'callHierarchyProvider' },
+ ['textDocument/rename'] = { 'renameProvider' },
+ ['textDocument/prepareRename'] = { 'renameProvider', 'prepareProvider' },
+ ['textDocument/codeAction'] = { 'codeActionProvider' },
+ ['textDocument/codeLens'] = { 'codeLensProvider' },
+ ['codeLens/resolve'] = { 'codeLensProvider', 'resolveProvider' },
+ ['workspace/executeCommand'] = { 'executeCommandProvider' },
+ ['workspace/symbol'] = { 'workspaceSymbolProvider' },
+ ['textDocument/references'] = { 'referencesProvider' },
+ ['textDocument/rangeFormatting'] = { 'documentRangeFormattingProvider' },
+ ['textDocument/formatting'] = { 'documentFormattingProvider' },
+ ['textDocument/completion'] = { 'completionProvider' },
+ ['textDocument/documentHighlight'] = { 'documentHighlightProvider' },
}
-- TODO improve handling of scratch buffers with LSP attached.
@@ -62,8 +62,8 @@ lsp._request_name_to_capability = {
---
---@param {...} (List of strings) List to write to the buffer
local function err_message(...)
- nvim_err_writeln(table.concat(vim.tbl_flatten{...}))
- nvim_command("redraw")
+ nvim_err_writeln(table.concat(vim.tbl_flatten({ ... })))
+ nvim_command('redraw')
end
---@private
@@ -73,7 +73,7 @@ end
---buffer if not given.
---@returns bufnr (number) Number of requested buffer
local function resolve_bufnr(bufnr)
- validate { bufnr = { bufnr, 'n', true } }
+ validate({ bufnr = { bufnr, 'n', true } })
if bufnr == nil or bufnr == 0 then
return vim.api.nvim_get_current_buf()
end
@@ -85,7 +85,10 @@ end
--- supported in any of the servers registered for the current buffer.
---@param method (string) name of the method
function lsp._unsupported_method(method)
- local msg = string.format("method %s is not supported by any of the servers registered for the current buffer", method)
+ local msg = string.format(
+ 'method %s is not supported by any of the servers registered for the current buffer',
+ method
+ )
log.warn(msg)
return msg
end
@@ -96,23 +99,29 @@ end
---@param filename (string) path to check
---@returns true if {filename} exists and is a directory, false otherwise
local function is_dir(filename)
- validate{filename={filename,'s'}}
+ validate({ filename = { filename, 's' } })
local stat = uv.fs_stat(filename)
return stat and stat.type == 'directory' or false
end
-local wait_result_reason = { [-1] = "timeout"; [-2] = "interrupted"; [-3] = "error" }
+local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' }
local valid_encodings = {
- ["utf-8"] = 'utf-8'; ["utf-16"] = 'utf-16'; ["utf-32"] = 'utf-32';
- ["utf8"] = 'utf-8'; ["utf16"] = 'utf-16'; ["utf32"] = 'utf-32';
- UTF8 = 'utf-8'; UTF16 = 'utf-16'; UTF32 = 'utf-32';
+ ['utf-8'] = 'utf-8',
+ ['utf-16'] = 'utf-16',
+ ['utf-32'] = 'utf-32',
+ ['utf8'] = 'utf-8',
+ ['utf16'] = 'utf-16',
+ ['utf32'] = 'utf-32',
+ UTF8 = 'utf-8',
+ UTF16 = 'utf-16',
+ UTF32 = 'utf-32',
}
local format_line_ending = {
- ["unix"] = '\n',
- ["dos"] = '\r\n',
- ["mac"] = '\r',
+ ['unix'] = '\n',
+ ['dos'] = '\r\n',
+ ['mac'] = '\r',
}
---@private
@@ -138,10 +147,10 @@ local uninitialized_clients = {}
---@private
local function for_each_buffer_client(bufnr, fn, restrict_client_ids)
- validate {
- fn = { fn, 'f' };
- restrict_client_ids = { restrict_client_ids, 't' , true};
- }
+ validate({
+ fn = { fn, 'f' },
+ restrict_client_ids = { restrict_client_ids, 't', true },
+ })
bufnr = resolve_bufnr(bufnr)
local client_ids = all_buffer_active_clients[bufnr]
if not client_ids or tbl_isempty(client_ids) then
@@ -169,9 +178,13 @@ end
-- Error codes to be used with `on_error` from |vim.lsp.start_client|.
-- Can be used to look up the string from a the number or the number
-- from the string.
-lsp.client_errors = tbl_extend("error", lsp_rpc.client_errors, vim.tbl_add_reverse_lookup {
- ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1;
-})
+lsp.client_errors = tbl_extend(
+ 'error',
+ lsp_rpc.client_errors,
+ vim.tbl_add_reverse_lookup({
+ ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1,
+ })
+)
---@private
--- Normalizes {encoding} to valid LSP encoding names.
@@ -179,11 +192,11 @@ lsp.client_errors = tbl_extend("error", lsp_rpc.client_errors, vim.tbl_add_rever
---@param encoding (string) Encoding to normalize
---@returns (string) normalized encoding name
local function validate_encoding(encoding)
- validate {
- encoding = { encoding, 's' };
- }
+ validate({
+ encoding = { encoding, 's' },
+ })
return valid_encodings[encoding:lower()]
- or error(string.format("Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", encoding))
+ or error(string.format("Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", encoding))
end
---@internal
@@ -194,16 +207,19 @@ end
---@returns (string) the command
---@returns (list of strings) its arguments
function lsp._cmd_parts(input)
- vim.validate{cmd={
+ vim.validate({ cmd = {
input,
- function() return vim.tbl_islist(input) end,
- "list"}}
+ function()
+ return vim.tbl_islist(input)
+ end,
+ 'list',
+ } })
local cmd = input[1]
local cmd_args = {}
-- Don't mutate our input.
for i, v in ipairs(input) do
- vim.validate{["cmd argument"]={v, "s"}}
+ vim.validate({ ['cmd argument'] = { v, 's' } })
if i > 1 then
table.insert(cmd_args, v)
end
@@ -233,31 +249,29 @@ end
---
---@see |vim.lsp.start_client()|
local function validate_client_config(config)
- validate {
- config = { config, 't' };
- }
- validate {
- handlers = { config.handlers, "t", true };
- capabilities = { config.capabilities, "t", true };
- cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" };
- cmd_env = { config.cmd_env, "t", true };
- detached = { config.detached, "b", true };
- name = { config.name, 's', true };
- on_error = { config.on_error, "f", true };
- on_exit = { config.on_exit, "f", true };
- on_init = { config.on_init, "f", true };
- settings = { config.settings, "t", true };
- commands = { config.commands, 't', true };
- before_init = { config.before_init, "f", true };
- offset_encoding = { config.offset_encoding, "s", true };
- flags = { config.flags, "t", true };
- get_language_id = { config.get_language_id, "f", true };
- }
+ validate({
+ config = { config, 't' },
+ })
+ validate({
+ handlers = { config.handlers, 't', true },
+ capabilities = { config.capabilities, 't', true },
+ cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' },
+ cmd_env = { config.cmd_env, 't', true },
+ detached = { config.detached, 'b', true },
+ name = { config.name, 's', true },
+ on_error = { config.on_error, 'f', true },
+ on_exit = { config.on_exit, 'f', true },
+ on_init = { config.on_init, 'f', true },
+ settings = { config.settings, 't', true },
+ commands = { config.commands, 't', true },
+ before_init = { config.before_init, 'f', true },
+ offset_encoding = { config.offset_encoding, 's', true },
+ flags = { config.flags, 't', true },
+ get_language_id = { config.get_language_id, 'f', true },
+ })
assert(
- (not config.flags
- or not config.flags.debounce_text_changes
- or type(config.flags.debounce_text_changes) == 'number'),
- "flags.debounce_text_changes must be a number with the debounce time in milliseconds"
+ (not config.flags or not config.flags.debounce_text_changes or type(config.flags.debounce_text_changes) == 'number'),
+ 'flags.debounce_text_changes must be a number with the debounce time in milliseconds'
)
local cmd, cmd_args = lsp._cmd_parts(config.cmd)
@@ -267,9 +281,9 @@ local function validate_client_config(config)
end
return {
- cmd = cmd;
- cmd_args = cmd_args;
- offset_encoding = offset_encoding;
+ cmd = cmd,
+ cmd_args = cmd_args,
+ offset_encoding = offset_encoding,
}
end
@@ -329,14 +343,15 @@ do
function changetracking.init(client, bufnr)
local use_incremental_sync = (
if_nil(client.config.flags.allow_incremental_sync, true)
- and vim.tbl_get(client.server_capabilities, "textDocumentSync", "change") == protocol.TextDocumentSyncKind.Incremental
+ and vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change')
+ == protocol.TextDocumentSyncKind.Incremental
)
local state = state_by_client[client.id]
if not state then
state = {
- buffers = {};
+ buffers = {},
debounce = client.config.flags.debounce_text_changes or 150,
- use_incremental_sync = use_incremental_sync;
+ use_incremental_sync = use_incremental_sync,
}
state_by_client[client.id] = state
end
@@ -405,7 +420,6 @@ do
---@private
function changetracking.prepare(bufnr, firstline, lastline, new_lastline)
local incremental_changes = function(client, buf_state)
-
local prev_lines = buf_state.lines
local curr_lines = buf_state.lines_tmp
@@ -426,7 +440,14 @@ do
local line_ending = buf_get_line_ending(bufnr)
local incremental_change = sync.compute_diff(
- buf_state.lines, curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending)
+ buf_state.lines,
+ curr_lines,
+ firstline,
+ lastline,
+ new_lastline,
+ client.offset_encoding or 'utf-16',
+ line_ending
+ )
-- Double-buffering of lines tables is used to reduce the load on the garbage collector.
-- At this point the prev_lines table is useless, but its internal storage has already been allocated,
@@ -443,12 +464,14 @@ do
end
local full_changes = once(function()
return {
- text = buf_get_full_text(bufnr);
- };
+ text = buf_get_full_text(bufnr),
+ }
end)
local uri = vim.uri_from_bufnr(bufnr)
return function(client)
- if vim.tbl_get(client.server_capabilities, "textDocumentSync", "change") == protocol.TextDocumentSyncKind.None then
+ if
+ vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') == protocol.TextDocumentSyncKind.None
+ then
return
end
local state = state_by_client[client.id]
@@ -467,7 +490,7 @@ do
return
end
local changes = state.use_incremental_sync and buf_state.pending_changes or { full_changes() }
- client.notify("textDocument/didChange", {
+ client.notify('textDocument/didChange', {
textDocument = {
uri = uri,
version = util.buf_versions[bufnr],
@@ -519,7 +542,6 @@ do
end
end
-
---@private
--- Default handler for the 'textDocument/didOpen' LSP notification.
---
@@ -527,7 +549,7 @@ end
---@param client Client object
local function text_document_did_open_handler(bufnr, client)
changetracking.init(client, bufnr)
- if not vim.tbl_get(client.server_capabilities, "textDocumentSync", "openClose") then
+ if not vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
return
end
if not vim.api.nvim_buf_is_loaded(bufnr) then
@@ -537,11 +559,11 @@ local function text_document_did_open_handler(bufnr, client)
local params = {
textDocument = {
- version = 0;
- uri = vim.uri_from_bufnr(bufnr);
- languageId = client.config.get_language_id(bufnr, filetype);
- text = buf_get_full_text(bufnr);
- }
+ version = 0,
+ uri = vim.uri_from_bufnr(bufnr),
+ languageId = client.config.get_language_id(bufnr, filetype),
+ text = buf_get_full_text(bufnr),
+ },
}
client.notify('textDocument/didOpen', params)
util.buf_versions[bufnr] = params.textDocument.version
@@ -763,13 +785,15 @@ function lsp.start_client(config)
-- By default, get_language_id just returns the exact filetype it is passed.
-- It is possible to pass in something that will calculate a different filetype,
-- to be sent by the client.
- config.get_language_id = config.get_language_id or function(_, filetype) return filetype end
+ config.get_language_id = config.get_language_id or function(_, filetype)
+ return filetype
+ end
local client_id = next_client_id()
local handlers = config.handlers or {}
local name = config.name or tostring(client_id)
- local log_prefix = string.format("LSP[%s]", name)
+ local log_prefix = string.format('LSP[%s]', name)
local dispatch = {}
@@ -794,7 +818,7 @@ function lsp.start_client(config)
local handler = resolve_handler(method)
if handler then
-- Method name is provided here for convenience.
- handler(nil, params, {method=method, client_id=client_id})
+ handler(nil, params, { method = method, client_id = client_id })
end
end
@@ -807,10 +831,10 @@ function lsp.start_client(config)
local _ = log.trace() and log.trace('server_request', method, params)
local handler = resolve_handler(method)
if handler then
- local _ = log.trace() and log.trace("server_request: found handler for", method)
- return handler(nil, params, {method=method, client_id=client_id})
+ local _ = log.trace() and log.trace('server_request: found handler for', method)
+ return handler(nil, params, { method = method, client_id = client_id })
end
- local _ = log.warn() and log.warn("server_request: no handler found for", method)
+ local _ = log.warn() and log.warn('server_request: no handler found for', method)
return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
end
@@ -822,12 +846,12 @@ function lsp.start_client(config)
---@see |vim.lsp.rpc.client_errors| for possible errors. Use
---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
function dispatch.on_error(code, err)
- local _ = log.error() and log.error(log_prefix, "on_error", { code = lsp.client_errors[code], err = err })
+ local _ = log.error() and log.error(log_prefix, 'on_error', { code = lsp.client_errors[code], err = err })
err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err))
if config.on_error then
local status, usererr = pcall(config.on_error, code, err)
if not status then
- local _ = log.error() and log.error(log_prefix, "user on_error failed", { err = usererr })
+ local _ = log.error() and log.error(log_prefix, 'user on_error failed', { err = usererr })
err_message(log_prefix, ' user on_error failed: ', tostring(usererr))
end
end
@@ -853,7 +877,7 @@ function lsp.start_client(config)
end
if code ~= 0 or (signal ~= 0 and signal ~= 15) then
- local msg = string.format("Client %s quit with exit code %s and signal %s", client_id, code, signal)
+ local msg = string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
vim.schedule(function()
vim.notify(msg, vim.log.levels.WARN)
end)
@@ -862,38 +886,41 @@ function lsp.start_client(config)
-- Start the RPC client.
local rpc = lsp_rpc.start(cmd, cmd_args, dispatch, {
- cwd = config.cmd_cwd;
- env = config.cmd_env;
- detached = config.detached;
+ cwd = config.cmd_cwd,
+ env = config.cmd_env,
+ detached = config.detached,
})
-- Return nil if client fails to start
- if not rpc then return end
+ if not rpc then
+ return
+ end
local client = {
- id = client_id;
- name = name;
- rpc = rpc;
- offset_encoding = offset_encoding;
- config = config;
- attached_buffers = {};
+ id = client_id,
+ name = name,
+ rpc = rpc,
+ offset_encoding = offset_encoding,
+ config = config,
+ attached_buffers = {},
- handlers = handlers;
- commands = config.commands or {};
+ handlers = handlers,
+ commands = config.commands or {},
- requests = {};
+ requests = {},
-- for $/progress report
- messages = { name = name, messages = {}, progress = {}, status = {} };
+ messages = { name = name, messages = {}, progress = {}, status = {} },
}
-
-- Store the uninitialized_clients for cleanup in case we exit before initialize finishes.
- uninitialized_clients[client_id] = client;
+ uninitialized_clients[client_id] = client
---@private
local function initialize()
local valid_traces = {
- off = 'off'; messages = 'messages'; verbose = 'verbose';
+ off = 'off',
+ messages = 'messages',
+ verbose = 'verbose',
}
local version = vim.version()
@@ -902,10 +929,12 @@ function lsp.start_client(config)
local root_path
if config.workspace_folders or config.root_dir then
if config.root_dir and not config.workspace_folders then
- workspace_folders = {{
- uri = vim.uri_from_fname(config.root_dir);
- name = string.format("%s", config.root_dir);
- }};
+ workspace_folders = {
+ {
+ uri = vim.uri_from_fname(config.root_dir),
+ name = string.format('%s', config.root_dir),
+ },
+ }
else
workspace_folders = config.workspace_folders
end
@@ -922,41 +951,41 @@ function lsp.start_client(config)
-- the process has not been started by another process. If the parent
-- process is not alive then the server should exit (see exit notification)
-- its process.
- processId = uv.getpid();
+ processId = uv.getpid(),
-- Information about the client
-- since 3.15.0
clientInfo = {
- name = "Neovim",
- version = string.format("%s.%s.%s", version.major, version.minor, version.patch)
- };
+ name = 'Neovim',
+ version = string.format('%s.%s.%s', version.major, version.minor, version.patch),
+ },
-- The rootPath of the workspace. Is null if no folder is open.
--
-- @deprecated in favour of rootUri.
- rootPath = root_path or vim.NIL;
+ rootPath = root_path or vim.NIL,
-- The rootUri of the workspace. Is null if no folder is open. If both
-- `rootPath` and `rootUri` are set `rootUri` wins.
- rootUri = root_uri or vim.NIL;
+ rootUri = root_uri or vim.NIL,
-- The workspace folders configured in the client when the server starts.
-- This property is only available if the client supports workspace folders.
-- It can be `null` if the client supports workspace folders but none are
-- configured.
- workspaceFolders = workspace_folders or vim.NIL;
+ workspaceFolders = workspace_folders or vim.NIL,
-- User provided initialization options.
- initializationOptions = config.init_options;
+ initializationOptions = config.init_options,
-- The capabilities provided by the client (editor or tool)
- capabilities = config.capabilities or protocol.make_client_capabilities();
+ capabilities = config.capabilities or protocol.make_client_capabilities(),
-- The initial trace setting. If omitted trace is disabled ("off").
-- trace = "off" | "messages" | "verbose";
- trace = valid_traces[config.trace] or 'off';
+ trace = valid_traces[config.trace] or 'off',
}
if config.before_init then
-- TODO(ashkan) handle errors here.
pcall(config.before_init, initialize_params, config)
end
- local _ = log.trace() and log.trace(log_prefix, "initialize_params", initialize_params)
+ local _ = log.trace() and log.trace(log_prefix, 'initialize_params', initialize_params)
rpc.request('initialize', initialize_params, function(init_err, result)
assert(not init_err, tostring(init_err))
- assert(result, "server sent empty result")
+ assert(result, 'server sent empty result')
rpc.notify('initialized', vim.empty_dict())
client.initialized = true
uninitialized_clients[client_id] = nil
@@ -973,10 +1002,13 @@ function lsp.start_client(config)
local mt = {}
mt.__index = function(table, key)
if key == 'resolved_capabilities' then
- vim.notify_once("[LSP] Accessing client.resolved_capabilities is deprecated, " ..
- "update your plugins or configuration to access client.server_capabilities instead." ..
- "The new key/value pairs in server_capabilities directly match those " ..
- "defined in the language server protocol", vim.log.levels.WARN)
+ vim.notify_once(
+ '[LSP] Accessing client.resolved_capabilities is deprecated, '
+ .. 'update your plugins or configuration to access client.server_capabilities instead.'
+ .. 'The new key/value pairs in server_capabilities directly match those '
+ .. 'defined in the language server protocol',
+ vim.log.levels.WARN
+ )
rawset(table, key, protocol._resolve_capabilities_compat(client.server_capabilities))
return rawget(table, key)
else
@@ -1004,7 +1036,8 @@ function lsp.start_client(config)
pcall(handlers.on_error, lsp.client_errors.ON_INIT_CALLBACK_ERROR, err)
end
end
- local _ = log.info() and log.info(log_prefix, "server_capabilities", { server_capabilities = client.server_capabilities })
+ local _ = log.info()
+ and log.info(log_prefix, 'server_capabilities', { server_capabilities = client.server_capabilities })
-- Only assign after initialized.
active_clients[client_id] = client
@@ -1039,22 +1072,22 @@ function lsp.start_client(config)
function client.request(method, params, handler, bufnr)
if not handler then
handler = resolve_handler(method)
- or error(string.format("not found: %q request handler for client %q.", method, client.name))
+ or error(string.format('not found: %q request handler for client %q.', method, client.name))
end
-- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
changetracking.flush(client, bufnr)
bufnr = resolve_bufnr(bufnr)
- local _ = log.debug() and log.debug(log_prefix, "client.request", client_id, method, params, handler, bufnr)
+ local _ = log.debug() and log.debug(log_prefix, 'client.request', client_id, method, params, handler, bufnr)
local success, request_id = rpc.request(method, params, function(err, result)
- handler(err, result, {method=method, client_id=client_id, bufnr=bufnr, params=params})
+ handler(err, result, { method = method, client_id = client_id, bufnr = bufnr, params = params })
end, function(request_id)
client.requests[request_id] = nil
- nvim_command("doautocmd <nomodeline> User LspRequest")
+ nvim_command('doautocmd <nomodeline> User LspRequest')
end)
if success then
- client.requests[request_id] = { type='pending', bufnr=bufnr, method=method }
- nvim_command("doautocmd <nomodeline> User LspRequest")
+ client.requests[request_id] = { type = 'pending', bufnr = bufnr, method = method }
+ nvim_command('doautocmd <nomodeline> User LspRequest')
end
return success, request_id
@@ -1081,9 +1114,10 @@ function lsp.start_client(config)
request_result = { err = err, result = result }
end
- local success, request_id = client.request(method, params, _sync_handler,
- bufnr)
- if not success then return nil end
+ local success, request_id = client.request(method, params, _sync_handler, bufnr)
+ if not success then
+ return nil
+ end
local wait_result, reason = vim.wait(timeout_ms or 1000, function()
return request_result ~= nil
@@ -1118,13 +1152,13 @@ function lsp.start_client(config)
---@returns true if any client returns true; false otherwise
---@see |vim.lsp.client.notify()|
function client.cancel_request(id)
- validate{id = {id, 'n'}}
+ validate({ id = { id, 'n' } })
local request = client.requests[id]
if request and request.type == 'pending' then
request.type = 'cancel'
- nvim_command("doautocmd <nomodeline> User LspRequest")
+ nvim_command('doautocmd <nomodeline> User LspRequest')
end
- return rpc.notify("$/cancelRequest", { id = id })
+ return rpc.notify('$/cancelRequest', { id = id })
end
-- Track this so that we can escalate automatically if we've already tried a
@@ -1139,7 +1173,6 @@ function lsp.start_client(config)
---
---@param force (bool, optional)
function client.stop(force)
-
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
changetracking.reset(client_id)
for _, client_ids in pairs(all_buffer_active_clients) do
@@ -1150,7 +1183,7 @@ function lsp.start_client(config)
if handle:is_closing() then
return
end
- if force or (not client.initialized) or graceful_shutdown_failed then
+ if force or not client.initialized or graceful_shutdown_failed then
handle:kill(15)
return
end
@@ -1198,7 +1231,6 @@ end
local text_document_did_change_handler
do
text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline)
-
-- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
return true
@@ -1215,17 +1247,17 @@ function lsp._text_document_did_save_handler(bufnr)
local uri = vim.uri_from_bufnr(bufnr)
local text = once(buf_get_full_text)
for_each_buffer_client(bufnr, function(client)
- local save_capability = vim.tbl_get(client.server_capabilities, "textDocumentSync", "save")
+ local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save')
if save_capability then
local included_text
- if type(save_capability) == "table" and save_capability.includeText then
+ if type(save_capability) == 'table' and save_capability.includeText then
included_text = text(bufnr)
end
client.notify('textDocument/didSave', {
textDocument = {
- uri = uri;
- };
- text = included_text;
+ uri = uri,
+ },
+ text = included_text,
})
end
end)
@@ -1239,15 +1271,13 @@ end
---@param bufnr (number) Buffer handle, or 0 for current
---@param client_id (number) Client id
function lsp.buf_attach_client(bufnr, client_id)
- validate {
- bufnr = {bufnr, 'n', true};
- client_id = {client_id, 'n'};
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ client_id = { client_id, 'n' },
+ })
bufnr = resolve_bufnr(bufnr)
if not vim.api.nvim_buf_is_loaded(bufnr) then
- local _ = log.warn() and log.warn(
- string.format("buf_attach_client called on unloaded buffer (id: %d): ", bufnr)
- )
+ local _ = log.warn() and log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr))
return false
end
local buffer_client_ids = all_buffer_active_clients[bufnr]
@@ -1266,36 +1296,38 @@ function lsp.buf_attach_client(bufnr, client_id)
vim.api.nvim_exec(string.format(buf_did_save_autocommand, client_id, bufnr, bufnr), false)
-- First time, so attach and set up stuff.
vim.api.nvim_buf_attach(bufnr, false, {
- on_lines = text_document_did_change_handler;
+ on_lines = text_document_did_change_handler,
on_reload = function()
- local params = { textDocument = { uri = uri; } }
+ local params = { textDocument = { uri = uri } }
for_each_buffer_client(bufnr, function(client, _)
changetracking.reset_buf(client, bufnr)
- if vim.tbl_get(client.server_capabilities, "textDocumentSync", "openClose") then
+ if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
client.notify('textDocument/didClose', params)
end
text_document_did_open_handler(bufnr, client)
end)
- end;
+ end,
on_detach = function()
- local params = { textDocument = { uri = uri; } }
+ local params = { textDocument = { uri = uri } }
for_each_buffer_client(bufnr, function(client, _)
changetracking.reset_buf(client, bufnr)
- if vim.tbl_get(client.server_capabilities, "textDocumentSync", "openClose") then
+ if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
client.notify('textDocument/didClose', params)
end
end)
util.buf_versions[bufnr] = nil
all_buffer_active_clients[bufnr] = nil
- end;
+ end,
-- TODO if we know all of the potential clients ahead of time, then we
-- could conditionally set this.
-- utf_sizes = size_index > 1;
- utf_sizes = true;
+ utf_sizes = true,
})
end
- if buffer_client_ids[client_id] then return end
+ if buffer_client_ids[client_id] then
+ return
+ end
-- This is our first time attaching this client to this buffer.
buffer_client_ids[client_id] = true
@@ -1315,25 +1347,23 @@ end
---@param bufnr number Buffer handle, or 0 for current
---@param client_id number Client id
function lsp.buf_detach_client(bufnr, client_id)
- validate {
- bufnr = {bufnr, 'n', true};
- client_id = {client_id, 'n'};
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ client_id = { client_id, 'n' },
+ })
bufnr = resolve_bufnr(bufnr)
local client = lsp.get_client_by_id(client_id)
if not client or not client.attached_buffers[bufnr] then
- vim.notify(
- string.format('Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', client_id, bufnr)
- )
+ vim.notify(string.format('Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', client_id, bufnr))
return
end
changetracking.reset_buf(client, bufnr)
- if vim.tbl_get(client.server_capabilities, "textDocumentSync", "openClose") then
+ if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
local uri = vim.uri_from_bufnr(bufnr)
- local params = { textDocument = { uri = uri; } }
+ local params = { textDocument = { uri = uri } }
client.notify('textDocument/didClose', params)
end
@@ -1349,7 +1379,6 @@ function lsp.buf_detach_client(bufnr, client_id)
vim.diagnostic.reset(namespace, bufnr)
vim.notify(string.format('Detached buffer (id: %d) from client (id: %d)', bufnr, client_id))
-
end
--- Checks if a buffer is attached for a particular client.
@@ -1394,7 +1423,7 @@ end
---@param client_id client id or |vim.lsp.client| object, or list thereof
---@param force boolean (optional) shutdown forcefully
function lsp.stop_client(client_id, force)
- local ids = type(client_id) == 'table' and client_id or {client_id}
+ local ids = type(client_id) == 'table' and client_id or { client_id }
for _, id in ipairs(ids) do
if type(id) == 'table' and id.stop ~= nil then
id.stop(force)
@@ -1414,7 +1443,7 @@ function lsp.get_active_clients()
end
function lsp._vim_exit_handler()
- log.info("exit_handler", active_clients)
+ log.info('exit_handler', active_clients)
for _, client in pairs(uninitialized_clients) do
client.stop(true)
end
@@ -1466,8 +1495,7 @@ function lsp._vim_exit_handler()
end
end
-nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
-
+nvim_command('autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()')
--- Sends an async request for all active clients attached to the
--- buffer.
@@ -1483,11 +1511,11 @@ nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
--- - Function which can be used to cancel all the requests. You could instead
--- iterate all clients and call their `cancel_request()` methods.
function lsp.buf_request(bufnr, method, params, handler)
- validate {
- bufnr = { bufnr, 'n', true };
- method = { method, 's' };
- handler = { handler, 'f', true };
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ method = { method, 's' },
+ handler = { handler, 'f', true },
+ })
local supported_clients = {}
local method_supported = false
@@ -1501,18 +1529,18 @@ function lsp.buf_request(bufnr, method, params, handler)
-- if has client but no clients support the given method, notify the user
if not tbl_isempty(all_buffer_active_clients[resolve_bufnr(bufnr)] or {}) and not method_supported then
vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR)
- vim.api.nvim_command("redraw")
+ vim.api.nvim_command('redraw')
return {}, function() end
end
local client_request_ids = {}
for_each_buffer_client(bufnr, function(client, client_id, resolved_bufnr)
- local request_success, request_id = client.request(method, params, handler, resolved_bufnr)
- -- This could only fail if the client shut down in the time since we looked
- -- it up and we did the request, which should be rare.
- if request_success then
- client_request_ids[client_id] = request_id
- end
+ local request_success, request_id = client.request(method, params, handler, resolved_bufnr)
+ -- This could only fail if the client shut down in the time since we looked
+ -- it up and we did the request, which should be rare.
+ if request_success then
+ client_request_ids[client_id] = request_id
+ end
end, supported_clients)
local function _cancel_all_requests()
@@ -1543,7 +1571,7 @@ function lsp.buf_request_all(bufnr, method, params, callback)
local result_count = 0
local expected_result_count = 0
- local set_expected_result_count = once(function ()
+ local set_expected_result_count = once(function()
for_each_buffer_client(bufnr, function(client)
if client.supports_method(method) then
expected_result_count = expected_result_count + 1
@@ -1607,18 +1635,19 @@ end
---
---@returns true if any client returns true; false otherwise
function lsp.buf_notify(bufnr, method, params)
- validate {
- bufnr = { bufnr, 'n', true };
- method = { method, 's' };
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ method = { method, 's' },
+ })
local resp = false
for_each_buffer_client(bufnr, function(client, _client_id, _resolved_bufnr)
- if client.rpc.notify(method, params) then resp = true end
+ if client.rpc.notify(method, params) then
+ resp = true
+ end
end)
return resp
end
-
---@private
local function adjust_start_col(lnum, line, items, encoding)
local min_start_char = nil
@@ -1650,7 +1679,7 @@ end
--- - findstart=0: column where the completion starts, or -2 or -3
--- - findstart=1: list of matches (actually just calls |complete()|)
function lsp.omnifunc(findstart, base)
- local _ = log.debug() and log.debug("omnifunc.findstart", { findstart = findstart, base = base })
+ local _ = log.debug() and log.debug('omnifunc.findstart', { findstart = findstart, base = base })
local bufnr = resolve_bufnr()
local has_buffer_clients = not tbl_isempty(all_buffer_active_clients[bufnr] or {})
@@ -1663,12 +1692,12 @@ function lsp.omnifunc(findstart, base)
end
-- Then, perform standard completion request
- local _ = log.info() and log.info("base ", base)
+ local _ = log.info() and log.info('base ', base)
local pos = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
local line_to_cursor = line:sub(1, pos[2])
- local _ = log.trace() and log.trace("omnifunc.line", pos, line)
+ local _ = log.trace() and log.trace('omnifunc.line', pos, line)
-- Get the start position of the current keyword
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
@@ -1677,7 +1706,9 @@ function lsp.omnifunc(findstart, base)
local items = {}
lsp.buf_request(bufnr, 'textDocument/completion', params, function(err, result, ctx)
- if err or not result or vim.fn.mode() ~= "i" then return end
+ if err or not result or vim.fn.mode() ~= 'i' then
+ return
+ end
-- Completion response items may be relative to a position different than `textMatch`.
-- Concrete example, with sumneko/lua-language-server:
@@ -1723,7 +1754,7 @@ function lsp.formatexpr(opts)
opts = opts or {}
local timeout_ms = opts.timeout_ms or 500
- if vim.tbl_contains({'i', 'R', 'ic', 'ix'}, vim.fn.mode()) then
+ if vim.tbl_contains({ 'i', 'R', 'ic', 'ix' }, vim.fn.mode()) then
-- `formatexpr` is also called when exceeding `textwidth` in insert mode
-- fall back to internal formatting
return 1
@@ -1734,14 +1765,14 @@ function lsp.formatexpr(opts)
if start_line > 0 and end_line > 0 then
local params = {
- textDocument = util.make_text_document_params();
+ textDocument = util.make_text_document_params(),
range = {
- start = { line = start_line - 1; character = 0; };
- ["end"] = { line = end_line - 1; character = 0; };
- };
- };
+ start = { line = start_line - 1, character = 0 },
+ ['end'] = { line = end_line - 1, character = 0 },
+ },
+ }
params.options = util.make_formatting_params().options
- local client_results = vim.lsp.buf_request_sync(0, "textDocument/rangeFormatting", params, timeout_ms)
+ local client_results = vim.lsp.buf_request_sync(0, 'textDocument/rangeFormatting', params, timeout_ms)
-- Apply the text edits from one and only one of the clients.
for client_id, response in pairs(client_results) do
@@ -1785,11 +1816,11 @@ end
---@param bufnr (optional, number): Buffer handle, or 0 for current
function lsp.buf_get_clients(bufnr)
bufnr = resolve_bufnr(bufnr)
- local result = {}
- for_each_buffer_client(bufnr, function(client, client_id)
- result[client_id] = client
- end)
- return result
+ local result = {}
+ for_each_buffer_client(bufnr, function(client, client_id)
+ result[client_id] = client
+ end)
+ return result
end
-- Log level dictionary with reverse lookup as well.
@@ -1815,7 +1846,7 @@ function lsp.set_log_level(level)
if type(level) == 'string' or type(level) == 'number' then
log.set_level(level)
else
- error(string.format("Invalid log level: %q", level))
+ error(string.format('Invalid log level: %q', level))
end
end
@@ -1845,7 +1876,7 @@ end
---@param override_config (table) Table containing the keys to override behavior of the {handler}
function lsp.with(handler, override_config)
return function(err, result, ctx, config)
- return handler(err, result, ctx, vim.tbl_deep_extend("force", config or {}, override_config))
+ return handler(err, result, ctx, vim.tbl_deep_extend('force', config or {}, override_config))
end
end
@@ -1860,12 +1891,16 @@ function lsp._with_extend(name, options, user_config)
local resulting_config = {}
for k, v in pairs(user_config) do
if options[k] == nil then
- error(debug.traceback(string.format(
- "Invalid option for `%s`: %s. Valid options are:\n%s",
- name,
- k,
- vim.inspect(vim.tbl_keys(options))
- )))
+ error(
+ debug.traceback(
+ string.format(
+ 'Invalid option for `%s`: %s. Valid options are:\n%s',
+ name,
+ k,
+ vim.inspect(vim.tbl_keys(options))
+ )
+ )
+ )
end
resulting_config[k] = v
@@ -1880,7 +1915,6 @@ function lsp._with_extend(name, options, user_config)
return resulting_config
end
-
--- Registry for client side commands.
--- This is an extension point for plugins to handle custom commands which are
--- not part of the core language server protocol specification.
@@ -1902,12 +1936,11 @@ end
--- The second argument is the `ctx` of |lsp-handler|
lsp.commands = setmetatable({}, {
__newindex = function(tbl, key, value)
- assert(type(key) == 'string', "The key for commands in `vim.lsp.commands` must be a string")
- assert(type(value) == 'function', "Command added to `vim.lsp.commands` must be a function")
+ assert(type(key) == 'string', 'The key for commands in `vim.lsp.commands` must be a string')
+ assert(type(value) == 'function', 'Command added to `vim.lsp.commands` must be a function')
rawset(tbl, key, value)
- end;
+ end,
})
-
return lsp
-- vim:sw=2 ts=2 et
diff --git a/runtime/lua/vim/lsp/_snippet.lua b/runtime/lua/vim/lsp/_snippet.lua
index 0140b0aee3..28064f36e9 100644
--- a/runtime/lua/vim/lsp/_snippet.lua
+++ b/runtime/lua/vim/lsp/_snippet.lua
@@ -41,7 +41,7 @@ P.take_until = function(targets, specials)
parsed = true,
value = {
raw = table.concat(raw, ''),
- esc = table.concat(esc, '')
+ esc = table.concat(esc, ''),
},
pos = new_pos,
}
@@ -248,49 +248,67 @@ S.format = P.any(
capture_index = values[3],
}, Node)
end),
- P.map(P.seq(S.dollar, S.open, S.int, S.colon, S.slash, P.any(
- P.token('upcase'),
- P.token('downcase'),
- P.token('capitalize'),
- P.token('camelcase'),
- P.token('pascalcase')
- ), S.close), function(values)
- return setmetatable({
- type = Node.Type.FORMAT,
- capture_index = values[3],
- modifier = values[6],
- }, Node)
- end),
- P.map(P.seq(S.dollar, S.open, S.int, S.colon, P.any(
- P.seq(S.question, P.take_until({ ':' }, { '\\' }), S.colon, P.take_until({ '}' }, { '\\' })),
- P.seq(S.plus, P.take_until({ '}' }, { '\\' })),
- P.seq(S.minus, P.take_until({ '}' }, { '\\' }))
- ), S.close), function(values)
+ P.map(
+ P.seq(
+ S.dollar,
+ S.open,
+ S.int,
+ S.colon,
+ S.slash,
+ P.any(P.token('upcase'), P.token('downcase'), P.token('capitalize'), P.token('camelcase'), P.token('pascalcase')),
+ S.close
+ ),
+ function(values)
+ return setmetatable({
+ type = Node.Type.FORMAT,
+ capture_index = values[3],
+ modifier = values[6],
+ }, Node)
+ end
+ ),
+ P.map(
+ P.seq(
+ S.dollar,
+ S.open,
+ S.int,
+ S.colon,
+ P.any(
+ P.seq(S.question, P.take_until({ ':' }, { '\\' }), S.colon, P.take_until({ '}' }, { '\\' })),
+ P.seq(S.plus, P.take_until({ '}' }, { '\\' })),
+ P.seq(S.minus, P.take_until({ '}' }, { '\\' }))
+ ),
+ S.close
+ ),
+ function(values)
+ return setmetatable({
+ type = Node.Type.FORMAT,
+ capture_index = values[3],
+ if_text = values[5][2].esc,
+ else_text = (values[5][4] or {}).esc,
+ }, Node)
+ end
+ )
+)
+
+S.transform = P.map(
+ P.seq(
+ S.slash,
+ P.take_until({ '/' }, { '\\' }),
+ S.slash,
+ P.many(P.any(S.format, S.text({ '$', '/' }, { '\\' }))),
+ S.slash,
+ P.opt(P.pattern('[ig]+'))
+ ),
+ function(values)
return setmetatable({
- type = Node.Type.FORMAT,
- capture_index = values[3],
- if_text = values[5][2].esc,
- else_text = (values[5][4] or {}).esc,
+ type = Node.Type.TRANSFORM,
+ pattern = values[2].raw,
+ format = values[4],
+ option = values[6],
}, Node)
- end)
+ end
)
-S.transform = P.map(P.seq(
- S.slash,
- P.take_until({ '/' }, { '\\' }),
- S.slash,
- P.many(P.any(S.format, S.text({ '$', '/' }, { '\\' }))),
- S.slash,
- P.opt(P.pattern('[ig]+'))
-), function(values)
- return setmetatable({
- type = Node.Type.TRANSFORM,
- pattern = values[2].raw,
- format = values[4],
- option = values[6],
- }, Node)
-end)
-
S.tabstop = P.any(
P.map(P.seq(S.dollar, S.int), function(values)
return setmetatable({
@@ -314,34 +332,38 @@ S.tabstop = P.any(
)
S.placeholder = P.any(
- P.map(P.seq(S.dollar, S.open, S.int, S.colon, P.many(P.any(S.toplevel, S.text({ '$', '}' }, { '\\' }))), S.close), function(values)
- return setmetatable({
- type = Node.Type.PLACEHOLDER,
- tabstop = values[3],
- children = values[5],
- }, Node)
- end)
+ P.map(
+ P.seq(S.dollar, S.open, S.int, S.colon, P.many(P.any(S.toplevel, S.text({ '$', '}' }, { '\\' }))), S.close),
+ function(values)
+ return setmetatable({
+ type = Node.Type.PLACEHOLDER,
+ tabstop = values[3],
+ children = values[5],
+ }, Node)
+ end
+ )
)
-S.choice = P.map(P.seq(
- S.dollar,
- S.open,
- S.int,
- S.pipe,
- P.many(
- P.map(P.seq(S.text({ ',', '|' }), P.opt(S.comma)), function(values)
+S.choice = P.map(
+ P.seq(
+ S.dollar,
+ S.open,
+ S.int,
+ S.pipe,
+ P.many(P.map(P.seq(S.text({ ',', '|' }), P.opt(S.comma)), function(values)
return values[1].esc
- end)
+ end)),
+ S.pipe,
+ S.close
),
- S.pipe,
- S.close
-), function(values)
- return setmetatable({
- type = Node.Type.CHOICE,
- tabstop = values[3],
- items = values[5],
- }, Node)
-end)
+ function(values)
+ return setmetatable({
+ type = Node.Type.CHOICE,
+ tabstop = values[3],
+ items = values[5],
+ }, Node)
+ end
+)
S.variable = P.any(
P.map(P.seq(S.dollar, S.var), function(values)
@@ -363,13 +385,16 @@ S.variable = P.any(
transform = values[4],
}, Node)
end),
- P.map(P.seq(S.dollar, S.open, S.var, S.colon, P.many(P.any(S.toplevel, S.text({ '$', '}' }, { '\\' }))), S.close), function(values)
- return setmetatable({
- type = Node.Type.VARIABLE,
- name = values[3],
- children = values[5],
- }, Node)
- end)
+ P.map(
+ P.seq(S.dollar, S.open, S.var, S.colon, P.many(P.any(S.toplevel, S.text({ '$', '}' }, { '\\' }))), S.close),
+ function(values)
+ return setmetatable({
+ type = Node.Type.VARIABLE,
+ name = values[3],
+ children = values[5],
+ }, Node)
+ end
+ )
)
S.snippet = P.map(P.many(P.any(S.toplevel, S.text({ '$' }, { '}', '\\' }))), function(values)
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 9b34a551b7..b0bf2c6e5b 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -1,7 +1,7 @@
local vim = vim
local validate = vim.validate
local vfn = vim.fn
-local util = require 'vim.lsp.util'
+local util = require('vim.lsp.util')
local M = {}
@@ -9,7 +9,9 @@ local M = {}
--- Returns nil if {status} is false or nil, otherwise returns the rest of the
--- arguments.
local function ok_or_nil(status, ...)
- if not status then return end
+ if not status then
+ return
+ end
return ...
end
@@ -39,10 +41,10 @@ end
---
---@see |vim.lsp.buf_request()|
local function request(method, params, handler)
- validate {
- method = {method, 's'};
- handler = {handler, 'f', true};
- }
+ validate({
+ method = { method, 's' },
+ handler = { handler, 'f', true },
+ })
return vim.lsp.buf_request(0, method, params, handler)
end
@@ -51,7 +53,7 @@ end
---
---@returns `true` if server responds.
function M.server_ready()
- return not not vim.lsp.buf_notify(0, "window/progress", {})
+ return not not vim.lsp.buf_notify(0, 'window/progress', {})
end
--- Displays hover information about the symbol under the cursor in a floating
@@ -117,9 +119,9 @@ end
--
---@returns The client that the user selected or nil
local function select_client(method, on_choice)
- validate {
+ validate({
on_choice = { on_choice, 'function', false },
- }
+ })
local clients = vim.tbl_values(vim.lsp.buf_get_clients())
clients = vim.tbl_filter(function(client)
return client.supports_method(method)
@@ -191,24 +193,21 @@ function M.format(options)
if options.filter then
clients = options.filter(clients)
elseif options.id then
- clients = vim.tbl_filter(
- function(client) return client.id == options.id end,
- clients
- )
+ clients = vim.tbl_filter(function(client)
+ return client.id == options.id
+ end, clients)
elseif options.name then
- clients = vim.tbl_filter(
- function(client) return client.name == options.name end,
- clients
- )
+ clients = vim.tbl_filter(function(client)
+ return client.name == options.name
+ end, clients)
end
- clients = vim.tbl_filter(
- function(client) return client.supports_method("textDocument/formatting") end,
- clients
- )
+ clients = vim.tbl_filter(function(client)
+ return client.supports_method('textDocument/formatting')
+ end, clients)
if #clients == 0 then
- vim.notify("[LSP] Format request failed, no matching language servers.")
+ vim.notify('[LSP] Format request failed, no matching language servers.')
end
if options.async then
@@ -218,7 +217,7 @@ function M.format(options)
return
end
local params = util.make_formatting_params(options.formatting_options)
- client.request("textDocument/formatting", params, function(...)
+ client.request('textDocument/formatting', params, function(...)
local handler = client.handlers['textDocument/formatting'] or vim.lsp.handlers['textDocument/formatting']
handler(...)
do_format(next(clients, idx))
@@ -229,11 +228,11 @@ function M.format(options)
local timeout_ms = options.timeout_ms or 1000
for _, client in pairs(clients) do
local params = util.make_formatting_params(options.formatting_options)
- local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr)
+ local result, err = client.request_sync('textDocument/formatting', params, timeout_ms, bufnr)
if result and result.result then
util.apply_text_edits(result.result, bufnr, client.offset_encoding)
elseif err then
- vim.notify(string.format("[LSP][%s] %s", client.name, err), vim.log.levels.WARN)
+ vim.notify(string.format('[LSP][%s] %s', client.name, err), vim.log.levels.WARN)
end
end
end
@@ -310,7 +309,7 @@ end
---the remaining clients in the order as they occur in the `order` list.
function M.formatting_seq_sync(options, timeout_ms, order)
vim.notify_once('vim.lsp.buf.formatting_seq_sync is deprecated. Use vim.lsp.buf.format instead', vim.log.levels.WARN)
- local clients = vim.tbl_values(vim.lsp.buf_get_clients());
+ local clients = vim.tbl_values(vim.lsp.buf_get_clients())
local bufnr = vim.api.nvim_get_current_buf()
-- sort the clients according to `order`
@@ -326,13 +325,18 @@ function M.formatting_seq_sync(options, timeout_ms, order)
-- loop through the clients and make synchronous formatting requests
for _, client in pairs(clients) do
- if vim.tbl_get(client.server_capabilities, "documentFormattingProvider") then
+ if vim.tbl_get(client.server_capabilities, 'documentFormattingProvider') then
local params = util.make_formatting_params(options)
- local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, vim.api.nvim_get_current_buf())
+ local result, err = client.request_sync(
+ 'textDocument/formatting',
+ params,
+ timeout_ms,
+ vim.api.nvim_get_current_buf()
+ )
if result and result.result then
util.apply_text_edits(result.result, bufnr, client.offset_encoding)
elseif err then
- vim.notify(string.format("vim.lsp.buf.formatting_seq_sync: (%s) %s", client.name, err), vim.log.levels.WARN)
+ vim.notify(string.format('vim.lsp.buf.formatting_seq_sync: (%s) %s', client.name, err), vim.log.levels.WARN)
end
end
end
@@ -377,20 +381,18 @@ function M.rename(new_name, options)
if options.filter then
clients = options.filter(clients)
elseif options.name then
- clients = vim.tbl_filter(
- function(client) return client.name == options.name end,
- clients
- )
+ clients = vim.tbl_filter(function(client)
+ return client.name == options.name
+ end, clients)
end
-- Clients must at least support rename, prepareRename is optional
- clients = vim.tbl_filter(
- function(client) return client.supports_method("textDocument/rename") end,
- clients
- )
+ clients = vim.tbl_filter(function(client)
+ return client.supports_method('textDocument/rename')
+ end, clients)
if #clients == 0 then
- vim.notify("[LSP] Rename, no matching language servers with rename capability.")
+ vim.notify('[LSP] Rename, no matching language servers with rename capability.')
end
local win = vim.api.nvim_get_current_win()
@@ -427,7 +429,7 @@ function M.rename(new_name, options)
end, bufnr)
end
- if client.supports_method("textDocument/prepareRename") then
+ if client.supports_method('textDocument/prepareRename') then
local params = util.make_position_params(win, client.offset_encoding)
client.request('textDocument/prepareRename', params, function(err, result)
if err or result == nil then
@@ -446,7 +448,7 @@ function M.rename(new_name, options)
end
local prompt_opts = {
- prompt = "New Name: "
+ prompt = 'New Name: ',
}
-- result: Range | { range: Range, placeholder: string }
if result.placeholder then
@@ -466,15 +468,15 @@ function M.rename(new_name, options)
end)
end, bufnr)
else
- assert(client.supports_method("textDocument/rename"), 'Client must support textDocument/rename')
+ assert(client.supports_method('textDocument/rename'), 'Client must support textDocument/rename')
if new_name then
rename(new_name)
return
end
local prompt_opts = {
- prompt = "New Name: ",
- default = cword
+ prompt = 'New Name: ',
+ default = cword,
}
vim.ui.input(prompt_opts, function(input)
if not input or #input == 0 then
@@ -493,10 +495,10 @@ end
---@param context (table) Context for the request
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
function M.references(context)
- validate { context = { context, 't', true } }
+ validate({ context = { context, 't', true } })
local params = util.make_position_params()
params.context = context or {
- includeDeclaration = true;
+ includeDeclaration = true,
}
request('textDocument/references', params)
end
@@ -510,14 +512,16 @@ end
---@private
local function pick_call_hierarchy_item(call_hierarchy_items)
- if not call_hierarchy_items then return end
+ if not call_hierarchy_items then
+ return
+ end
if #call_hierarchy_items == 1 then
return call_hierarchy_items[1]
end
local items = {}
for i, item in pairs(call_hierarchy_items) do
local entry = item.detail or item.name
- table.insert(items, string.format("%d. %s", i, entry))
+ table.insert(items, string.format('%d. %s', i, entry))
end
local choice = vim.fn.inputlist(items)
if choice < 1 or choice > #items then
@@ -539,8 +543,8 @@ local function call_hierarchy(method)
if client then
client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr)
else
- vim.notify(string.format(
- 'Client with id=%d disappeared during call hierarchy request', ctx.client_id),
+ vim.notify(
+ string.format('Client with id=%d disappeared during call hierarchy request', ctx.client_id),
vim.log.levels.WARN
)
end
@@ -576,20 +580,25 @@ end
--- Add the folder at path to the workspace folders. If {path} is
--- not provided, the user will be prompted for a path using |input()|.
function M.add_workspace_folder(workspace_folder)
- workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'), 'dir')
- vim.api.nvim_command("redraw")
- if not (workspace_folder and #workspace_folder > 0) then return end
+ workspace_folder = workspace_folder or npcall(vfn.input, 'Workspace Folder: ', vfn.expand('%:p:h'), 'dir')
+ vim.api.nvim_command('redraw')
+ if not (workspace_folder and #workspace_folder > 0) then
+ return
+ end
if vim.fn.isdirectory(workspace_folder) == 0 then
- print(workspace_folder, " is not a valid directory")
+ print(workspace_folder, ' is not a valid directory')
return
end
- local params = util.make_workspace_params({{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}}, {{}})
+ local params = util.make_workspace_params(
+ { { uri = vim.uri_from_fname(workspace_folder), name = workspace_folder } },
+ { {} }
+ )
for _, client in pairs(vim.lsp.buf_get_clients()) do
local found = false
for _, folder in pairs(client.workspace_folders or {}) do
if folder.name == workspace_folder then
found = true
- print(workspace_folder, "is already part of this workspace")
+ print(workspace_folder, 'is already part of this workspace')
break
end
end
@@ -607,10 +616,15 @@ end
--- {path} is not provided, the user will be prompted for
--- a path using |input()|.
function M.remove_workspace_folder(workspace_folder)
- workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'))
- vim.api.nvim_command("redraw")
- if not (workspace_folder and #workspace_folder > 0) then return end
- local params = util.make_workspace_params({{}}, {{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}})
+ workspace_folder = workspace_folder or npcall(vfn.input, 'Workspace Folder: ', vfn.expand('%:p:h'))
+ vim.api.nvim_command('redraw')
+ if not (workspace_folder and #workspace_folder > 0) then
+ return
+ end
+ local params = util.make_workspace_params(
+ { {} },
+ { { uri = vim.uri_from_fname(workspace_folder), name = workspace_folder } }
+ )
for _, client in pairs(vim.lsp.buf_get_clients()) do
for idx, folder in pairs(client.workspace_folders) do
if folder.name == workspace_folder then
@@ -620,7 +634,7 @@ function M.remove_workspace_folder(workspace_folder)
end
end
end
- print(workspace_folder, "is not currently part of the workspace")
+ print(workspace_folder, 'is not currently part of the workspace')
end
--- Lists all symbols in the current workspace in the quickfix window.
@@ -631,11 +645,11 @@ end
---
---@param query (string, optional)
function M.workspace_symbol(query)
- query = query or npcall(vfn.input, "Query: ")
+ query = query or npcall(vfn.input, 'Query: ')
if query == nil then
return
end
- local params = {query = query}
+ local params = { query = query }
request('workspace/symbol', params)
end
@@ -665,7 +679,6 @@ function M.clear_references()
util.buf_clear_references()
end
-
---@private
--
--- This is not public because the main extension point is
@@ -678,10 +691,38 @@ end
--- `codeAction/resolve`
local function on_code_action_results(results, ctx, options)
local action_tuples = {}
- local filter = options and options.filter
+
+ ---@private
+ local function action_filter(a)
+ -- filter by specified action kind
+ if options and options.context and options.context.only then
+ if not a.kind then
+ return false
+ end
+ local found = false
+ for _, o in ipairs(options.context.only) do
+ -- action kinds are hierachical with . as a separator: when requesting only
+ -- 'quickfix' this filter allows both 'quickfix' and 'quickfix.foo', for example
+ if a.kind:find('^' .. o .. '$') or a.kind:find('^' .. o .. '%.') then
+ found = true
+ break
+ end
+ end
+ if not found then
+ return false
+ end
+ end
+ -- filter by user function
+ if options and options.filter and not options.filter(a) then
+ return false
+ end
+ -- no filter removed this action
+ return true
+ end
+
for client_id, result in pairs(results) do
for _, action in pairs(result.result or {}) do
- if not filter or filter(action) then
+ if action_filter(action) then
table.insert(action_tuples, { client_id, action })
end
end
@@ -728,10 +769,11 @@ local function on_code_action_results(results, ctx, options)
--
local client = vim.lsp.get_client_by_id(action_tuple[1])
local action = action_tuple[2]
- if not action.edit
- and client
- and vim.tbl_get(client.server_capabilities, "codeActionProvider", "resolveProvider") then
-
+ if
+ not action.edit
+ and client
+ and vim.tbl_get(client.server_capabilities, 'codeActionProvider', 'resolveProvider')
+ then
client.request('codeAction/resolve', action, function(err, resolved_action)
if err then
vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
@@ -761,7 +803,6 @@ local function on_code_action_results(results, ctx, options)
}, on_user_choice)
end
-
--- Requests code actions from all clients and calls the handler exactly once
--- with all aggregated results
---@private
@@ -769,7 +810,7 @@ local function code_action_request(params, options)
local bufnr = vim.api.nvim_get_current_buf()
local method = 'textDocument/codeAction'
vim.lsp.buf_request_all(bufnr, method, params, function(results)
- local ctx = { bufnr = bufnr, method = method, params = params}
+ local ctx = { bufnr = bufnr, method = method, params = params }
on_code_action_results(results, ctx, options)
end)
end
@@ -794,7 +835,7 @@ end
--- (after filtering), the action is applied without user query.
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
function M.code_action(options)
- validate { options = { options, 't', true } }
+ validate({ options = { options, 't', true } })
options = options or {}
-- Detect old API call code_action(context) which should now be
-- code_action({ context = context} )
@@ -826,7 +867,7 @@ end
---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection.
function M.range_code_action(context, start_pos, end_pos)
- validate { context = { context, 't', true } }
+ validate({ context = { context, 't', true } })
context = context or {}
if not context.diagnostics then
context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
@@ -841,16 +882,16 @@ end
---@param command_params table A valid `ExecuteCommandParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
function M.execute_command(command_params)
- validate {
+ validate({
command = { command_params.command, 's' },
- arguments = { command_params.arguments, 't', true }
- }
+ arguments = { command_params.arguments, 't', true },
+ })
command_params = {
- command=command_params.command,
- arguments=command_params.arguments,
- workDoneToken=command_params.workDoneToken,
+ command = command_params.command,
+ arguments = command_params.arguments,
+ workDoneToken = command_params.workDoneToken,
}
- request('workspace/executeCommand', command_params )
+ request('workspace/executeCommand', command_params)
end
return M
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 99695d2ed1..ec0aede2d3 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -12,7 +12,7 @@ local lens_cache_by_buf = setmetatable({}, {
__index = function(t, b)
local key = b > 0 and b or api.nvim_get_current_buf()
return rawget(t, key)
- end
+ end,
})
local namespaces = setmetatable({}, {
@@ -20,13 +20,12 @@ local namespaces = setmetatable({}, {
local value = api.nvim_create_namespace('vim_lsp_codelens:' .. key)
rawset(t, key, value)
return value
- end;
+ end,
})
---@private
M.__namespaces = namespaces
-
---@private
local function execute_lens(lens, bufnr, client_id)
local line = lens.range.start.line
@@ -44,10 +43,14 @@ local function execute_lens(lens, bufnr, client_id)
local command_provider = client.server_capabilities.executeCommandProvider
local commands = type(command_provider) == 'table' and command_provider.commands or {}
if not vim.tbl_contains(commands, command.command) then
- vim.notify(string.format(
- "Language server does not support command `%s`. This command may require a client extension.", command.command),
- vim.log.levels.WARN)
- return
+ vim.notify(
+ string.format(
+ 'Language server does not support command `%s`. This command may require a client extension.',
+ command.command
+ ),
+ vim.log.levels.WARN
+ )
+ return
end
client.request('workspace/executeCommand', command, function(...)
local result = vim.lsp.handlers['workspace/executeCommand'](...)
@@ -56,14 +59,15 @@ local function execute_lens(lens, bufnr, client_id)
end, bufnr)
end
-
--- Return all lenses for the given buffer
---
---@param bufnr number Buffer number. 0 can be used for the current buffer.
---@return table (`CodeLens[]`)
function M.get(bufnr)
local lenses_by_client = lens_cache_by_buf[bufnr or 0]
- if not lenses_by_client then return {} end
+ if not lenses_by_client then
+ return {}
+ end
local lenses = {}
for _, client_lenses in pairs(lenses_by_client) do
vim.list_extend(lenses, client_lenses)
@@ -71,7 +75,6 @@ function M.get(bufnr)
return lenses
end
-
--- Run the code lens in the current line
---
function M.run()
@@ -82,7 +85,7 @@ function M.run()
for client, lenses in pairs(lenses_by_client) do
for _, lens in pairs(lenses) do
if lens.range.start.line == (line - 1) then
- table.insert(options, {client=client, lens=lens})
+ table.insert(options, { client = client, lens = lens })
end
end
end
@@ -105,7 +108,6 @@ function M.run()
end
end
-
--- Display the lenses using virtual text
---
---@param lenses table of lenses to display (`CodeLens[] | null`)
@@ -133,19 +135,20 @@ function M.display(lenses, bufnr, client_id)
local num_line_lenses = #line_lenses
for j, lens in ipairs(line_lenses) do
local text = lens.command and lens.command.title or 'Unresolved lens ...'
- table.insert(chunks, {text, 'LspCodeLens' })
+ table.insert(chunks, { text, 'LspCodeLens' })
if j < num_line_lenses then
- table.insert(chunks, {' | ', 'LspCodeLensSeparator' })
+ table.insert(chunks, { ' | ', 'LspCodeLensSeparator' })
end
end
if #chunks > 0 then
- api.nvim_buf_set_extmark(bufnr, ns, i, 0, { virt_text = chunks,
- hl_mode="combine" })
+ api.nvim_buf_set_extmark(bufnr, ns, i, 0, {
+ virt_text = chunks,
+ hl_mode = 'combine',
+ })
end
end
end
-
--- Store lenses for a specific buffer and client
---
---@param lenses table of lenses to store (`CodeLens[] | null`)
@@ -158,16 +161,17 @@ function M.save(lenses, bufnr, client_id)
lens_cache_by_buf[bufnr] = lenses_by_client
local ns = namespaces[client_id]
api.nvim_buf_attach(bufnr, false, {
- on_detach = function(b) lens_cache_by_buf[b] = nil end,
+ on_detach = function(b)
+ lens_cache_by_buf[b] = nil
+ end,
on_lines = function(_, b, _, first_lnum, last_lnum)
api.nvim_buf_clear_namespace(b, ns, first_lnum, last_lnum)
- end
+ end,
})
end
lenses_by_client[client_id] = lenses
end
-
---@private
local function resolve_lenses(lenses, bufnr, client_id, callback)
lenses = lenses or {}
@@ -201,8 +205,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback)
ns,
lens.range.start.line,
0,
- { virt_text = {{ lens.command.title, 'LspCodeLens' }},
- hl_mode="combine" }
+ { virt_text = { { lens.command.title, 'LspCodeLens' } }, hl_mode = 'combine' }
)
end
countdown()
@@ -211,13 +214,12 @@ local function resolve_lenses(lenses, bufnr, client_id, callback)
end
end
-
--- |lsp-handler| for the method `textDocument/codeLens`
---
function M.on_codelens(err, result, ctx, _)
if err then
active_refreshes[ctx.bufnr] = nil
- local _ = log.error() and log.error("codelens", err)
+ local _ = log.error() and log.error('codelens', err)
return
end
@@ -232,7 +234,6 @@ function M.on_codelens(err, result, ctx, _)
end)
end
-
--- Refresh the codelens for the current buffer
---
--- It is recommended to trigger this using an autocmd or via keymap.
@@ -243,7 +244,7 @@ end
---
function M.refresh()
local params = {
- textDocument = util.make_text_document_params()
+ textDocument = util.make_text_document_params(),
}
local bufnr = api.nvim_get_current_buf()
if active_refreshes[bufnr] then
@@ -253,5 +254,4 @@ function M.refresh()
vim.lsp.buf_request(0, 'textDocument/codeLens', params, M.on_codelens)
end
-
return M
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 28a236cc7e..126be2a0ad 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -50,12 +50,12 @@ end
---@private
local function line_byte_from_position(lines, lnum, col, offset_encoding)
- if not lines or offset_encoding == "utf-8" then
+ if not lines or offset_encoding == 'utf-8' then
return col
end
local line = lines[lnum + 1]
- local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == "utf-16")
+ local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16')
if ok then
return result
end
@@ -75,7 +75,7 @@ local function get_buf_lines(bufnr)
return
end
- local content = f:read("*a")
+ local content = f:read('*a')
if not content then
-- Some LSP servers report diagnostics at a directory level, in which case
-- io.read() returns nil
@@ -83,7 +83,7 @@ local function get_buf_lines(bufnr)
return
end
- local lines = vim.split(content, "\n")
+ local lines = vim.split(content, '\n')
f:close()
return lines
end
@@ -92,10 +92,10 @@ end
local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
local buf_lines = get_buf_lines(bufnr)
local client = vim.lsp.get_client_by_id(client_id)
- local offset_encoding = client and client.offset_encoding or "utf-16"
+ local offset_encoding = client and client.offset_encoding or 'utf-16'
return vim.tbl_map(function(diagnostic)
local start = diagnostic.range.start
- local _end = diagnostic.range["end"]
+ local _end = diagnostic.range['end']
return {
lnum = start.line,
col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding),
@@ -122,14 +122,14 @@ end
---@private
local function diagnostic_vim_to_lsp(diagnostics)
return vim.tbl_map(function(diagnostic)
- return vim.tbl_extend("keep", {
+ return vim.tbl_extend('keep', {
-- "keep" the below fields over any duplicate fields in diagnostic.user_data.lsp
range = {
start = {
line = diagnostic.lnum,
character = diagnostic.col,
},
- ["end"] = {
+ ['end'] = {
line = diagnostic.end_lnum,
character = diagnostic.end_col,
},
@@ -148,10 +148,10 @@ local _client_namespaces = {}
---
---@param client_id number The id of the LSP client
function M.get_namespace(client_id)
- vim.validate { client_id = { client_id, 'n' } }
+ vim.validate({ client_id = { client_id, 'n' } })
if not _client_namespaces[client_id] then
local client = vim.lsp.get_client_by_id(client_id)
- local name = string.format("vim.lsp.%s.%d", client and client.name or "unknown", client_id)
+ local name = string.format('vim.lsp.%s.%d', client and client.name or 'unknown', client_id)
_client_namespaces[client_id] = vim.api.nvim_create_namespace(name)
end
return _client_namespaces[client_id]
@@ -203,7 +203,7 @@ function M.on_publish_diagnostics(_, result, ctx, config)
for _, opt in pairs(config) do
if type(opt) == 'table' then
if not opt.severity and opt.severity_limit then
- opt.severity = {min=severity_lsp_to_vim(opt.severity_limit)}
+ opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) }
end
end
end
@@ -240,7 +240,6 @@ end
-- Deprecated Functions {{{
-
--- Save diagnostics to the current buffer.
---
---@deprecated Prefer |vim.diagnostic.set()|
@@ -251,7 +250,7 @@ end
---@param client_id number
---@private
function M.save(diagnostics, bufnr, client_id)
- vim.deprecate('vim.lsp.diagnostic.save', 'vim.diagnostic.set', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.save', 'vim.diagnostic.set', '0.8')
local namespace = M.get_namespace(client_id)
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
end
@@ -265,14 +264,14 @@ end
--- If nil, diagnostics of all clients are included.
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
function M.get_all(client_id)
- vim.deprecate('vim.lsp.diagnostic.get_all', 'vim.diagnostic.get', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_all', 'vim.diagnostic.get', '0.8')
local result = {}
local namespace
if client_id then
namespace = M.get_namespace(client_id)
end
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
- local diagnostics = diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, {namespace = namespace}))
+ local diagnostics = diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, { namespace = namespace }))
result[bufnr] = diagnostics
end
return result
@@ -287,8 +286,10 @@ end
--- Else, return just the diagnostics associated with the client_id.
---@param predicate function|nil Optional function for filtering diagnostics
function M.get(bufnr, client_id, predicate)
- vim.deprecate('vim.lsp.diagnostic.get', 'vim.diagnostic.get', '0.8' )
- predicate = predicate or function() return true end
+ vim.deprecate('vim.lsp.diagnostic.get', 'vim.diagnostic.get', '0.8')
+ predicate = predicate or function()
+ return true
+ end
if client_id == nil then
local all_diagnostics = {}
vim.lsp.for_each_buffer_client(bufnr, function(_, iter_client_id, _)
@@ -301,7 +302,7 @@ function M.get(bufnr, client_id, predicate)
end
local namespace = M.get_namespace(client_id)
- return diagnostic_vim_to_lsp(vim.tbl_filter(predicate, vim.diagnostic.get(bufnr, {namespace=namespace})))
+ return diagnostic_vim_to_lsp(vim.tbl_filter(predicate, vim.diagnostic.get(bufnr, { namespace = namespace })))
end
--- Get the diagnostics by line
@@ -325,7 +326,7 @@ function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
if client_id then
@@ -349,7 +350,7 @@ end
---@param severity DiagnosticSeverity
---@param client_id number the client id
function M.get_count(bufnr, severity, client_id)
- vim.deprecate('vim.lsp.diagnostic.get_count', 'vim.diagnostic.get', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_count', 'vim.diagnostic.get', '0.8')
severity = severity_lsp_to_vim(severity)
local opts = { severity = severity }
if client_id ~= nil then
@@ -366,15 +367,15 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic
function M.get_prev(opts)
- vim.deprecate('vim.lsp.diagnostic.get_prev', 'vim.diagnostic.get_prev', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_prev', 'vim.diagnostic.get_prev', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
- return diagnostic_vim_to_lsp({vim.diagnostic.get_prev(opts)})[1]
+ return diagnostic_vim_to_lsp({ vim.diagnostic.get_prev(opts) })[1]
end
--- Return the pos, {row, col}, for the prev diagnostic in the current buffer.
@@ -384,12 +385,12 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic position
function M.get_prev_pos(opts)
- vim.deprecate('vim.lsp.diagnostic.get_prev_pos', 'vim.diagnostic.get_prev_pos', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_prev_pos', 'vim.diagnostic.get_prev_pos', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
return vim.diagnostic.get_prev_pos(opts)
@@ -401,12 +402,12 @@ end
---
---@param opts table See |vim.lsp.diagnostic.goto_next()|
function M.goto_prev(opts)
- vim.deprecate('vim.lsp.diagnostic.goto_prev', 'vim.diagnostic.goto_prev', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.goto_prev', 'vim.diagnostic.goto_prev', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
return vim.diagnostic.goto_prev(opts)
@@ -419,15 +420,15 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic
function M.get_next(opts)
- vim.deprecate('vim.lsp.diagnostic.get_next', 'vim.diagnostic.get_next', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_next', 'vim.diagnostic.get_next', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
- return diagnostic_vim_to_lsp({vim.diagnostic.get_next(opts)})[1]
+ return diagnostic_vim_to_lsp({ vim.diagnostic.get_next(opts) })[1]
end
--- Return the pos, {row, col}, for the next diagnostic in the current buffer.
@@ -437,12 +438,12 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic position
function M.get_next_pos(opts)
- vim.deprecate('vim.lsp.diagnostic.get_next_pos', 'vim.diagnostic.get_next_pos', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_next_pos', 'vim.diagnostic.get_next_pos', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
return vim.diagnostic.get_next_pos(opts)
@@ -452,12 +453,12 @@ end
---
---@deprecated Prefer |vim.diagnostic.goto_next()|
function M.goto_next(opts)
- vim.deprecate('vim.lsp.diagnostic.goto_next', 'vim.diagnostic.goto_next', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.goto_next', 'vim.diagnostic.goto_next', '0.8')
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
end
return vim.diagnostic.goto_next(opts)
@@ -476,10 +477,10 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_signs(diagnostics, bufnr, client_id, _, opts)
- vim.deprecate('vim.lsp.diagnostic.set_signs', nil , '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.set_signs', nil, '0.8')
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
vim.diagnostic._set_signs(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), opts)
@@ -497,10 +498,10 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_underline(diagnostics, bufnr, client_id, _, opts)
- vim.deprecate('vim.lsp.diagnostic.set_underline', nil , '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.set_underline', nil, '0.8')
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
return vim.diagnostic._set_underline(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), opts)
end
@@ -519,10 +520,10 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts)
- vim.deprecate('vim.lsp.diagnostic.set_virtual_text', nil , '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.set_virtual_text', nil, '0.8')
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
return vim.diagnostic._set_virtual_text(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id), opts)
end
@@ -538,7 +539,7 @@ end
---@return an array of [text, hl_group] arrays. This can be passed directly to
--- the {virt_text} option of |nvim_buf_set_extmark()|.
function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts)
- vim.deprecate('vim.lsp.diagnostic.get_virtual_text_chunks_for_line', nil, '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.get_virtual_text_chunks_for_line', nil, '0.8')
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
end
@@ -556,14 +557,14 @@ end
---@param position table|nil The (0,0)-indexed position
---@return table {popup_bufnr, win_id}
function M.show_position_diagnostics(opts, buf_nr, position)
- vim.deprecate('vim.lsp.diagnostic.show_position_diagnostics', 'vim.diagnostic.open_float', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.show_position_diagnostics', 'vim.diagnostic.open_float', '0.8')
opts = opts or {}
- opts.scope = "cursor"
+ opts.scope = 'cursor'
opts.pos = position
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
return vim.diagnostic.open_float(buf_nr, opts)
end
@@ -580,9 +581,9 @@ end
---@param client_id number|nil the client id
---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
- vim.deprecate('vim.lsp.diagnostic.show_line_diagnostics', 'vim.diagnostic.open_float', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.show_line_diagnostics', 'vim.diagnostic.open_float', '0.8')
opts = opts or {}
- opts.scope = "line"
+ opts.scope = 'line'
opts.pos = line_nr
if client_id then
opts.namespace = M.get_namespace(client_id)
@@ -604,7 +605,7 @@ end
--- client. The default is to redraw diagnostics for all attached
--- clients.
function M.redraw(bufnr, client_id)
- vim.deprecate('vim.lsp.diagnostic.redraw', 'vim.diagnostic.show', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.redraw', 'vim.diagnostic.show', '0.8')
bufnr = get_bufnr(bufnr)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
@@ -632,12 +633,12 @@ end
--- - {workspace}: (boolean, default true)
--- - Set the list with workspace diagnostics
function M.set_qflist(opts)
- vim.deprecate('vim.lsp.diagnostic.set_qflist', 'vim.diagnostic.setqflist', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.set_qflist', 'vim.diagnostic.setqflist', '0.8')
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
if opts.client_id then
opts.client_id = nil
@@ -664,12 +665,12 @@ end
--- - {workspace}: (boolean, default false)
--- - Set the list with workspace diagnostics
function M.set_loclist(opts)
- vim.deprecate('vim.lsp.diagnostic.set_loclist', 'vim.diagnostic.setloclist', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.set_loclist', 'vim.diagnostic.setloclist', '0.8')
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
elseif opts.severity_limit then
- opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
+ opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
end
if opts.client_id then
opts.client_id = nil
@@ -692,7 +693,7 @@ end
-- send diagnostic information and the client will still process it. The
-- diagnostics are simply not displayed to the user.
function M.disable(bufnr, client_id)
- vim.deprecate('vim.lsp.diagnostic.disable', 'vim.diagnostic.disable', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.disable', 'vim.diagnostic.disable', '0.8')
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.disable(bufnr, client.id)
@@ -713,7 +714,7 @@ end
--- client. The default is to enable diagnostics for all attached
--- clients.
function M.enable(bufnr, client_id)
- vim.deprecate('vim.lsp.diagnostic.enable', 'vim.diagnostic.enable', '0.8' )
+ vim.deprecate('vim.lsp.diagnostic.enable', 'vim.diagnostic.enable', '0.8')
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.enable(bufnr, client.id)
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 5c80ed0d10..b3a253c118 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -1,6 +1,6 @@
-local log = require 'vim.lsp.log'
-local protocol = require 'vim.lsp.protocol'
-local util = require 'vim.lsp.util'
+local log = require('vim.lsp.log')
+local protocol = require('vim.lsp.protocol')
+local util = require('vim.lsp.util')
local vim = vim
local api = vim.api
@@ -12,8 +12,8 @@ local M = {}
--- Writes to error buffer.
---@param ... (table of strings) Will be concatenated before being written
local function err_message(...)
- vim.notify(table.concat(vim.tbl_flatten{...}), vim.log.levels.ERROR)
- api.nvim_command("redraw")
+ vim.notify(table.concat(vim.tbl_flatten({ ... })), vim.log.levels.ERROR)
+ api.nvim_command('redraw')
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
@@ -25,15 +25,17 @@ end
local function progress_handler(_, result, ctx, _)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- local client_name = client and client.name or string.format("id=%d", client_id)
+ local client_name = client and client.name or string.format('id=%d', client_id)
if not client then
- err_message("LSP[", client_name, "] client has shut down during progress update")
+ err_message('LSP[', client_name, '] client has shut down during progress update')
return vim.NIL
end
- local val = result.value -- unspecified yet
- local token = result.token -- string or number
+ local val = result.value -- unspecified yet
+ local token = result.token -- string or number
- if type(val) ~= 'table' then val = { content=val } end
+ if type(val) ~= 'table' then
+ val = { content = val }
+ end
if val.kind then
if val.kind == 'begin' then
client.messages.progress[token] = {
@@ -42,11 +44,11 @@ local function progress_handler(_, result, ctx, _)
percentage = val.percentage,
}
elseif val.kind == 'report' then
- client.messages.progress[token].message = val.message;
- client.messages.progress[token].percentage = val.percentage;
+ client.messages.progress[token].message = val.message
+ client.messages.progress[token].percentage = val.percentage
elseif val.kind == 'end' then
if client.messages.progress[token] == nil then
- err_message("LSP[", client_name, "] received `end` message with no corresponding `begin`")
+ err_message('LSP[', client_name, '] received `end` message with no corresponding `begin`')
else
client.messages.progress[token].message = val.message
client.messages.progress[token].done = true
@@ -57,20 +59,20 @@ local function progress_handler(_, result, ctx, _)
client.messages.progress[token].done = true
end
- vim.api.nvim_command("doautocmd <nomodeline> User LspProgressUpdate")
+ vim.api.nvim_command('doautocmd <nomodeline> User LspProgressUpdate')
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress
M['$/progress'] = progress_handler
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create
-M['window/workDoneProgress/create'] = function(_, result, ctx)
+M['window/workDoneProgress/create'] = function(_, result, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- local token = result.token -- string or number
- local client_name = client and client.name or string.format("id=%d", client_id)
+ local token = result.token -- string or number
+ local client_name = client and client.name or string.format('id=%d', client_id)
if not client then
- err_message("LSP[", client_name, "] client has shut down while creating progress report")
+ err_message('LSP[', client_name, '] client has shut down while creating progress report')
return vim.NIL
end
client.messages.progress[token] = {}
@@ -79,20 +81,19 @@ end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest
M['window/showMessageRequest'] = function(_, result)
-
local actions = result.actions
print(result.message)
- local option_strings = {result.message, "\nRequest Actions:"}
+ local option_strings = { result.message, '\nRequest Actions:' }
for i, action in ipairs(actions) do
local title = action.title:gsub('\r\n', '\\r\\n')
title = title:gsub('\n', '\\n')
- table.insert(option_strings, string.format("%d. %s", i, title))
+ table.insert(option_strings, string.format('%d. %s', i, title))
end
-- window/showMessageRequest can return either MessageActionItem[] or null.
local choice = vim.fn.inputlist(option_strings)
if choice < 1 or choice > #actions then
- return vim.NIL
+ return vim.NIL
else
return actions[choice]
end
@@ -101,11 +102,11 @@ end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability
M['client/registerCapability'] = function(_, _, ctx)
local client_id = ctx.client_id
- local warning_tpl = "The language server %s triggers a registerCapability "..
- "handler despite dynamicRegistration set to false. "..
- "Report upstream, this warning is harmless"
+ local warning_tpl = 'The language server %s triggers a registerCapability '
+ .. 'handler despite dynamicRegistration set to false. '
+ .. 'Report upstream, this warning is harmless'
local client = vim.lsp.get_client_by_id(client_id)
- local client_name = client and client.name or string.format("id=%d", client_id)
+ local client_name = client and client.name or string.format('id=%d', client_id)
local warning = string.format(warning_tpl, client_name)
log.warn(warning)
return vim.NIL
@@ -113,17 +114,19 @@ end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
M['workspace/applyEdit'] = function(_, workspace_edit, ctx)
- if not workspace_edit then return end
+ if not workspace_edit then
+ return
+ end
-- TODO(ashkan) Do something more with label?
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
if workspace_edit.label then
- print("Workspace edit", workspace_edit.label)
+ print('Workspace edit', workspace_edit.label)
end
local status, result = pcall(util.apply_workspace_edit, workspace_edit.edit, client.offset_encoding)
return {
- applied = status;
- failureReason = result;
+ applied = status,
+ failureReason = result,
}
end
@@ -132,7 +135,7 @@ M['workspace/configuration'] = function(_, result, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
if not client then
- err_message("LSP[", client_id, "] client has shut down after sending a workspace/configuration request")
+ err_message('LSP[', client_id, '] client has shut down after sending a workspace/configuration request')
return
end
if not result.items then
@@ -158,7 +161,7 @@ M['workspace/workspaceFolders'] = function(_, _, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
if not client then
- err_message("LSP[id=", client_id, "] client has shut down after sending the message")
+ err_message('LSP[id=', client_id, '] client has shut down after sending the message')
return
end
return client.workspace_folders or vim.NIL
@@ -172,7 +175,6 @@ M['textDocument/codeLens'] = function(...)
return require('vim.lsp.codelens').on_codelens(...)
end
-
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
M['textDocument/references'] = function(_, result, ctx, config)
if not result or vim.tbl_isempty(result) then
@@ -182,23 +184,22 @@ M['textDocument/references'] = function(_, result, ctx, config)
config = config or {}
if config.loclist then
vim.fn.setloclist(0, {}, ' ', {
- title = 'References';
- items = util.locations_to_items(result, client.offset_encoding);
- context = ctx;
+ title = 'References',
+ items = util.locations_to_items(result, client.offset_encoding),
+ context = ctx,
})
- api.nvim_command("lopen")
+ api.nvim_command('lopen')
else
vim.fn.setqflist({}, ' ', {
- title = 'References';
- items = util.locations_to_items(result, client.offset_encoding);
- context = ctx;
+ title = 'References',
+ items = util.locations_to_items(result, client.offset_encoding),
+ context = ctx,
})
- api.nvim_command("botright copen")
+ api.nvim_command('botright copen')
end
end
end
-
---@private
--- Return a function that converts LSP responses to list items and opens the list
---
@@ -218,27 +219,26 @@ local function response_to_list(map_result, entity, title_fn)
config = config or {}
if config.loclist then
vim.fn.setloclist(0, {}, ' ', {
- title = title_fn(ctx);
- items = map_result(result, ctx.bufnr);
- context = ctx;
+ title = title_fn(ctx),
+ items = map_result(result, ctx.bufnr),
+ context = ctx,
})
- api.nvim_command("lopen")
+ api.nvim_command('lopen')
else
vim.fn.setqflist({}, ' ', {
- title = title_fn(ctx);
- items = map_result(result, ctx.bufnr);
- context = ctx;
+ title = title_fn(ctx),
+ items = map_result(result, ctx.bufnr),
+ context = ctx,
})
- api.nvim_command("botright copen")
+ api.nvim_command('botright copen')
end
end
end
end
-
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
M['textDocument/documentSymbol'] = response_to_list(util.symbols_to_items, 'document symbols', function(ctx)
- local fname = vim.fn.fnamemodify(vim.uri_to_fname(ctx.params.textDocument.uri), ":.")
+ local fname = vim.fn.fnamemodify(vim.uri_to_fname(ctx.params.textDocument.uri), ':.')
return string.format('Symbols in %s', fname)
end)
@@ -249,36 +249,44 @@ end)
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
M['textDocument/rename'] = function(_, result, ctx, _)
- if not result then return end
+ if not result then
+ return
+ end
local client = vim.lsp.get_client_by_id(ctx.client_id)
util.apply_workspace_edit(result, client.offset_encoding)
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting
M['textDocument/rangeFormatting'] = function(_, result, ctx, _)
- if not result then return end
+ if not result then
+ return
+ end
local client = vim.lsp.get_client_by_id(ctx.client_id)
util.apply_text_edits(result, ctx.bufnr, client.offset_encoding)
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
M['textDocument/formatting'] = function(_, result, ctx, _)
- if not result then return end
+ if not result then
+ return
+ end
local client = vim.lsp.get_client_by_id(ctx.client_id)
util.apply_text_edits(result, ctx.bufnr, client.offset_encoding)
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
M['textDocument/completion'] = function(_, result, _, _)
- if vim.tbl_isempty(result or {}) then return end
+ if vim.tbl_isempty(result or {}) then
+ return
+ end
local row, col = unpack(api.nvim_win_get_cursor(0))
- local line = assert(api.nvim_buf_get_lines(0, row-1, row, false)[1])
- local line_to_cursor = line:sub(col+1)
+ local line = assert(api.nvim_buf_get_lines(0, row - 1, row, false)[1])
+ local line_to_cursor = line:sub(col + 1)
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
- local prefix = line_to_cursor:sub(textMatch+1)
+ local prefix = line_to_cursor:sub(textMatch + 1)
local matches = util.text_document_completion_list_to_complete_items(result, prefix)
- vim.fn.complete(textMatch+1, matches)
+ vim.fn.complete(textMatch + 1, matches)
end
--- |lsp-handler| for the method "textDocument/hover"
@@ -307,7 +315,7 @@ function M.hover(_, result, ctx, config)
vim.notify('No information available')
return
end
- return util.open_floating_preview(markdown_lines, "markdown", config)
+ return util.open_floating_preview(markdown_lines, 'markdown', config)
end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
@@ -335,9 +343,9 @@ local function location_handler(_, result, ctx, _)
if #result > 1 then
vim.fn.setqflist({}, ' ', {
title = 'LSP locations',
- items = util.locations_to_items(result, client.offset_encoding)
+ items = util.locations_to_items(result, client.offset_encoding),
})
- api.nvim_command("botright copen")
+ api.nvim_command('botright copen')
end
else
util.jump_to_location(result, client.offset_encoding)
@@ -379,7 +387,7 @@ function M.signature_help(_, result, ctx, config)
return
end
local client = vim.lsp.get_client_by_id(ctx.client_id)
- local triggers = vim.tbl_get(client.server_capabilities, "signatureHelpProvider", "triggerCharacters")
+ local triggers = vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters')
local ft = api.nvim_buf_get_option(ctx.bufnr, 'filetype')
local lines, hl = util.convert_signature_help_to_markdown_lines(result, ft, triggers)
lines = util.trim_empty_lines(lines)
@@ -389,9 +397,9 @@ function M.signature_help(_, result, ctx, config)
end
return
end
- local fbuf, fwin = util.open_floating_preview(lines, "markdown", config)
+ local fbuf, fwin = util.open_floating_preview(lines, 'markdown', config)
if hl then
- api.nvim_buf_add_highlight(fbuf, -1, "LspSignatureActiveParameter", 0, unpack(hl))
+ api.nvim_buf_add_highlight(fbuf, -1, 'LspSignatureActiveParameter', 0, unpack(hl))
end
return fbuf, fwin
end
@@ -401,10 +409,14 @@ M['textDocument/signatureHelp'] = M.signature_help
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight
M['textDocument/documentHighlight'] = function(_, result, ctx, _)
- if not result then return end
+ if not result then
+ return
+ end
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- if not client then return end
+ if not client then
+ return
+ end
util.buf_highlight_references(ctx.bufnr, result, client.offset_encoding)
end
@@ -417,7 +429,9 @@ end
---@returns `CallHierarchyOutgoingCall[]` if {direction} is `"to"`,
local make_call_hierarchy_handler = function(direction)
return function(_, result)
- if not result then return end
+ if not result then
+ return
+ end
local items = {}
for _, call_hierarchy_call in pairs(result) do
local call_hierarchy_item = call_hierarchy_call[direction]
@@ -430,8 +444,8 @@ local make_call_hierarchy_handler = function(direction)
})
end
end
- vim.fn.setqflist({}, ' ', {title = 'LSP call hierarchy', items = items})
- api.nvim_command("botright copen")
+ vim.fn.setqflist({}, ' ', { title = 'LSP call hierarchy', items = items })
+ api.nvim_command('botright copen')
end
end
@@ -447,15 +461,15 @@ M['window/logMessage'] = function(_, result, ctx, _)
local message = result.message
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- local client_name = client and client.name or string.format("id=%d", client_id)
+ local client_name = client and client.name or string.format('id=%d', client_id)
if not client then
- err_message("LSP[", client_name, "] client has shut down after sending ", message)
+ err_message('LSP[', client_name, '] client has shut down after sending ', message)
end
if message_type == protocol.MessageType.Error then
log.error(message)
elseif message_type == protocol.MessageType.Warning then
log.warn(message)
- elseif message_type == protocol.MessageType.Info or message_type == protocol.MessageType.Log then
+ elseif message_type == protocol.MessageType.Info or message_type == protocol.MessageType.Log then
log.info(message)
else
log.debug(message)
@@ -469,15 +483,15 @@ M['window/showMessage'] = function(_, result, ctx, _)
local message = result.message
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- local client_name = client and client.name or string.format("id=%d", client_id)
+ local client_name = client and client.name or string.format('id=%d', client_id)
if not client then
- err_message("LSP[", client_name, "] client has shut down after sending ", message)
+ err_message('LSP[', client_name, '] client has shut down after sending ', message)
end
if message_type == protocol.MessageType.Error then
- err_message("LSP[", client_name, "] ", message)
+ err_message('LSP[', client_name, '] ', message)
else
local message_type_name = protocol.MessageType[message_type]
- api.nvim_out_write(string.format("LSP[%s][%s] %s\n", client_name, message_type_name, message))
+ api.nvim_out_write(string.format('LSP[%s][%s] %s\n', client_name, message_type_name, message))
end
return result
end
@@ -485,9 +499,13 @@ end
-- Add boilerplate error validation and logging for all of these.
for k, fn in pairs(M) do
M[k] = function(err, result, ctx, config)
- local _ = log.trace() and log.trace('default_handler', ctx.method, {
- err = err, result = result, ctx=vim.inspect(ctx), config = config
- })
+ local _ = log.trace()
+ and log.trace('default_handler', ctx.method, {
+ err = err,
+ result = result,
+ ctx = vim.inspect(ctx),
+ config = config,
+ })
if err then
-- LSP spec:
@@ -499,7 +517,7 @@ for k, fn in pairs(M) do
-- Per LSP, don't show ContentModified error to the user.
if err.code ~= protocol.ErrorCodes.ContentModified then
local client = vim.lsp.get_client_by_id(ctx.client_id)
- local client_name = client and client.name or string.format("client_id=%d", ctx.client_id)
+ local client_name = client and client.name or string.format('client_id=%d', ctx.client_id)
err_message(client_name .. ': ' .. tostring(err.code) .. ': ' .. err.message)
end
diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua
index ed3eea59df..74714ebc6b 100644
--- a/runtime/lua/vim/lsp/health.lua
+++ b/runtime/lua/vim/lsp/health.lua
@@ -8,20 +8,19 @@ function M.check()
local log = require('vim.lsp.log')
local current_log_level = log.get_level()
local log_level_string = log.levels[current_log_level]
- report_info(string.format("LSP log level : %s", log_level_string))
+ report_info(string.format('LSP log level : %s', log_level_string))
if current_log_level < log.levels.WARN then
- report_warn(string.format("Log level %s will cause degraded performance and high disk usage", log_level_string))
+ report_warn(string.format('Log level %s will cause degraded performance and high disk usage', log_level_string))
end
local log_path = vim.lsp.get_log_path()
- report_info(string.format("Log path: %s", log_path))
+ report_info(string.format('Log path: %s', log_path))
local log_size = vim.loop.fs_stat(log_path).size
local report_fn = (log_size / 1000000 > 100 and report_warn or report_info)
- report_fn(string.format("Log size: %d KB", log_size / 1000 ))
+ report_fn(string.format('Log size: %d KB', log_size / 1000))
end
return M
-
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index fff42fd011..29cb27d373 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -14,21 +14,23 @@ log.levels = vim.deepcopy(vim.log.levels)
-- Default log level is warn.
local current_log_level = log.levels.WARN
-local log_date_format = "%F %H:%M:%S"
-local format_func = function(arg) return vim.inspect(arg, {newline=''}) end
+local log_date_format = '%F %H:%M:%S'
+local format_func = function(arg)
+ return vim.inspect(arg, { newline = '' })
+end
do
- local path_sep = vim.loop.os_uname().version:match("Windows") and "\\" or "/"
+ local path_sep = vim.loop.os_uname().version:match('Windows') and '\\' or '/'
---@private
local function path_join(...)
- return table.concat(vim.tbl_flatten{...}, path_sep)
+ return table.concat(vim.tbl_flatten({ ... }), path_sep)
end
- local logfilename = path_join(vim.fn.stdpath('cache'), 'lsp.log')
+ local logfilename = path_join(vim.fn.stdpath('log'), 'lsp.log')
-- TODO: Ideally the directory should be created in open_logfile(), right
-- before opening the log file, but open_logfile() can be called from libuv
-- callbacks, where using fn.mkdir() is not allowed.
- vim.fn.mkdir(vim.fn.stdpath('cache'), "p")
+ vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
--- Returns the log filename.
---@returns (string) log filename
@@ -41,28 +43,28 @@ do
--- Opens log file. Returns true if file is open, false on error
local function open_logfile()
-- Try to open file only once
- if logfile then return true end
- if openerr then return false end
+ if logfile then
+ return true
+ end
+ if openerr then
+ return false
+ end
- logfile, openerr = io.open(logfilename, "a+")
+ logfile, openerr = io.open(logfilename, 'a+')
if not logfile then
- local err_msg = string.format("Failed to open LSP client log file: %s", openerr)
+ local err_msg = string.format('Failed to open LSP client log file: %s', openerr)
vim.notify(err_msg, vim.log.levels.ERROR)
return false
end
local log_info = vim.loop.fs_stat(logfilename)
if log_info and log_info.size > 1e9 then
- local warn_msg = string.format(
- "LSP client log is large (%d MB): %s",
- log_info.size / (1000 * 1000),
- logfilename
- )
+ local warn_msg = string.format('LSP client log is large (%d MB): %s', log_info.size / (1000 * 1000), logfilename)
vim.notify(warn_msg)
end
-- Start message for logging
- logfile:write(string.format("[START][%s] LSP logging initiated\n", os.date(log_date_format)))
+ logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format)))
return true
end
@@ -83,24 +85,36 @@ do
-- ```
--
-- This way you can avoid string allocations if the log level isn't high enough.
- if level ~= "OFF" then
+ if level ~= 'OFF' then
log[level:lower()] = function(...)
- local argc = select("#", ...)
- if levelnr < current_log_level then return false end
- if argc == 0 then return true end
- if not open_logfile() then return false end
- local info = debug.getinfo(2, "Sl")
- local header = string.format("[%s][%s] ...%s:%s", level, os.date(log_date_format), string.sub(info.short_src, #info.short_src - 15), info.currentline)
+ local argc = select('#', ...)
+ if levelnr < current_log_level then
+ return false
+ end
+ if argc == 0 then
+ return true
+ end
+ if not open_logfile() then
+ return false
+ end
+ local info = debug.getinfo(2, 'Sl')
+ local header = string.format(
+ '[%s][%s] ...%s:%s',
+ level,
+ os.date(log_date_format),
+ string.sub(info.short_src, #info.short_src - 15),
+ info.currentline
+ )
local parts = { header }
for i = 1, argc do
local arg = select(i, ...)
if arg == nil then
- table.insert(parts, "nil")
+ table.insert(parts, 'nil')
else
table.insert(parts, format_func(arg))
end
end
- logfile:write(table.concat(parts, '\t'), "\n")
+ logfile:write(table.concat(parts, '\t'), '\n')
logfile:flush()
end
end
@@ -115,10 +129,10 @@ vim.tbl_add_reverse_lookup(log.levels)
---@param level (string or number) One of `vim.lsp.log.levels`
function log.set_level(level)
if type(level) == 'string' then
- current_log_level = assert(log.levels[level:upper()], string.format("Invalid log level: %q", level))
+ current_log_level = assert(log.levels[level:upper()], string.format('Invalid log level: %q', level))
else
- assert(type(level) == 'number', "level must be a number or string")
- assert(log.levels[level], string.format("Invalid log level: %d", level))
+ assert(type(level) == 'number', 'level must be a number or string')
+ assert(log.levels[level], string.format('Invalid log level: %d', level))
current_log_level = level
end
end
@@ -132,7 +146,7 @@ end
--- Sets formatting function used to format logs
---@param handle function function to apply to logging arguments, pass vim.inspect for multi-line formatting
function log.set_format_func(handle)
- assert(handle == vim.inspect or type(handle) == 'function', "handle must be a function")
+ assert(handle == vim.inspect or type(handle) == 'function', 'handle must be a function')
format_func = handle
end
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 8f50863360..6ecf7891c7 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -23,150 +23,150 @@ end
local constants = {
DiagnosticSeverity = {
-- Reports an error.
- Error = 1;
+ Error = 1,
-- Reports a warning.
- Warning = 2;
+ Warning = 2,
-- Reports an information.
- Information = 3;
+ Information = 3,
-- Reports a hint.
- Hint = 4;
- };
+ Hint = 4,
+ },
DiagnosticTag = {
-- Unused or unnecessary code
- Unnecessary = 1;
+ Unnecessary = 1,
-- Deprecated or obsolete code
- Deprecated = 2;
- };
+ Deprecated = 2,
+ },
MessageType = {
-- An error message.
- Error = 1;
+ Error = 1,
-- A warning message.
- Warning = 2;
+ Warning = 2,
-- An information message.
- Info = 3;
+ Info = 3,
-- A log message.
- Log = 4;
- };
+ Log = 4,
+ },
-- The file event type.
FileChangeType = {
-- The file got created.
- Created = 1;
+ Created = 1,
-- The file got changed.
- Changed = 2;
+ Changed = 2,
-- The file got deleted.
- Deleted = 3;
- };
+ Deleted = 3,
+ },
-- The kind of a completion entry.
CompletionItemKind = {
- Text = 1;
- Method = 2;
- Function = 3;
- Constructor = 4;
- Field = 5;
- Variable = 6;
- Class = 7;
- Interface = 8;
- Module = 9;
- Property = 10;
- Unit = 11;
- Value = 12;
- Enum = 13;
- Keyword = 14;
- Snippet = 15;
- Color = 16;
- File = 17;
- Reference = 18;
- Folder = 19;
- EnumMember = 20;
- Constant = 21;
- Struct = 22;
- Event = 23;
- Operator = 24;
- TypeParameter = 25;
- };
+ Text = 1,
+ Method = 2,
+ Function = 3,
+ Constructor = 4,
+ Field = 5,
+ Variable = 6,
+ Class = 7,
+ Interface = 8,
+ Module = 9,
+ Property = 10,
+ Unit = 11,
+ Value = 12,
+ Enum = 13,
+ Keyword = 14,
+ Snippet = 15,
+ Color = 16,
+ File = 17,
+ Reference = 18,
+ Folder = 19,
+ EnumMember = 20,
+ Constant = 21,
+ Struct = 22,
+ Event = 23,
+ Operator = 24,
+ TypeParameter = 25,
+ },
-- How a completion was triggered
CompletionTriggerKind = {
-- Completion was triggered by typing an identifier (24x7 code
-- complete), manual invocation (e.g Ctrl+Space) or via API.
- Invoked = 1;
+ Invoked = 1,
-- Completion was triggered by a trigger character specified by
-- the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
- TriggerCharacter = 2;
+ TriggerCharacter = 2,
-- Completion was re-triggered as the current completion list is incomplete.
- TriggerForIncompleteCompletions = 3;
- };
+ TriggerForIncompleteCompletions = 3,
+ },
-- A document highlight kind.
DocumentHighlightKind = {
-- A textual occurrence.
- Text = 1;
+ Text = 1,
-- Read-access of a symbol, like reading a variable.
- Read = 2;
+ Read = 2,
-- Write-access of a symbol, like writing to a variable.
- Write = 3;
- };
+ Write = 3,
+ },
-- A symbol kind.
SymbolKind = {
- File = 1;
- Module = 2;
- Namespace = 3;
- Package = 4;
- Class = 5;
- Method = 6;
- Property = 7;
- Field = 8;
- Constructor = 9;
- Enum = 10;
- Interface = 11;
- Function = 12;
- Variable = 13;
- Constant = 14;
- String = 15;
- Number = 16;
- Boolean = 17;
- Array = 18;
- Object = 19;
- Key = 20;
- Null = 21;
- EnumMember = 22;
- Struct = 23;
- Event = 24;
- Operator = 25;
- TypeParameter = 26;
- };
+ File = 1,
+ Module = 2,
+ Namespace = 3,
+ Package = 4,
+ Class = 5,
+ Method = 6,
+ Property = 7,
+ Field = 8,
+ Constructor = 9,
+ Enum = 10,
+ Interface = 11,
+ Function = 12,
+ Variable = 13,
+ Constant = 14,
+ String = 15,
+ Number = 16,
+ Boolean = 17,
+ Array = 18,
+ Object = 19,
+ Key = 20,
+ Null = 21,
+ EnumMember = 22,
+ Struct = 23,
+ Event = 24,
+ Operator = 25,
+ TypeParameter = 26,
+ },
-- Represents reasons why a text document is saved.
TextDocumentSaveReason = {
-- Manually triggered, e.g. by the user pressing save, by starting debugging,
-- or by an API call.
- Manual = 1;
+ Manual = 1,
-- Automatic after a delay.
- AfterDelay = 2;
+ AfterDelay = 2,
-- When the editor lost focus.
- FocusOut = 3;
- };
+ FocusOut = 3,
+ },
ErrorCodes = {
-- Defined by JSON RPC
- ParseError = -32700;
- InvalidRequest = -32600;
- MethodNotFound = -32601;
- InvalidParams = -32602;
- InternalError = -32603;
- serverErrorStart = -32099;
- serverErrorEnd = -32000;
- ServerNotInitialized = -32002;
- UnknownErrorCode = -32001;
+ ParseError = -32700,
+ InvalidRequest = -32600,
+ MethodNotFound = -32601,
+ InvalidParams = -32602,
+ InternalError = -32603,
+ serverErrorStart = -32099,
+ serverErrorEnd = -32000,
+ ServerNotInitialized = -32002,
+ UnknownErrorCode = -32001,
-- Defined by the protocol.
- RequestCancelled = -32800;
- ContentModified = -32801;
- };
+ RequestCancelled = -32800,
+ ContentModified = -32801,
+ },
-- Describes the content type that a client supports in various
-- result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
@@ -175,88 +175,88 @@ local constants = {
-- are reserved for internal usage.
MarkupKind = {
-- Plain text is supported as a content format
- PlainText = 'plaintext';
+ PlainText = 'plaintext',
-- Markdown is supported as a content format
- Markdown = 'markdown';
- };
+ Markdown = 'markdown',
+ },
ResourceOperationKind = {
-- Supports creating new files and folders.
- Create = 'create';
+ Create = 'create',
-- Supports renaming existing files and folders.
- Rename = 'rename';
+ Rename = 'rename',
-- Supports deleting existing files and folders.
- Delete = 'delete';
- };
+ Delete = 'delete',
+ },
FailureHandlingKind = {
-- Applying the workspace change is simply aborted if one of the changes provided
-- fails. All operations executed before the failing operation stay executed.
- Abort = 'abort';
+ Abort = 'abort',
-- All operations are executed transactionally. That means they either all
-- succeed or no changes at all are applied to the workspace.
- Transactional = 'transactional';
+ Transactional = 'transactional',
-- If the workspace edit contains only textual file changes they are executed transactionally.
-- If resource changes (create, rename or delete file) are part of the change the failure
-- handling strategy is abort.
- TextOnlyTransactional = 'textOnlyTransactional';
+ TextOnlyTransactional = 'textOnlyTransactional',
-- The client tries to undo the operations already executed. But there is no
-- guarantee that this succeeds.
- Undo = 'undo';
- };
+ Undo = 'undo',
+ },
-- Known error codes for an `InitializeError`;
InitializeError = {
-- If the protocol version provided by the client can't be handled by the server.
-- @deprecated This initialize error got replaced by client capabilities. There is
-- no version handshake in version 3.0x
- unknownProtocolVersion = 1;
- };
+ unknownProtocolVersion = 1,
+ },
-- Defines how the host (editor) should sync document changes to the language server.
TextDocumentSyncKind = {
-- Documents should not be synced at all.
- None = 0;
+ None = 0,
-- Documents are synced by always sending the full content
-- of the document.
- Full = 1;
+ Full = 1,
-- Documents are synced by sending the full content on open.
-- After that only incremental updates to the document are
-- send.
- Incremental = 2;
- };
+ Incremental = 2,
+ },
WatchKind = {
-- Interested in create events.
- Create = 1;
+ Create = 1,
-- Interested in change events
- Change = 2;
+ Change = 2,
-- Interested in delete events
- Delete = 4;
- };
+ Delete = 4,
+ },
-- Defines whether the insert text in a completion item should be interpreted as
-- plain text or a snippet.
InsertTextFormat = {
-- The primary text to be inserted is treated as a plain string.
- PlainText = 1;
+ PlainText = 1,
-- The primary text to be inserted is treated as a snippet.
--
-- A snippet can define tab stops and placeholders with `$1`, `$2`
-- and `${3:foo};`. `$0` defines the final tab stop, it defaults to
-- the end of the snippet. Placeholders with equal identifiers are linked,
-- that is typing in one will update others too.
- Snippet = 2;
- };
+ Snippet = 2,
+ },
-- A set of predefined code action kinds
CodeActionKind = {
-- Empty kind.
- Empty = '';
+ Empty = '',
-- Base kind for quickfix actions
- QuickFix = 'quickfix';
+ QuickFix = 'quickfix',
-- Base kind for refactoring actions
- Refactor = 'refactor';
+ Refactor = 'refactor',
-- Base kind for refactoring extraction actions
--
-- Example extract actions:
@@ -266,7 +266,7 @@ local constants = {
-- - Extract variable
-- - Extract interface from class
-- - ...
- RefactorExtract = 'refactor.extract';
+ RefactorExtract = 'refactor.extract',
-- Base kind for refactoring inline actions
--
-- Example inline actions:
@@ -275,7 +275,7 @@ local constants = {
-- - Inline variable
-- - Inline constant
-- - ...
- RefactorInline = 'refactor.inline';
+ RefactorInline = 'refactor.inline',
-- Base kind for refactoring rewrite actions
--
-- Example rewrite actions:
@@ -286,14 +286,14 @@ local constants = {
-- - Make method static
-- - Move method to base class
-- - ...
- RefactorRewrite = 'refactor.rewrite';
+ RefactorRewrite = 'refactor.rewrite',
-- Base kind for source actions
--
-- Source code actions apply to the entire file.
- Source = 'source';
+ Source = 'source',
-- Base kind for an organize imports source action
- SourceOrganizeImports = 'source.organizeImports';
- };
+ SourceOrganizeImports = 'source.organizeImports',
+ },
}
for k, v in pairs(constants) do
@@ -620,19 +620,19 @@ function protocol.make_client_capabilities()
return {
textDocument = {
synchronization = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
-- TODO(ashkan) Send textDocument/willSave before saving (BufWritePre)
- willSave = false;
+ willSave = false,
-- TODO(ashkan) Implement textDocument/willSaveWaitUntil
- willSaveWaitUntil = false;
+ willSaveWaitUntil = false,
-- Send textDocument/didSave after saving (BufWritePost)
- didSave = true;
- };
+ didSave = true,
+ },
codeAction = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
codeActionLiteralSupport = {
codeActionKind = {
@@ -640,138 +640,146 @@ function protocol.make_client_capabilities()
local res = vim.tbl_values(protocol.CodeActionKind)
table.sort(res)
return res
- end)();
- };
- };
- isPreferredSupport = true;
- dataSupport = true;
+ end)(),
+ },
+ },
+ isPreferredSupport = true,
+ dataSupport = true,
resolveSupport = {
- properties = { 'edit', }
- };
- };
+ properties = { 'edit' },
+ },
+ },
completion = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
completionItem = {
-- Until we can actually expand snippet, move cursor and allow for true snippet experience,
-- this should be disabled out of the box.
-- However, users can turn this back on if they have a snippet plugin.
- snippetSupport = false;
+ snippetSupport = false,
- commitCharactersSupport = false;
- preselectSupport = false;
- deprecatedSupport = false;
- documentationFormat = { protocol.MarkupKind.Markdown; protocol.MarkupKind.PlainText };
- };
+ commitCharactersSupport = false,
+ preselectSupport = false,
+ deprecatedSupport = false,
+ documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
+ },
completionItemKind = {
valueSet = (function()
local res = {}
for k in ipairs(protocol.CompletionItemKind) do
- if type(k) == 'number' then table.insert(res, k) end
+ if type(k) == 'number' then
+ table.insert(res, k)
+ end
end
return res
- end)();
- };
+ end)(),
+ },
-- TODO(tjdevries): Implement this
- contextSupport = false;
- };
+ contextSupport = false,
+ },
declaration = {
- linkSupport = true;
- };
+ linkSupport = true,
+ },
definition = {
- linkSupport = true;
- };
+ linkSupport = true,
+ },
implementation = {
- linkSupport = true;
- };
+ linkSupport = true,
+ },
typeDefinition = {
- linkSupport = true;
- };
+ linkSupport = true,
+ },
hover = {
- dynamicRegistration = false;
- contentFormat = { protocol.MarkupKind.Markdown; protocol.MarkupKind.PlainText };
- };
+ dynamicRegistration = false,
+ contentFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
+ },
signatureHelp = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
signatureInformation = {
- activeParameterSupport = true;
- documentationFormat = { protocol.MarkupKind.Markdown; protocol.MarkupKind.PlainText };
+ activeParameterSupport = true,
+ documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
parameterInformation = {
- labelOffsetSupport = true;
- };
- };
- };
+ labelOffsetSupport = true,
+ },
+ },
+ },
references = {
- dynamicRegistration = false;
- };
+ dynamicRegistration = false,
+ },
documentHighlight = {
- dynamicRegistration = false
- };
+ dynamicRegistration = false,
+ },
documentSymbol = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
symbolKind = {
valueSet = (function()
local res = {}
for k in ipairs(protocol.SymbolKind) do
- if type(k) == 'number' then table.insert(res, k) end
+ if type(k) == 'number' then
+ table.insert(res, k)
+ end
end
return res
- end)();
- };
- hierarchicalDocumentSymbolSupport = true;
- };
+ end)(),
+ },
+ hierarchicalDocumentSymbolSupport = true,
+ },
rename = {
- dynamicRegistration = false;
- prepareSupport = true;
- };
+ dynamicRegistration = false,
+ prepareSupport = true,
+ },
publishDiagnostics = {
- relatedInformation = true;
+ relatedInformation = true,
tagSupport = {
valueSet = (function()
local res = {}
for k in ipairs(protocol.DiagnosticTag) do
- if type(k) == 'number' then table.insert(res, k) end
+ if type(k) == 'number' then
+ table.insert(res, k)
+ end
end
return res
- end)();
- };
- };
- };
+ end)(),
+ },
+ },
+ },
workspace = {
symbol = {
- dynamicRegistration = false;
+ dynamicRegistration = false,
symbolKind = {
valueSet = (function()
local res = {}
for k in ipairs(protocol.SymbolKind) do
- if type(k) == 'number' then table.insert(res, k) end
+ if type(k) == 'number' then
+ table.insert(res, k)
+ end
end
return res
- end)();
- };
- hierarchicalWorkspaceSymbolSupport = true;
- };
- workspaceFolders = true;
- applyEdit = true;
+ end)(),
+ },
+ hierarchicalWorkspaceSymbolSupport = true,
+ },
+ workspaceFolders = true,
+ applyEdit = true,
workspaceEdit = {
- resourceOperations = {'rename', 'create', 'delete',},
- };
- };
+ resourceOperations = { 'rename', 'create', 'delete' },
+ },
+ },
callHierarchy = {
- dynamicRegistration = false;
- };
- experimental = nil;
+ dynamicRegistration = false,
+ },
+ experimental = nil,
window = {
- workDoneProgress = true;
+ workDoneProgress = true,
showMessage = {
messageActionItem = {
- additionalPropertiesSupport = false;
- };
- };
+ additionalPropertiesSupport = false,
+ },
+ },
showDocument = {
- support = false;
- };
- };
+ support = false,
+ },
+ },
}
end
@@ -791,12 +799,12 @@ function protocol.resolve_capabilities(server_capabilities)
willSaveWaitUntil = false,
save = {
includeText = false,
- }
+ },
}
elseif type(textDocumentSync) == 'number' then
-- Backwards compatibility
if not TextDocumentSyncKind[textDocumentSync] then
- return nil, "Invalid server TextDocumentSyncKind for textDocumentSync"
+ return nil, 'Invalid server TextDocumentSyncKind for textDocumentSync'
end
server_capabilities.textDocumentSync = {
openClose = true,
@@ -805,10 +813,10 @@ function protocol.resolve_capabilities(server_capabilities)
willSaveWaitUntil = false,
save = {
includeText = false,
- }
+ },
}
elseif type(textDocumentSync) ~= 'table' then
- return nil, string.format("Invalid type for textDocumentSync: %q", type(textDocumentSync))
+ return nil, string.format('Invalid type for textDocumentSync: %q', type(textDocumentSync))
end
return server_capabilities
end
@@ -827,39 +835,41 @@ function protocol._resolve_capabilities_compat(server_capabilities)
if textDocumentSync == nil then
-- Defaults if omitted.
text_document_sync_properties = {
- text_document_open_close = false;
- text_document_did_change = TextDocumentSyncKind.None;
--- text_document_did_change = false;
- text_document_will_save = false;
- text_document_will_save_wait_until = false;
- text_document_save = false;
- text_document_save_include_text = false;
+ text_document_open_close = false,
+ text_document_did_change = TextDocumentSyncKind.None,
+ -- text_document_did_change = false;
+ text_document_will_save = false,
+ text_document_will_save_wait_until = false,
+ text_document_save = false,
+ text_document_save_include_text = false,
}
elseif type(textDocumentSync) == 'number' then
-- Backwards compatibility
if not TextDocumentSyncKind[textDocumentSync] then
- return nil, "Invalid server TextDocumentSyncKind for textDocumentSync"
+ return nil, 'Invalid server TextDocumentSyncKind for textDocumentSync'
end
text_document_sync_properties = {
- text_document_open_close = true;
- text_document_did_change = textDocumentSync;
- text_document_will_save = false;
- text_document_will_save_wait_until = false;
- text_document_save = true;
- text_document_save_include_text = false;
+ text_document_open_close = true,
+ text_document_did_change = textDocumentSync,
+ text_document_will_save = false,
+ text_document_will_save_wait_until = false,
+ text_document_save = true,
+ text_document_save_include_text = false,
}
elseif type(textDocumentSync) == 'table' then
text_document_sync_properties = {
- text_document_open_close = if_nil(textDocumentSync.openClose, false);
- text_document_did_change = if_nil(textDocumentSync.change, TextDocumentSyncKind.None);
- text_document_will_save = if_nil(textDocumentSync.willSave, false);
- text_document_will_save_wait_until = if_nil(textDocumentSync.willSaveWaitUntil, false);
- text_document_save = if_nil(textDocumentSync.save, false);
- text_document_save_include_text = if_nil(type(textDocumentSync.save) == 'table'
- and textDocumentSync.save.includeText, false);
+ text_document_open_close = if_nil(textDocumentSync.openClose, false),
+ text_document_did_change = if_nil(textDocumentSync.change, TextDocumentSyncKind.None),
+ text_document_will_save = if_nil(textDocumentSync.willSave, false),
+ text_document_will_save_wait_until = if_nil(textDocumentSync.willSaveWaitUntil, false),
+ text_document_save = if_nil(textDocumentSync.save, false),
+ text_document_save_include_text = if_nil(
+ type(textDocumentSync.save) == 'table' and textDocumentSync.save.includeText,
+ false
+ ),
}
else
- return nil, string.format("Invalid type for textDocumentSync: %q", type(textDocumentSync))
+ return nil, string.format('Invalid type for textDocumentSync: %q', type(textDocumentSync))
end
end
general_properties.completion = server_capabilities.completionProvider ~= nil
@@ -889,16 +899,18 @@ function protocol._resolve_capabilities_compat(server_capabilities)
general_properties.code_lens = true
general_properties.code_lens_resolve = server_capabilities.codeLensProvider.resolveProvider or false
else
- error("The server sent invalid codeLensProvider")
+ error('The server sent invalid codeLensProvider')
end
if server_capabilities.codeActionProvider == nil then
general_properties.code_action = false
- elseif type(server_capabilities.codeActionProvider) == 'boolean'
- or type(server_capabilities.codeActionProvider) == 'table' then
+ elseif
+ type(server_capabilities.codeActionProvider) == 'boolean'
+ or type(server_capabilities.codeActionProvider) == 'table'
+ then
general_properties.code_action = server_capabilities.codeActionProvider
else
- error("The server sent invalid codeActionProvider")
+ error('The server sent invalid codeActionProvider')
end
if server_capabilities.declarationProvider == nil then
@@ -908,7 +920,7 @@ function protocol._resolve_capabilities_compat(server_capabilities)
elseif type(server_capabilities.declarationProvider) == 'table' then
general_properties.declaration = server_capabilities.declarationProvider
else
- error("The server sent invalid declarationProvider")
+ error('The server sent invalid declarationProvider')
end
if server_capabilities.typeDefinitionProvider == nil then
@@ -918,7 +930,7 @@ function protocol._resolve_capabilities_compat(server_capabilities)
elseif type(server_capabilities.typeDefinitionProvider) == 'table' then
general_properties.type_definition = server_capabilities.typeDefinitionProvider
else
- error("The server sent invalid typeDefinitionProvider")
+ error('The server sent invalid typeDefinitionProvider')
end
if server_capabilities.implementationProvider == nil then
@@ -928,7 +940,7 @@ function protocol._resolve_capabilities_compat(server_capabilities)
elseif type(server_capabilities.implementationProvider) == 'table' then
general_properties.implementation = server_capabilities.implementationProvider
else
- error("The server sent invalid implementationProvider")
+ error('The server sent invalid implementationProvider')
end
local workspace = server_capabilities.workspace
@@ -936,45 +948,45 @@ function protocol._resolve_capabilities_compat(server_capabilities)
if workspace == nil or workspace.workspaceFolders == nil then
-- Defaults if omitted.
workspace_properties = {
- workspace_folder_properties = {
- supported = false;
- changeNotifications=false;
- }
+ workspace_folder_properties = {
+ supported = false,
+ changeNotifications = false,
+ },
}
elseif type(workspace.workspaceFolders) == 'table' then
workspace_properties = {
workspace_folder_properties = {
- supported = if_nil(workspace.workspaceFolders.supported, false);
- changeNotifications = if_nil(workspace.workspaceFolders.changeNotifications, false);
-
- }
+ supported = if_nil(workspace.workspaceFolders.supported, false),
+ changeNotifications = if_nil(workspace.workspaceFolders.changeNotifications, false),
+ },
}
else
- error("The server sent invalid workspace")
+ error('The server sent invalid workspace')
end
local signature_help_properties
if server_capabilities.signatureHelpProvider == nil then
signature_help_properties = {
- signature_help = false;
- signature_help_trigger_characters = {};
+ signature_help = false,
+ signature_help_trigger_characters = {},
}
elseif type(server_capabilities.signatureHelpProvider) == 'table' then
signature_help_properties = {
- signature_help = true;
+ signature_help = true,
-- The characters that trigger signature help automatically.
- signature_help_trigger_characters = server_capabilities.signatureHelpProvider.triggerCharacters or {};
+ signature_help_trigger_characters = server_capabilities.signatureHelpProvider.triggerCharacters or {},
}
else
- error("The server sent invalid signatureHelpProvider")
+ error('The server sent invalid signatureHelpProvider')
end
- local capabilities = vim.tbl_extend("error"
- , text_document_sync_properties
- , signature_help_properties
- , workspace_properties
- , general_properties
- )
+ local capabilities = vim.tbl_extend(
+ 'error',
+ text_document_sync_properties,
+ signature_help_properties,
+ workspace_properties,
+ general_properties
+ )
return capabilities
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index be2cc58f07..2dcafc92bc 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -32,9 +32,9 @@ local function env_merge(env)
-- Merge.
env = vim.tbl_extend('force', vim.fn.environ(), env)
local final_env = {}
- for k,v in pairs(env) do
+ for k, v in pairs(env) do
assert(type(k) == 'string', 'env must be a dict')
- table.insert(final_env, k..'='..tostring(v))
+ table.insert(final_env, k .. '=' .. tostring(v))
end
return final_env
end
@@ -45,10 +45,12 @@ end
---@param encoded_message (string)
---@returns (table) table containing encoded message and `Content-Length` attribute
local function format_message_with_content_length(encoded_message)
- return table.concat {
- 'Content-Length: '; tostring(#encoded_message); '\r\n\r\n';
- encoded_message;
- }
+ return table.concat({
+ 'Content-Length: ',
+ tostring(#encoded_message),
+ '\r\n\r\n',
+ encoded_message,
+ })
end
---@private
@@ -65,23 +67,25 @@ local function parse_headers(header)
if line == '' then
break
end
- local key, value = line:match("^%s*(%S+)%s*:%s*(.+)%s*$")
+ local key, value = line:match('^%s*(%S+)%s*:%s*(.+)%s*$')
if key then
key = key:lower():gsub('%-', '_')
headers[key] = value
else
- local _ = log.error() and log.error("invalid header line %q", line)
- error(string.format("invalid header line %q", line))
+ local _ = log.error() and log.error('invalid header line %q', line)
+ error(string.format('invalid header line %q', line))
end
end
headers.content_length = tonumber(headers.content_length)
- or error(string.format("Content-Length not found in headers. %q", header))
+ or error(string.format('Content-Length not found in headers. %q', header))
return headers
end
-- This is the start of any possible header patterns. The gsub converts it to a
-- case insensitive pattern.
-local header_start_pattern = ("content"):gsub("%w", function(c) return "["..c..c:upper().."]" end)
+local header_start_pattern = ('content'):gsub('%w', function(c)
+ return '[' .. c .. c:upper() .. ']'
+end)
---@private
--- The actual workhorse.
@@ -100,17 +104,16 @@ local function request_parser_loop()
-- be searching for.
-- TODO(ashkan) I'd like to remove this, but it seems permanent :(
local buffer_start = buffer:find(header_start_pattern)
- local headers = parse_headers(buffer:sub(buffer_start, start-1))
+ local headers = parse_headers(buffer:sub(buffer_start, start - 1))
local content_length = headers.content_length
-- Use table instead of just string to buffer the message. It prevents
-- a ton of strings allocating.
-- ref. http://www.lua.org/pil/11.6.html
- local body_chunks = {buffer:sub(finish+1)}
+ local body_chunks = { buffer:sub(finish + 1) }
local body_length = #body_chunks[1]
-- Keep waiting for data until we have enough.
while body_length < content_length do
- local chunk = coroutine.yield()
- or error("Expected more data for the body. The server may have died.") -- TODO hmm.
+ local chunk = coroutine.yield() or error('Expected more data for the body. The server may have died.') -- TODO hmm.
table.insert(body_chunks, chunk)
body_length = body_length + #chunk
end
@@ -123,25 +126,24 @@ local function request_parser_loop()
end
local body = table.concat(body_chunks)
-- Yield our data.
- buffer = rest..(coroutine.yield(headers, body)
- or error("Expected more data for the body. The server may have died.")) -- TODO hmm.
+ buffer = rest
+ .. (coroutine.yield(headers, body) or error('Expected more data for the body. The server may have died.')) -- TODO hmm.
else
-- Get more data since we don't have enough.
- buffer = buffer..(coroutine.yield()
- or error("Expected more data for the header. The server may have died.")) -- TODO hmm.
+ buffer = buffer .. (coroutine.yield() or error('Expected more data for the header. The server may have died.')) -- TODO hmm.
end
end
end
--- Mapping of error codes used by the client
local client_errors = {
- INVALID_SERVER_MESSAGE = 1;
- INVALID_SERVER_JSON = 2;
- NO_RESULT_CALLBACK_FOUND = 3;
- READ_ERROR = 4;
- NOTIFICATION_HANDLER_ERROR = 5;
- SERVER_REQUEST_HANDLER_ERROR = 6;
- SERVER_RESULT_CALLBACK_ERROR = 7;
+ INVALID_SERVER_MESSAGE = 1,
+ INVALID_SERVER_JSON = 2,
+ NO_RESULT_CALLBACK_FOUND = 3,
+ READ_ERROR = 4,
+ NOTIFICATION_HANDLER_ERROR = 5,
+ SERVER_REQUEST_HANDLER_ERROR = 6,
+ SERVER_RESULT_CALLBACK_ERROR = 7,
}
client_errors = vim.tbl_add_reverse_lookup(client_errors)
@@ -151,26 +153,26 @@ client_errors = vim.tbl_add_reverse_lookup(client_errors)
---@param err (table) The error object
---@returns (string) The formatted error message
local function format_rpc_error(err)
- validate {
- err = { err, 't' };
- }
+ validate({
+ err = { err, 't' },
+ })
-- There is ErrorCodes in the LSP specification,
-- but in ResponseError.code it is not used and the actual type is number.
local code
if protocol.ErrorCodes[err.code] then
- code = string.format("code_name = %s,", protocol.ErrorCodes[err.code])
+ code = string.format('code_name = %s,', protocol.ErrorCodes[err.code])
else
- code = string.format("code_name = unknown, code = %s,", err.code)
+ code = string.format('code_name = unknown, code = %s,', err.code)
end
- local message_parts = {"RPC[Error]", code}
+ local message_parts = { 'RPC[Error]', code }
if err.message then
- table.insert(message_parts, "message =")
- table.insert(message_parts, string.format("%q", err.message))
+ table.insert(message_parts, 'message =')
+ table.insert(message_parts, string.format('%q', err.message))
end
if err.data then
- table.insert(message_parts, "data =")
+ table.insert(message_parts, 'data =')
table.insert(message_parts, vim.inspect(err.data))
end
return table.concat(message_parts, ' ')
@@ -185,11 +187,11 @@ local function rpc_response_error(code, message, data)
-- TODO should this error or just pick a sane error (like InternalError)?
local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code')
return setmetatable({
- code = code;
- message = message or code_name;
- data = data;
+ code = code,
+ message = message or code_name,
+ data = data,
}, {
- __tostring = format_rpc_error;
+ __tostring = format_rpc_error,
})
end
@@ -220,7 +222,7 @@ end
---@param signal (number): Number describing the signal used to terminate (if
---any)
function default_dispatchers.on_exit(code, signal)
- local _ = log.info() and log.info("client_exit", { code = code, signal = signal })
+ local _ = log.info() and log.info('client_exit', { code = code, signal = signal })
end
---@private
--- Default dispatcher for client errors.
@@ -258,15 +260,15 @@ end
--- - {handle} A handle for low-level interaction with the LSP server process
--- |vim.loop|.
local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
- local _ = log.info() and log.info("Starting RPC client", {cmd = cmd, args = cmd_args, extra = extra_spawn_params})
- validate {
- cmd = { cmd, 's' };
- cmd_args = { cmd_args, 't' };
- dispatchers = { dispatchers, 't', true };
- }
+ local _ = log.info() and log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params })
+ validate({
+ cmd = { cmd, 's' },
+ cmd_args = { cmd_args, 't' },
+ dispatchers = { dispatchers, 't', true },
+ })
if extra_spawn_params and extra_spawn_params.cwd then
- assert(is_dir(extra_spawn_params.cwd), "cwd must be a directory")
+ assert(is_dir(extra_spawn_params.cwd), 'cwd must be a directory')
end
if dispatchers then
local user_dispatchers = dispatchers
@@ -275,11 +277,11 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
local user_dispatcher = user_dispatchers[dispatch_name]
if user_dispatcher then
if type(user_dispatcher) ~= 'function' then
- error(string.format("dispatcher.%s must be a function", dispatch_name))
+ error(string.format('dispatcher.%s must be a function', dispatch_name))
end
-- server_request is wrapped elsewhere.
- if not (dispatch_name == 'server_request'
- or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason.
+ if
+ not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason.
then
user_dispatcher = schedule_wrap(user_dispatcher)
end
@@ -317,9 +319,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
dispatchers.on_exit(code, signal)
end
local spawn_params = {
- args = cmd_args;
- stdio = {stdin, stdout, stderr};
- detached = true;
+ args = cmd_args,
+ stdio = { stdin, stdout, stderr },
+ detached = true,
}
if extra_spawn_params then
spawn_params.cwd = extra_spawn_params.cwd
@@ -330,11 +332,11 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
handle, pid = uv.spawn(cmd, spawn_params, onexit)
if handle == nil then
- local msg = string.format("Spawning language server with cmd: `%s` failed", cmd)
- if string.match(pid, "ENOENT") then
- msg = msg .. ". The language server is either not installed, missing from PATH, or not executable."
+ local msg = string.format('Spawning language server with cmd: `%s` failed', cmd)
+ if string.match(pid, 'ENOENT') then
+ msg = msg .. '. The language server is either not installed, missing from PATH, or not executable.'
else
- msg = msg .. string.format(" with error message: %s", pid)
+ msg = msg .. string.format(' with error message: %s', pid)
end
vim.notify(msg, vim.log.levels.WARN)
return
@@ -348,8 +350,10 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
---@param payload table
---@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing.
local function encode_and_send(payload)
- local _ = log.debug() and log.debug("rpc.send", payload)
- if handle == nil or handle:is_closing() then return false end
+ local _ = log.debug() and log.debug('rpc.send', payload)
+ if handle == nil or handle:is_closing() then
+ return false
+ end
local encoded = vim.json.encode(payload)
stdin:write(format_message_with_content_length(encoded))
return true
@@ -363,22 +367,22 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
---@param params (table): Parameters for the invoked LSP method
---@returns (bool) `true` if notification could be sent, `false` if not
local function notify(method, params)
- return encode_and_send {
- jsonrpc = "2.0";
- method = method;
- params = params;
- }
+ return encode_and_send({
+ jsonrpc = '2.0',
+ method = method,
+ params = params,
+ })
end
---@private
--- sends an error object to the remote LSP process.
local function send_response(request_id, err, result)
- return encode_and_send {
- id = request_id;
- jsonrpc = "2.0";
- error = err;
- result = result;
- }
+ return encode_and_send({
+ id = request_id,
+ jsonrpc = '2.0',
+ error = err,
+ result = result,
+ })
end
-- FIXME: DOC: Should be placed on the RPC client object returned by
@@ -392,18 +396,18 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
local function request(method, params, callback, notify_reply_callback)
- validate {
- callback = { callback, 'f' };
- notify_reply_callback = { notify_reply_callback, 'f', true };
- }
+ validate({
+ callback = { callback, 'f' },
+ notify_reply_callback = { notify_reply_callback, 'f', true },
+ })
message_index = message_index + 1
local message_id = message_index
- local result = encode_and_send {
- id = message_id;
- jsonrpc = "2.0";
- method = method;
- params = params;
- }
+ local result = encode_and_send({
+ id = message_id,
+ jsonrpc = '2.0',
+ method = method,
+ params = params,
+ })
if result then
if message_callbacks then
message_callbacks[message_id] = schedule_wrap(callback)
@@ -421,7 +425,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
stderr:read_start(function(_err, chunk)
if chunk then
- local _ = log.error() and log.error("rpc", cmd, "stderr", chunk)
+ local _ = log.error() and log.error('rpc', cmd, 'stderr', chunk)
end
end)
@@ -455,7 +459,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
on_error(client_errors.INVALID_SERVER_JSON, decoded)
return
end
- local _ = log.debug() and log.debug("rpc.receive", decoded)
+ local _ = log.debug() and log.debug('rpc.receive', decoded)
if type(decoded.method) == 'string' and decoded.id then
local err
@@ -463,17 +467,30 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
-- we can still use the result.
schedule(function()
local status, result
- status, result, err = try_call(client_errors.SERVER_REQUEST_HANDLER_ERROR,
- dispatchers.server_request, decoded.method, decoded.params)
- local _ = log.debug() and log.debug("server_request: callback result", { status = status, result = result, err = err })
+ status, result, err = try_call(
+ client_errors.SERVER_REQUEST_HANDLER_ERROR,
+ dispatchers.server_request,
+ decoded.method,
+ decoded.params
+ )
+ local _ = log.debug()
+ and log.debug('server_request: callback result', { status = status, result = result, err = err })
if status then
if not (result or err) then
-- TODO this can be a problem if `null` is sent for result. needs vim.NIL
- error(string.format("method %q: either a result or an error must be sent to the server in response", decoded.method))
+ error(
+ string.format(
+ 'method %q: either a result or an error must be sent to the server in response',
+ decoded.method
+ )
+ )
end
if err then
- assert(type(err) == 'table', "err must be a table. Use rpc_response_error to help format errors.")
- local code_name = assert(protocol.ErrorCodes[err.code], "Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.")
+ assert(type(err) == 'table', 'err must be a table. Use rpc_response_error to help format errors.')
+ local code_name = assert(
+ protocol.ErrorCodes[err.code],
+ 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.'
+ )
err.message = err.message or code_name
end
else
@@ -483,18 +500,17 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
send_response(decoded.id, err, result)
end)
- -- This works because we are expecting vim.NIL here
+ -- This works because we are expecting vim.NIL here
elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then
-
-- We sent a number, so we expect a number.
local result_id = tonumber(decoded.id)
-- Notify the user that a response was received for the request
local notify_reply_callback = notify_reply_callbacks and notify_reply_callbacks[result_id]
if notify_reply_callback then
- validate {
- notify_reply_callback = { notify_reply_callback, 'f' };
- }
+ validate({
+ notify_reply_callback = { notify_reply_callback, 'f' },
+ })
notify_reply_callback(result_id)
notify_reply_callbacks[result_id] = nil
end
@@ -503,7 +519,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
if decoded.error then
local mute_error = false
if decoded.error.code == protocol.ErrorCodes.RequestCancelled then
- local _ = log.debug() and log.debug("Received cancellation ack", decoded)
+ local _ = log.debug() and log.debug('Received cancellation ack', decoded)
mute_error = true
end
@@ -523,24 +539,22 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
local callback = message_callbacks and message_callbacks[result_id]
if callback then
message_callbacks[result_id] = nil
- validate {
- callback = { callback, 'f' };
- }
+ validate({
+ callback = { callback, 'f' },
+ })
if decoded.error then
decoded.error = setmetatable(decoded.error, {
- __tostring = format_rpc_error;
+ __tostring = format_rpc_error,
})
end
- try_call(client_errors.SERVER_RESULT_CALLBACK_ERROR,
- callback, decoded.error, decoded.result)
+ try_call(client_errors.SERVER_RESULT_CALLBACK_ERROR, callback, decoded.error, decoded.result)
else
on_error(client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
- local _ = log.error() and log.error("No callback found for server response id "..result_id)
+ local _ = log.error() and log.error('No callback found for server response id ' .. result_id)
end
elseif type(decoded.method) == 'string' then
-- Notification
- try_call(client_errors.NOTIFICATION_HANDLER_ERROR,
- dispatchers.notification, decoded.method, decoded.params)
+ try_call(client_errors.NOTIFICATION_HANDLER_ERROR, dispatchers.notification, decoded.method, decoded.params)
else
-- Invalid server message
on_error(client_errors.INVALID_SERVER_MESSAGE, decoded)
@@ -556,7 +570,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
return
end
-- This should signal that we are done reading from the client.
- if not chunk then return end
+ if not chunk then
+ return
+ end
-- Flush anything in the parser by looping until we don't get a result
-- anymore.
while true do
@@ -574,17 +590,17 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end)
return {
- pid = pid;
- handle = handle;
- request = request;
- notify = notify
+ pid = pid,
+ handle = handle,
+ request = request,
+ notify = notify,
}
end
return {
- start = start;
- rpc_response_error = rpc_response_error;
- format_rpc_error = format_rpc_error;
- client_errors = client_errors;
+ start = start,
+ rpc_response_error = rpc_response_error,
+ format_rpc_error = format_rpc_error,
+ client_errors = client_errors,
}
-- vim:sw=2 ts=2 et
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index 9955fff3e2..73b4e0025a 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -79,7 +79,7 @@ local function compute_line_length(line, offset_encoding)
local length
local _
if offset_encoding == 'utf-16' then
- _, length = str_utfindex(line)
+ _, length = str_utfindex(line)
elseif offset_encoding == 'utf-32' then
length, _ = str_utfindex(line)
else
@@ -100,7 +100,7 @@ local function align_end_position(line, byte, offset_encoding)
-- If on the first byte, or an empty string: the trivial case
if byte == 1 or #line == 0 then
char = byte
- -- Called in the case of extending an empty line "" -> "a"
+ -- Called in the case of extending an empty line "" -> "a"
elseif byte == #line + 1 then
char = compute_line_length(line, offset_encoding) + 1
else
@@ -175,12 +175,12 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline,
end
-- Convert byte to codepoint if applicable
- if start_byte_idx == 1 or (#prev_line == 0 and start_byte_idx == 1)then
+ if start_byte_idx == 1 or (#prev_line == 0 and start_byte_idx == 1) then
byte_idx = start_byte_idx
char_idx = 1
elseif start_byte_idx == #prev_line + 1 then
byte_idx = start_byte_idx
- char_idx = compute_line_length(prev_line, offset_encoding) + 1
+ char_idx = compute_line_length(prev_line, offset_encoding) + 1
else
byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx)
char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding)
@@ -203,14 +203,30 @@ end
---@param new_lastline integer
---@param offset_encoding string
---@returns (int, int) end_line_idx and end_col_idx of range
-local function compute_end_range(prev_lines, curr_lines, start_range, firstline, lastline, new_lastline, offset_encoding)
+local function compute_end_range(
+ prev_lines,
+ curr_lines,
+ start_range,
+ firstline,
+ lastline,
+ new_lastline,
+ offset_encoding
+)
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
-- In this case, the last_byte...
if firstline == new_lastline then
- return { line_idx = (lastline - new_lastline + firstline), byte_idx = 1, char_idx = 1 }, { line_idx = firstline, byte_idx = 1, char_idx = 1 }
+ return { line_idx = (lastline - new_lastline + firstline), byte_idx = 1, char_idx = 1 }, {
+ line_idx = firstline,
+ byte_idx = 1,
+ char_idx = 1,
+ }
end
if firstline == lastline then
- return { line_idx = firstline, byte_idx = 1, char_idx = 1 }, { line_idx = new_lastline - lastline + firstline, byte_idx = 1, char_idx = 1 }
+ return { line_idx = firstline, byte_idx = 1, char_idx = 1 }, {
+ line_idx = new_lastline - lastline + firstline,
+ byte_idx = 1,
+ char_idx = 1,
+ }
end
-- Compare on last line, at minimum will be the start range
local start_line_idx = start_range.line_idx
@@ -239,9 +255,7 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline,
end
for idx = 0, max_length do
byte_offset = idx
- if
- str_byte(prev_line, prev_line_length - byte_offset) ~= str_byte(curr_line, curr_line_length - byte_offset)
- then
+ if str_byte(prev_line, prev_line_length - byte_offset) ~= str_byte(curr_line, curr_line_length - byte_offset) then
break
end
end
@@ -281,14 +295,13 @@ end
---@param end_range table new_end_range returned by last_difference
---@returns string text extracted from defined region
local function extract_text(lines, start_range, end_range, line_ending)
- if not lines[start_range.line_idx] then
- return ""
- end
+ if not lines[start_range.line_idx] then
+ return ''
+ end
-- Trivial case: start and end range are the same line, directly grab changed text
if start_range.line_idx == end_range.line_idx then
-- string.sub is inclusive, end_range is not
return string.sub(lines[start_range.line_idx], start_range.byte_idx, end_range.byte_idx - 1)
-
else
-- Handle deletion case
-- Collect the changed portion of the first changed line
@@ -303,7 +316,7 @@ local function extract_text(lines, start_range, end_range, line_ending)
-- Collect the changed portion of the last changed line.
table.insert(result, string.sub(lines[end_range.line_idx], 1, end_range.byte_idx - 1))
else
- table.insert(result, "")
+ table.insert(result, '')
end
-- Add line ending between all lines
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index bb87e8372b..e8a8e06f46 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -1,10 +1,10 @@
-local protocol = require 'vim.lsp.protocol'
-local snippet = require 'vim.lsp._snippet'
+local protocol = require('vim.lsp.protocol')
+local snippet = require('vim.lsp._snippet')
local vim = vim
local validate = vim.validate
local api = vim.api
local list_extend = vim.list_extend
-local highlight = require 'vim.highlight'
+local highlight = require('vim.highlight')
local uv = vim.loop
local npcall = vim.F.npcall
@@ -13,14 +13,14 @@ local split = vim.split
local M = {}
local default_border = {
- {"", "NormalFloat"},
- {"", "NormalFloat"},
- {"", "NormalFloat"},
- {" ", "NormalFloat"},
- {"", "NormalFloat"},
- {"", "NormalFloat"},
- {"", "NormalFloat"},
- {" ", "NormalFloat"},
+ { '', 'NormalFloat' },
+ { '', 'NormalFloat' },
+ { '', 'NormalFloat' },
+ { ' ', 'NormalFloat' },
+ { '', 'NormalFloat' },
+ { '', 'NormalFloat' },
+ { '', 'NormalFloat' },
+ { ' ', 'NormalFloat' },
}
---@private
@@ -35,43 +35,50 @@ local function get_border_size(opts)
local width = 0
if type(border) == 'string' then
- local border_size = {none = {0, 0}, single = {2, 2}, double = {2, 2}, rounded = {2, 2}, solid = {2, 2}, shadow = {1, 1}}
+ local border_size = {
+ none = { 0, 0 },
+ single = { 2, 2 },
+ double = { 2, 2 },
+ rounded = { 2, 2 },
+ solid = { 2, 2 },
+ shadow = { 1, 1 },
+ }
if border_size[border] == nil then
- error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
+ error(string.format('invalid floating preview border: %s. :help vim.api.nvim_open_win()', vim.inspect(border)))
end
height, width = unpack(border_size[border])
else
if 8 % #border ~= 0 then
- error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
+ error(string.format('invalid floating preview border: %s. :help vim.api.nvim_open_win()', vim.inspect(border)))
end
---@private
local function border_width(id)
id = (id - 1) % #border + 1
- if type(border[id]) == "table" then
+ if type(border[id]) == 'table' then
-- border specified as a table of <character, highlight group>
return vim.fn.strdisplaywidth(border[id][1])
- elseif type(border[id]) == "string" then
+ elseif type(border[id]) == 'string' then
-- border specified as a list of border characters
return vim.fn.strdisplaywidth(border[id])
end
- error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
+ error(string.format('invalid floating preview border: %s. :help vim.api.nvim_open_win()', vim.inspect(border)))
end
---@private
local function border_height(id)
id = (id - 1) % #border + 1
- if type(border[id]) == "table" then
+ if type(border[id]) == 'table' then
-- border specified as a table of <character, highlight group>
return #border[id][1] > 0 and 1 or 0
- elseif type(border[id]) == "string" then
+ elseif type(border[id]) == 'string' then
-- border specified as a list of border characters
return #border[id] > 0 and 1 or 0
end
- error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
+ error(string.format('invalid floating preview border: %s. :help vim.api.nvim_open_win()', vim.inspect(border)))
end
- height = height + border_height(2) -- top
- height = height + border_height(6) -- bottom
- width = width + border_width(4) -- right
- width = width + border_width(8) -- left
+ height = height + border_height(2) -- top
+ height = height + border_height(6) -- bottom
+ width = width + border_width(4) -- right
+ width = width + border_width(8) -- left
end
return { height = height, width = width }
@@ -89,9 +96,15 @@ end
---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
---@return number `encoding` index of `index` in `line`
function M._str_utfindex_enc(line, index, encoding)
- if not encoding then encoding = 'utf-16' end
+ if not encoding then
+ encoding = 'utf-16'
+ end
if encoding == 'utf-8' then
- if index then return index else return #line end
+ if index then
+ return index
+ else
+ return #line
+ end
elseif encoding == 'utf-16' then
local _, col16 = vim.str_utfindex(line, index)
return col16
@@ -99,7 +112,7 @@ function M._str_utfindex_enc(line, index, encoding)
local col32, _ = vim.str_utfindex(line, index)
return col32
else
- error("Invalid encoding: " .. vim.inspect(encoding))
+ error('Invalid encoding: ' .. vim.inspect(encoding))
end
end
@@ -111,15 +124,21 @@ end
---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
---@return number byte (utf-8) index of `encoding` index `index` in `line`
function M._str_byteindex_enc(line, index, encoding)
- if not encoding then encoding = 'utf-16' end
+ if not encoding then
+ encoding = 'utf-16'
+ end
if encoding == 'utf-8' then
- if index then return index else return #line end
+ if index then
+ return index
+ else
+ return #line
+ end
elseif encoding == 'utf-16' then
return vim.str_byteindex(line, index, true)
elseif encoding == 'utf-32' then
return vim.str_byteindex(line, index)
else
- error("Invalid encoding: " .. vim.inspect(encoding))
+ error('Invalid encoding: ' .. vim.inspect(encoding))
end
end
@@ -142,34 +161,38 @@ function M.set_lines(lines, A, B, new_lines)
-- specifying a line number after what we would call the last line.
local i_n = math.min(B[1] + 1, #lines)
if not (i_0 >= 1 and i_0 <= #lines + 1 and i_n >= 1 and i_n <= #lines) then
- error("Invalid range: "..vim.inspect{A = A; B = B; #lines, new_lines})
+ error('Invalid range: ' .. vim.inspect({ A = A, B = B, #lines, new_lines }))
end
- local prefix = ""
- local suffix = lines[i_n]:sub(B[2]+1)
+ local prefix = ''
+ local suffix = lines[i_n]:sub(B[2] + 1)
if A[2] > 0 then
prefix = lines[i_0]:sub(1, A[2])
end
local n = i_n - i_0 + 1
if n ~= #new_lines then
- for _ = 1, n - #new_lines do table.remove(lines, i_0) end
- for _ = 1, #new_lines - n do table.insert(lines, i_0, '') end
+ for _ = 1, n - #new_lines do
+ table.remove(lines, i_0)
+ end
+ for _ = 1, #new_lines - n do
+ table.insert(lines, i_0, '')
+ end
end
for i = 1, #new_lines do
lines[i - 1 + i_0] = new_lines[i]
end
if #suffix > 0 then
local i = i_0 + #new_lines - 1
- lines[i] = lines[i]..suffix
+ lines[i] = lines[i] .. suffix
end
if #prefix > 0 then
- lines[i_0] = prefix..lines[i_0]
+ lines[i_0] = prefix .. lines[i_0]
end
return lines
end
---@private
local function sort_by_key(fn)
- return function(a,b)
+ return function(a, b)
local ka, kb = fn(a), fn(b)
assert(#ka == #kb)
for i = 1, #ka do
@@ -191,7 +214,7 @@ end
---@param rows number[] zero-indexed line numbers
---@return table<number string> a table mapping rows to lines
local function get_lines(bufnr, rows)
- rows = type(rows) == "table" and rows or { rows }
+ rows = type(rows) == 'table' and rows or { rows }
-- This is needed for bufload and bufloaded
if bufnr == 0 then
@@ -202,7 +225,7 @@ local function get_lines(bufnr, rows)
local function buf_lines()
local lines = {}
for _, row in pairs(rows) do
- lines[row] = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1]
+ lines[row] = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { '' })[1]
end
return lines
end
@@ -211,7 +234,7 @@ local function get_lines(bufnr, rows)
-- load the buffer if this is not a file uri
-- Custom language server protocol extensions can result in servers sending URIs with custom schemes. Plugins are able to load these via `BufReadCmd` autocmds.
- if uri:sub(1, 4) ~= "file" then
+ if uri:sub(1, 4) ~= 'file' then
vim.fn.bufload(bufnr)
return buf_lines()
end
@@ -224,8 +247,10 @@ local function get_lines(bufnr, rows)
local filename = api.nvim_buf_get_name(bufnr)
-- get the data from the file
- local fd = uv.fs_open(filename, "r", 438)
- if not fd then return "" end
+ local fd = uv.fs_open(filename, 'r', 438)
+ if not fd then
+ return ''
+ end
local stat = uv.fs_fstat(fd)
local data = uv.fs_read(fd, stat.size, 0)
uv.fs_close(fd)
@@ -242,11 +267,13 @@ local function get_lines(bufnr, rows)
local found = 0
local lnum = 0
- for line in string.gmatch(data, "([^\n]*)\n?") do
+ for line in string.gmatch(data, '([^\n]*)\n?') do
if lines[lnum] == true then
lines[lnum] = line
found = found + 1
- if found == need then break end
+ if found == need then
+ break
+ end
end
lnum = lnum + 1
end
@@ -254,13 +281,12 @@ local function get_lines(bufnr, rows)
-- change any lines we didn't find to the empty string
for i, line in pairs(lines) do
if line == true then
- lines[i] = ""
+ lines[i] = ''
end
end
return lines
end
-
---@private
--- Gets the zero-indexed line from the given buffer.
--- Works on unloaded buffers by reading the file using libuv to bypass buf reading events.
@@ -273,7 +299,6 @@ local function get_line(bufnr, row)
return get_lines(bufnr, { row })[row]
end
-
---@private
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
--- Returns a zero-indexed column, since set_lines() does the conversion to
@@ -300,30 +325,27 @@ end
--- Process and return progress reports from lsp server
---@private
function M.get_progress_messages()
-
local new_messages = {}
local progress_remove = {}
for _, client in ipairs(vim.lsp.get_active_clients()) do
- local messages = client.messages
- local data = messages
- for token, ctx in pairs(data.progress) do
-
- local new_report = {
- name = data.name,
- title = ctx.title or "empty title",
- message = ctx.message,
- percentage = ctx.percentage,
- done = ctx.done,
- progress = true,
- }
- table.insert(new_messages, new_report)
+ local messages = client.messages
+ local data = messages
+ for token, ctx in pairs(data.progress) do
+ local new_report = {
+ name = data.name,
+ title = ctx.title or 'empty title',
+ message = ctx.message,
+ percentage = ctx.percentage,
+ done = ctx.done,
+ progress = true,
+ }
+ table.insert(new_messages, new_report)
- if ctx.done then
- table.insert(progress_remove, {client = client, token = token})
- end
+ if ctx.done then
+ table.insert(progress_remove, { client = client, token = token })
end
-
+ end
end
for _, item in ipairs(progress_remove) do
@@ -339,12 +361,14 @@ end
---@param offset_encoding string utf-8|utf-16|utf-32
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
function M.apply_text_edits(text_edits, bufnr, offset_encoding)
- validate {
- text_edits = { text_edits, 't', false };
- bufnr = { bufnr, 'number', false };
- offset_encoding = { offset_encoding, 'string', false };
- }
- if not next(text_edits) then return end
+ validate({
+ text_edits = { text_edits, 't', false },
+ bufnr = { bufnr, 'number', false },
+ offset_encoding = { offset_encoding, 'string', false },
+ })
+ if not next(text_edits) then
+ return
+ end
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
@@ -356,7 +380,11 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
index = index + 1
text_edit._index = index
- if text_edit.range.start.line > text_edit.range['end'].line or text_edit.range.start.line == text_edit.range['end'].line and text_edit.range.start.character > text_edit.range['end'].character then
+ if
+ text_edit.range.start.line > text_edit.range['end'].line
+ or text_edit.range.start.line == text_edit.range['end'].line
+ and text_edit.range.start.character > text_edit.range['end'].character
+ then
local start = text_edit.range.start
text_edit.range.start = text_edit.range['end']
text_edit.range['end'] = start
@@ -406,7 +434,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
start_row = text_edit.range.start.line,
start_col = get_line_byte_from_position(bufnr, text_edit.range.start, offset_encoding),
end_row = text_edit.range['end'].line,
- end_col = get_line_byte_from_position(bufnr, text_edit.range['end'], offset_encoding),
+ end_col = get_line_byte_from_position(bufnr, text_edit.range['end'], offset_encoding),
text = vim.split(text_edit.newText, '\n', true),
}
@@ -456,7 +484,11 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
-- Remove final line if needed
local fix_eol = has_eol_text_edit
- fix_eol = fix_eol and (api.nvim_buf_get_option(bufnr, 'eol') or (api.nvim_buf_get_option(bufnr, 'fixeol') and not api.nvim_buf_get_option(bufnr, 'binary')))
+ fix_eol = fix_eol
+ and (
+ api.nvim_buf_get_option(bufnr, 'eol')
+ or (api.nvim_buf_get_option(bufnr, 'fixeol') and not api.nvim_buf_get_option(bufnr, 'binary'))
+ )
fix_eol = fix_eol and get_line(bufnr, max - 1) == ''
if fix_eol then
vim.api.nvim_buf_set_lines(bufnr, -2, -1, false, {})
@@ -499,7 +531,7 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
local text_document = text_document_edit.textDocument
local bufnr = vim.uri_to_bufnr(text_document.uri)
if offset_encoding == nil then
- vim.notify_once("apply_text_document_edit must be called with valid offset encoding", vim.log.levels.WARN)
+ vim.notify_once('apply_text_document_edit must be called with valid offset encoding', vim.log.levels.WARN)
end
-- For lists of text document edits,
@@ -511,11 +543,16 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
-- `VersionedTextDocumentIdentifier`s version may be null
-- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
- if should_check_version and (text_document.version
+ if
+ should_check_version
+ and (
+ text_document.version
and text_document.version > 0
and M.buf_versions[bufnr]
- and M.buf_versions[bufnr] > text_document.version) then
- print("Buffer ", text_document.uri, " newer than edits.")
+ and M.buf_versions[bufnr] > text_document.version
+ )
+ then
+ print('Buffer ', text_document.uri, ' newer than edits.')
return
end
@@ -551,16 +588,16 @@ end
--- precedence is as follows: textEdit.newText > insertText > label
--see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
local function get_completion_word(item)
- if item.textEdit ~= nil and item.textEdit.newText ~= nil and item.textEdit.newText ~= "" then
+ if item.textEdit ~= nil and item.textEdit.newText ~= nil and item.textEdit.newText ~= '' then
local insert_text_format = protocol.InsertTextFormat[item.insertTextFormat]
- if insert_text_format == "PlainText" or insert_text_format == nil then
+ if insert_text_format == 'PlainText' or insert_text_format == nil then
return item.textEdit.newText
else
return M.parse_snippet(item.textEdit.newText)
end
- elseif item.insertText ~= nil and item.insertText ~= "" then
+ elseif item.insertText ~= nil and item.insertText ~= '' then
local insert_text_format = protocol.InsertTextFormat[item.insertTextFormat]
- if insert_text_format == "PlainText" or insert_text_format == nil then
+ if insert_text_format == 'PlainText' or insert_text_format == nil then
return item.insertText
else
return M.parse_snippet(item.insertText)
@@ -588,7 +625,7 @@ end
---@returns (`vim.lsp.protocol.completionItemKind`)
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
function M._get_completion_item_kind_name(completion_item_kind)
- return protocol.CompletionItemKind[completion_item_kind] or "Unknown"
+ return protocol.CompletionItemKind[completion_item_kind] or 'Unknown'
end
--- Turns the result of a `textDocument/completion` request into vim-compatible
@@ -619,7 +656,7 @@ function M.text_document_completion_list_to_complete_items(result, prefix)
info = documentation
elseif type(documentation) == 'table' and type(documentation.value) == 'string' then
info = documentation.value
- -- else
+ -- else
-- TODO(ashkan) Validation handling here?
end
end
@@ -637,9 +674,9 @@ function M.text_document_completion_list_to_complete_items(result, prefix)
user_data = {
nvim = {
lsp = {
- completion_item = completion_item
- }
- }
+ completion_item = completion_item,
+ },
+ },
},
})
end
@@ -647,7 +684,6 @@ function M.text_document_completion_list_to_complete_items(result, prefix)
return matches
end
-
--- Rename old_fname to new_fname
---
---@param opts (table)
@@ -700,7 +736,7 @@ local function delete_file(change)
if opts.ignoreIfNotExists and not stat then
return
end
- assert(stat, "Cannot delete not existing file or folder " .. fname)
+ assert(stat, 'Cannot delete not existing file or folder ' .. fname)
local flags
if stat and stat.type == 'directory' then
flags = opts.recursive and 'rf' or 'd'
@@ -713,7 +749,6 @@ local function delete_file(change)
api.nvim_buf_delete(bufnr, { force = true })
end
-
--- Applies a `WorkspaceEdit`.
---
---@param workspace_edit table `WorkspaceEdit`
@@ -721,22 +756,18 @@ end
--see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
function M.apply_workspace_edit(workspace_edit, offset_encoding)
if offset_encoding == nil then
- vim.notify_once("apply_workspace_edit must be called with valid offset encoding", vim.log.levels.WARN)
+ vim.notify_once('apply_workspace_edit must be called with valid offset encoding', vim.log.levels.WARN)
end
if workspace_edit.documentChanges then
for idx, change in ipairs(workspace_edit.documentChanges) do
- if change.kind == "rename" then
- M.rename(
- vim.uri_to_fname(change.oldUri),
- vim.uri_to_fname(change.newUri),
- change.options
- )
+ if change.kind == 'rename' then
+ M.rename(vim.uri_to_fname(change.oldUri), vim.uri_to_fname(change.newUri), change.options)
elseif change.kind == 'create' then
create_file(change)
elseif change.kind == 'delete' then
delete_file(change)
elseif change.kind then
- error(string.format("Unsupported change: %q", vim.inspect(change)))
+ error(string.format('Unsupported change: %q', vim.inspect(change)))
else
M.apply_text_document_edit(change, idx, offset_encoding)
end
@@ -770,7 +801,7 @@ function M.convert_input_to_markdown_lines(input, contents)
if type(input) == 'string' then
list_extend(contents, split_lines(input))
else
- assert(type(input) == 'table', "Expected a table for Hover.contents")
+ assert(type(input) == 'table', 'Expected a table for Hover.contents')
-- MarkupContent
if input.kind then
-- The kind can be either plaintext or markdown.
@@ -779,22 +810,22 @@ function M.convert_input_to_markdown_lines(input, contents)
-- Some servers send input.value as empty, so let's ignore this :(
local value = input.value or ''
- if input.kind == "plaintext" then
+ if input.kind == 'plaintext' then
-- wrap this in a <text></text> block so that stylize_markdown
-- can properly process it as plaintext
- value = string.format("<text>\n%s\n</text>", value)
+ value = string.format('<text>\n%s\n</text>', value)
end
-- assert(type(value) == 'string')
list_extend(contents, split_lines(value))
- -- MarkupString variation 2
+ -- MarkupString variation 2
elseif input.language then
-- Some servers send input.value as empty, so let's ignore this :(
-- assert(type(input.value) == 'string')
- table.insert(contents, "```"..input.language)
+ table.insert(contents, '```' .. input.language)
list_extend(contents, split_lines(input.value or ''))
- table.insert(contents, "```")
- -- By deduction, this must be MarkedString[]
+ table.insert(contents, '```')
+ -- By deduction, this must be MarkedString[]
else
-- Use our existing logic to handle MarkedString
for _, marked_string in ipairs(input) do
@@ -838,7 +869,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
local label = signature.label
if ft then
-- wrap inside a code block so stylize_markdown can render it properly
- label = ("```%s\n%s\n```"):format(ft, label)
+ label = ('```%s\n%s\n```'):format(ft, label)
end
vim.list_extend(contents, vim.split(label, '\n', true))
if signature.documentation then
@@ -846,8 +877,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
end
if signature.parameters and #signature.parameters > 0 then
local active_parameter = (signature.activeParameter or signature_help.activeParameter or 0)
- if active_parameter < 0
- then active_parameter = 0
+ if active_parameter < 0 then
+ active_parameter = 0
end
-- If the activeParameter is > #parameters, then set it to the last
@@ -877,7 +908,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
}
--]=]
if parameter.label then
- if type(parameter.label) == "table" then
+ if type(parameter.label) == 'table' then
active_hl = parameter.label
else
local offset = 1
@@ -890,9 +921,11 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
end
for p, param in pairs(signature.parameters) do
offset = signature.label:find(param.label, offset, true)
- if not offset then break end
+ if not offset then
+ break
+ end
if p == active_parameter + 1 then
- active_hl = {offset - 1, offset + #parameter.label - 1}
+ active_hl = { offset - 1, offset + #parameter.label - 1 }
break
end
offset = offset + #param.label + 1
@@ -920,14 +953,14 @@ end
--- - zindex (string or table) override `zindex`, defaults to 50
---@returns (table) Options
function M.make_floating_popup_options(width, height, opts)
- validate {
- opts = { opts, 't', true };
- }
+ validate({
+ opts = { opts, 't', true },
+ })
opts = opts or {}
- validate {
- ["opts.offset_x"] = { opts.offset_x, 'n', true };
- ["opts.offset_y"] = { opts.offset_y, 'n', true };
- }
+ validate({
+ ['opts.offset_x'] = { opts.offset_x, 'n', true },
+ ['opts.offset_y'] = { opts.offset_y, 'n', true },
+ })
local anchor = ''
local row, col
@@ -936,20 +969,20 @@ function M.make_floating_popup_options(width, height, opts)
local lines_below = vim.fn.winheight(0) - lines_above
if lines_above < lines_below then
- anchor = anchor..'N'
+ anchor = anchor .. 'N'
height = math.min(lines_below, height)
row = 1
else
- anchor = anchor..'S'
+ anchor = anchor .. 'S'
height = math.min(lines_above, height)
row = 0
end
if vim.fn.wincol() + width + (opts.offset_x or 0) <= api.nvim_get_option('columns') then
- anchor = anchor..'W'
+ anchor = anchor .. 'W'
col = 0
else
- anchor = anchor..'E'
+ anchor = anchor .. 'E'
col = 1
end
@@ -975,18 +1008,20 @@ end
function M.jump_to_location(location, offset_encoding)
-- location may be Location or LocationLink
local uri = location.uri or location.targetUri
- if uri == nil then return end
+ if uri == nil then
+ return
+ end
if offset_encoding == nil then
- vim.notify_once("jump_to_location must be called with valid offset encoding", vim.log.levels.WARN)
+ vim.notify_once('jump_to_location must be called with valid offset encoding', vim.log.levels.WARN)
end
local bufnr = vim.uri_to_bufnr(uri)
-- Save position in jumplist
- vim.cmd "normal! m'"
+ vim.cmd("normal! m'")
-- Push a new item into tagstack
- local from = {vim.fn.bufnr('%'), vim.fn.line('.'), vim.fn.col('.'), 0}
- local items = {{tagname=vim.fn.expand('<cword>'), from=from}}
- vim.fn.settagstack(vim.fn.win_getid(), {items=items}, 't')
+ local from = { vim.fn.bufnr('%'), vim.fn.line('.'), vim.fn.col('.'), 0 }
+ local items = { { tagname = vim.fn.expand('<cword>'), from = from } }
+ vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't')
--- Jump to new location (adjusting for UTF-16 encoding of characters)
api.nvim_set_current_buf(bufnr)
@@ -994,9 +1029,9 @@ function M.jump_to_location(location, offset_encoding)
local range = location.range or location.targetSelectionRange
local row = range.start.line
local col = get_line_byte_from_position(bufnr, range.start, offset_encoding)
- api.nvim_win_set_cursor(0, {row + 1, col})
+ api.nvim_win_set_cursor(0, { row + 1, col })
-- Open folds under the cursor
- vim.cmd("normal! zv")
+ vim.cmd('normal! zv')
return true
end
@@ -1011,22 +1046,24 @@ end
function M.preview_location(location, opts)
-- location may be LocationLink or Location (more useful for the former)
local uri = location.targetUri or location.uri
- if uri == nil then return end
+ if uri == nil then
+ return
+ end
local bufnr = vim.uri_to_bufnr(uri)
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
local range = location.targetRange or location.range
- local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range["end"].line+1, false)
+ local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range['end'].line + 1, false)
local syntax = api.nvim_buf_get_option(bufnr, 'syntax')
- if syntax == "" then
+ if syntax == '' then
-- When no syntax is set, we use filetype as fallback. This might not result
-- in a valid syntax definition. See also ft detection in stylize_markdown.
-- An empty syntax is more common now with TreeSitter, since TS disables syntax.
syntax = api.nvim_buf_get_option(bufnr, 'filetype')
end
opts = opts or {}
- opts.focus_id = "location"
+ opts.focus_id = 'location'
return M.open_floating_preview(contents, syntax, opts)
end
@@ -1047,20 +1084,20 @@ end
--- - pad_bottom number of lines to pad contents at bottom (default 0)
---@return contents table of trimmed and padded lines
function M._trim(contents, opts)
- validate {
- contents = { contents, 't' };
- opts = { opts, 't', true };
- }
+ validate({
+ contents = { contents, 't' },
+ opts = { opts, 't', true },
+ })
opts = opts or {}
contents = M.trim_empty_lines(contents)
if opts.pad_top then
for _ = 1, opts.pad_top do
- table.insert(contents, 1, "")
+ table.insert(contents, 1, '')
end
end
if opts.pad_bottom then
for _ = 1, opts.pad_bottom do
- table.insert(contents, "")
+ table.insert(contents, '')
end
end
return contents
@@ -1073,7 +1110,7 @@ end
local function get_markdown_fences()
local fences = {}
for _, fence in pairs(vim.g.markdown_fenced_languages or {}) do
- local lang, syntax = fence:match("^(.*)=(.*)$")
+ local lang, syntax = fence:match('^(.*)=(.*)$')
if lang then
fences[lang] = syntax
end
@@ -1102,28 +1139,28 @@ end
--- - separator insert separator after code block
---@returns width,height size of float
function M.stylize_markdown(bufnr, contents, opts)
- validate {
- contents = { contents, 't' };
- opts = { opts, 't', true };
- }
+ validate({
+ contents = { contents, 't' },
+ opts = { opts, 't', true },
+ })
opts = opts or {}
-- table of fence types to {ft, begin, end}
-- when ft is nil, we get the ft from the regex match
local matchers = {
- block = {nil, "```+([a-zA-Z0-9_]*)", "```+"},
- pre = {"", "<pre>", "</pre>"},
- code = {"", "<code>", "</code>"},
- text = {"text", "<text>", "</text>"},
+ block = { nil, '```+([a-zA-Z0-9_]*)', '```+' },
+ pre = { '', '<pre>', '</pre>' },
+ code = { '', '<code>', '</code>' },
+ text = { 'text', '<text>', '</text>' },
}
local match_begin = function(line)
for type, pattern in pairs(matchers) do
- local ret = line:match(string.format("^%%s*%s%%s*$", pattern[2]))
+ local ret = line:match(string.format('^%%s*%s%%s*$', pattern[2]))
if ret then
return {
type = type,
- ft = pattern[1] or ret
+ ft = pattern[1] or ret,
}
end
end
@@ -1131,7 +1168,7 @@ function M.stylize_markdown(bufnr, contents, opts)
local match_end = function(line, match)
local pattern = matchers[match.type]
- return line:match(string.format("^%%s*%s%%s*$", pattern[3]))
+ return line:match(string.format('^%%s*%s%%s*$', pattern[3]))
end
-- Clean up
@@ -1161,25 +1198,27 @@ function M.stylize_markdown(bufnr, contents, opts)
i = i + 1
end
table.insert(highlights, {
- ft = match.ft;
- start = start + 1;
- finish = #stripped;
+ ft = match.ft,
+ start = start + 1,
+ finish = #stripped,
})
-- add a separator, but not on the last line
if add_sep and i < #contents then
- table.insert(stripped, "---")
+ table.insert(stripped, '---')
markdown_lines[#stripped] = true
end
else
-- strip any empty lines or separators prior to this separator in actual markdown
- if line:match("^---+$") then
- while markdown_lines[#stripped] and (stripped[#stripped]:match("^%s*$") or stripped[#stripped]:match("^---+$")) do
+ if line:match('^---+$') then
+ while
+ markdown_lines[#stripped] and (stripped[#stripped]:match('^%s*$') or stripped[#stripped]:match('^---+$'))
+ do
markdown_lines[#stripped] = false
table.remove(stripped, #stripped)
end
end
-- add the line if its not an empty line following a separator
- if not (line:match("^%s*$") and markdown_lines[#stripped] and stripped[#stripped]:match("^---+$")) then
+ if not (line:match('^%s*$') and markdown_lines[#stripped] and stripped[#stripped]:match('^---+$')) then
table.insert(stripped, line)
markdown_lines[#stripped] = true
end
@@ -1189,13 +1228,13 @@ function M.stylize_markdown(bufnr, contents, opts)
end
-- Compute size of float needed to show (wrapped) lines
- opts.wrap_at = opts.wrap_at or (vim.wo["wrap"] and api.nvim_win_get_width(0))
+ opts.wrap_at = opts.wrap_at or (vim.wo['wrap'] and api.nvim_win_get_width(0))
local width = M._make_floating_popup_size(stripped, opts)
- local sep_line = string.rep("─", math.min(width, opts.wrap_at or width))
+ local sep_line = string.rep('─', math.min(width, opts.wrap_at or width))
for l in pairs(markdown_lines) do
- if stripped[l]:match("^---+$") then
+ if stripped[l]:match('^---+$') then
stripped[l] = sep_line
end
end
@@ -1209,24 +1248,28 @@ function M.stylize_markdown(bufnr, contents, opts)
local langs = {}
local fences = get_markdown_fences()
local function apply_syntax_to_region(ft, start, finish)
- if ft == "" then
- vim.cmd(string.format("syntax region markdownCode start=+\\%%%dl+ end=+\\%%%dl+ keepend extend", start, finish + 1))
+ if ft == '' then
+ vim.cmd(
+ string.format('syntax region markdownCode start=+\\%%%dl+ end=+\\%%%dl+ keepend extend', start, finish + 1)
+ )
return
end
ft = fences[ft] or ft
- local name = ft..idx
+ local name = ft .. idx
idx = idx + 1
- local lang = "@"..ft:upper()
+ local lang = '@' .. ft:upper()
if not langs[lang] then
-- HACK: reset current_syntax, since some syntax files like markdown won't load if it is already set
- pcall(vim.api.nvim_buf_del_var, bufnr, "current_syntax")
+ pcall(vim.api.nvim_buf_del_var, bufnr, 'current_syntax')
-- TODO(ashkan): better validation before this.
- if not pcall(vim.cmd, string.format("syntax include %s syntax/%s.vim", lang, ft)) then
+ if not pcall(vim.cmd, string.format('syntax include %s syntax/%s.vim', lang, ft)) then
return
end
langs[lang] = true
end
- vim.cmd(string.format("syntax region %s start=+\\%%%dl+ end=+\\%%%dl+ contains=%s keepend", name, start, finish + 1, lang))
+ vim.cmd(
+ string.format('syntax region %s start=+\\%%%dl+ end=+\\%%%dl+ contains=%s keepend', name, start, finish + 1, lang)
+ )
end
-- needs to run in the buffer for the regions to work
@@ -1237,13 +1280,13 @@ function M.stylize_markdown(bufnr, contents, opts)
local last = 1
for _, h in ipairs(highlights) do
if last < h.start then
- apply_syntax_to_region("lsp_markdown", last, h.start - 1)
+ apply_syntax_to_region('lsp_markdown', last, h.start - 1)
end
apply_syntax_to_region(h.ft, h.start, h.finish)
last = h.finish + 1
end
if last <= #stripped then
- apply_syntax_to_region("lsp_markdown", last, #stripped)
+ apply_syntax_to_region('lsp_markdown', last, #stripped)
end
end)
@@ -1258,23 +1301,33 @@ end
---@param bufnrs table list of buffers where the preview window will remain visible
---@see |autocmd-events|
local function close_preview_autocmd(events, winnr, bufnrs)
- local augroup = 'preview_window_'..winnr
+ local augroup = 'preview_window_' .. winnr
-- close the preview window when entered a buffer that is not
-- the floating window buffer or the buffer that spawned it
- vim.cmd(string.format([[
+ vim.cmd(string.format(
+ [[
augroup %s
autocmd!
autocmd BufEnter * lua vim.lsp.util._close_preview_window(%d, {%s})
augroup end
- ]], augroup, winnr, table.concat(bufnrs, ',')))
+ ]],
+ augroup,
+ winnr,
+ table.concat(bufnrs, ',')
+ ))
if #events > 0 then
- vim.cmd(string.format([[
+ vim.cmd(string.format(
+ [[
augroup %s
autocmd %s <buffer> lua vim.lsp.util._close_preview_window(%d)
augroup end
- ]], augroup, table.concat(events, ','), winnr))
+ ]],
+ augroup,
+ table.concat(events, ','),
+ winnr
+ ))
end
end
@@ -1290,13 +1343,17 @@ function M._close_preview_window(winnr, bufnrs)
return
end
- local augroup = 'preview_window_'..winnr
- vim.cmd(string.format([[
+ local augroup = 'preview_window_' .. winnr
+ vim.cmd(string.format(
+ [[
augroup %s
autocmd!
augroup end
augroup! %s
- ]], augroup, augroup))
+ ]],
+ augroup,
+ augroup
+ ))
pcall(vim.api.nvim_win_close, winnr, true)
end)
end
@@ -1313,10 +1370,10 @@ end
--- - max_height maximal height of floating window
---@returns width,height size of float
function M._make_floating_popup_size(contents, opts)
- validate {
- contents = { contents, 't' };
- opts = { opts, 't', true };
- }
+ validate({
+ contents = { contents, 't' },
+ opts = { opts, 't', true },
+ })
opts = opts or {}
local width = opts.width
@@ -1360,11 +1417,11 @@ function M._make_floating_popup_size(contents, opts)
if vim.tbl_isempty(line_widths) then
for _, line in ipairs(contents) do
local line_width = vim.fn.strdisplaywidth(line)
- height = height + math.ceil(line_width/wrap_at)
+ height = height + math.ceil(line_width / wrap_at)
end
else
for i = 1, #contents do
- height = height + math.max(1, math.ceil(line_widths[i]/wrap_at))
+ height = height + math.max(1, math.ceil(line_widths[i] / wrap_at))
end
end
end
@@ -1398,16 +1455,16 @@ end
---@returns bufnr,winnr buffer and window number of the newly created floating
---preview window
function M.open_floating_preview(contents, syntax, opts)
- validate {
- contents = { contents, 't' };
- syntax = { syntax, 's', true };
- opts = { opts, 't', true };
- }
+ validate({
+ contents = { contents, 't' },
+ syntax = { syntax, 's', true },
+ opts = { opts, 't', true },
+ })
opts = opts or {}
opts.wrap = opts.wrap ~= false -- wrapping by default
opts.stylize_markdown = opts.stylize_markdown ~= false
opts.focus = opts.focus ~= false
- opts.close_events = opts.close_events or {"CursorMoved", "CursorMovedI", "InsertCharPre"}
+ opts.close_events = opts.close_events or { 'CursorMoved', 'CursorMovedI', 'InsertCharPre' }
local bufnr = api.nvim_get_current_buf()
@@ -1416,7 +1473,7 @@ function M.open_floating_preview(contents, syntax, opts)
-- Go back to previous window if we are in a focusable one
local current_winnr = api.nvim_get_current_win()
if npcall(api.nvim_win_get_var, current_winnr, opts.focus_id) then
- api.nvim_command("wincmd p")
+ api.nvim_command('wincmd p')
return bufnr, current_winnr
end
do
@@ -1424,7 +1481,7 @@ function M.open_floating_preview(contents, syntax, opts)
if win and api.nvim_win_is_valid(win) and vim.fn.pumvisible() == 0 then
-- focus and return the existing buf, win
api.nvim_set_current_win(win)
- api.nvim_command("stopinsert")
+ api.nvim_command('stopinsert')
return api.nvim_win_get_buf(win), win
end
end
@@ -1432,14 +1489,13 @@ function M.open_floating_preview(contents, syntax, opts)
-- check if another floating preview already exists for this buffer
-- and close it if needed
- local existing_float = npcall(api.nvim_buf_get_var, bufnr, "lsp_floating_preview")
+ local existing_float = npcall(api.nvim_buf_get_var, bufnr, 'lsp_floating_preview')
if existing_float and api.nvim_win_is_valid(existing_float) then
api.nvim_win_close(existing_float, true)
end
local floating_bufnr = api.nvim_create_buf(false, true)
- local do_stylize = syntax == "markdown" and opts.stylize_markdown
-
+ local do_stylize = syntax == 'markdown' and opts.stylize_markdown
-- Clean up input: trim empty lines from the end, pad
contents = M._trim(contents, opts)
@@ -1475,26 +1531,32 @@ function M.open_floating_preview(contents, syntax, opts)
api.nvim_buf_set_option(floating_bufnr, 'modifiable', false)
api.nvim_buf_set_option(floating_bufnr, 'bufhidden', 'wipe')
- api.nvim_buf_set_keymap(floating_bufnr, "n", "q", "<cmd>bdelete<cr>", {silent = true, noremap = true, nowait = true})
- close_preview_autocmd(opts.close_events, floating_winnr, {floating_bufnr, bufnr})
+ api.nvim_buf_set_keymap(
+ floating_bufnr,
+ 'n',
+ 'q',
+ '<cmd>bdelete<cr>',
+ { silent = true, noremap = true, nowait = true }
+ )
+ close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr })
-- save focus_id
if opts.focus_id then
api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr)
end
- api.nvim_buf_set_var(bufnr, "lsp_floating_preview", floating_winnr)
+ api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr)
return floating_bufnr, floating_winnr
end
do --[[ References ]]
- local reference_ns = api.nvim_create_namespace("vim_lsp_references")
+ local reference_ns = api.nvim_create_namespace('vim_lsp_references')
--- Removes document highlights from a buffer.
---
---@param bufnr number Buffer id
function M.buf_clear_references(bufnr)
- validate { bufnr = {bufnr, 'n', true} }
+ validate({ bufnr = { bufnr, 'n', true } })
api.nvim_buf_clear_namespace(bufnr or 0, reference_ns, 0, -1)
end
@@ -1505,35 +1567,41 @@ do --[[ References ]]
---@param offset_encoding string One of "utf-8", "utf-16", "utf-32".
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
function M.buf_highlight_references(bufnr, references, offset_encoding)
- validate {
- bufnr = {bufnr, 'n', true},
- offset_encoding = { offset_encoding, 'string', false };
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ offset_encoding = { offset_encoding, 'string', false },
+ })
for _, reference in ipairs(references) do
- local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"]
- local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"]
+ local start_line, start_char = reference['range']['start']['line'], reference['range']['start']['character']
+ local end_line, end_char = reference['range']['end']['line'], reference['range']['end']['character']
- local start_idx = get_line_byte_from_position(bufnr, { line = start_line, character = start_char }, offset_encoding)
+ local start_idx = get_line_byte_from_position(
+ bufnr,
+ { line = start_line, character = start_char },
+ offset_encoding
+ )
local end_idx = get_line_byte_from_position(bufnr, { line = start_line, character = end_char }, offset_encoding)
local document_highlight_kind = {
- [protocol.DocumentHighlightKind.Text] = "LspReferenceText";
- [protocol.DocumentHighlightKind.Read] = "LspReferenceRead";
- [protocol.DocumentHighlightKind.Write] = "LspReferenceWrite";
+ [protocol.DocumentHighlightKind.Text] = 'LspReferenceText',
+ [protocol.DocumentHighlightKind.Read] = 'LspReferenceRead',
+ [protocol.DocumentHighlightKind.Write] = 'LspReferenceWrite',
}
- local kind = reference["kind"] or protocol.DocumentHighlightKind.Text
- highlight.range(bufnr,
- reference_ns,
- document_highlight_kind[kind],
- { start_line, start_idx },
- { end_line, end_idx },
- { priority = vim.highlight.priorities.user })
+ local kind = reference['kind'] or protocol.DocumentHighlightKind.Text
+ highlight.range(
+ bufnr,
+ reference_ns,
+ document_highlight_kind[kind],
+ { start_line, start_idx },
+ { end_line, end_idx },
+ { priority = vim.highlight.priorities.user }
+ )
end
end
end
local position_sort = sort_by_key(function(v)
- return {v.start.line, v.start.character}
+ return { v.start.line, v.start.character }
end)
--- Returns the items with the byte position calculated correctly and in sorted
@@ -1547,7 +1615,7 @@ end)
---@returns (table) list of items
function M.locations_to_items(locations, offset_encoding)
if offset_encoding == nil then
- vim.notify_once("locations_to_items must be called with valid offset encoding", vim.log.levels.WARN)
+ vim.notify_once('locations_to_items must be called with valid offset encoding', vim.log.levels.WARN)
end
local items = {}
@@ -1556,16 +1624,15 @@ function M.locations_to_items(locations, offset_encoding)
local v = {}
rawset(t, k, v)
return v
- end;
+ end,
})
for _, d in ipairs(locations) do
-- locations may be Location or LocationLink
local uri = d.uri or d.targetUri
local range = d.range or d.targetSelectionRange
- table.insert(grouped[uri], {start = range.start})
+ table.insert(grouped[uri], { start = range.start })
end
-
local keys = vim.tbl_keys(grouped)
table.sort(keys)
-- TODO(ashkan) I wish we could do this lazily.
@@ -1588,13 +1655,13 @@ function M.locations_to_items(locations, offset_encoding)
for _, temp in ipairs(rows) do
local pos = temp.start
local row = pos.line
- local line = lines[row] or ""
+ local line = lines[row] or ''
local col = M._str_byteindex_enc(line, pos.character, offset_encoding)
table.insert(items, {
filename = filename,
lnum = row + 1,
- col = col + 1;
- text = line;
+ col = col + 1,
+ text = line,
})
end
end
@@ -1609,10 +1676,10 @@ end
---
---@param items (table) list of items
function M.set_loclist(items, win_id)
- vim.api.nvim_echo({{'vim.lsp.util.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.api.nvim_echo({ { 'vim.lsp.util.set_loclist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {})
vim.fn.setloclist(win_id or 0, {}, ' ', {
- title = 'Language Server';
- items = items;
+ title = 'Language Server',
+ items = items,
})
end
@@ -1623,10 +1690,10 @@ end
---
---@param items (table) list of items
function M.set_qflist(items)
- vim.api.nvim_echo({{'vim.lsp.util.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.api.nvim_echo({ { 'vim.lsp.util.set_qflist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {})
vim.fn.setqflist({}, ' ', {
- title = 'Language Server';
- items = items;
+ title = 'Language Server',
+ items = items,
})
end
@@ -1634,7 +1701,7 @@ end
-- the client must handle it properly even if it receives a value outside the specification.
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
function M._get_symbol_kind_name(symbol_kind)
- return protocol.SymbolKind[symbol_kind] or "Unknown"
+ return protocol.SymbolKind[symbol_kind] or 'Unknown'
end
--- Converts symbols to quickfix list items.
@@ -1652,7 +1719,7 @@ function M.symbols_to_items(symbols, bufnr)
lnum = range.start.line + 1,
col = range.start.character + 1,
kind = kind,
- text = '['..kind..'] '..symbol.name,
+ text = '[' .. kind .. '] ' .. symbol.name,
})
elseif symbol.selectionRange then -- DocumentSymbole type
local kind = M._get_symbol_kind_name(symbol.kind)
@@ -1662,7 +1729,7 @@ function M.symbols_to_items(symbols, bufnr)
lnum = symbol.selectionRange.start.line + 1,
col = symbol.selectionRange.start.character + 1,
kind = kind,
- text = '['..kind..'] '..symbol.name
+ text = '[' .. kind .. '] ' .. symbol.name,
})
if symbol.children then
for _, v in ipairs(_symbols_to_items(symbol.children, _items, _bufnr)) do
@@ -1707,12 +1774,12 @@ end
---@param lines (table) list of lines
---@returns (string) filetype or 'markdown' if it was unchanged.
function M.try_trim_markdown_code_blocks(lines)
- local language_id = lines[1]:match("^```(.*)")
+ local language_id = lines[1]:match('^```(.*)')
if language_id then
local has_inner_code_fence = false
for i = 2, (#lines - 1) do
local line = lines[i]
- if line:sub(1,3) == '```' then
+ if line:sub(1, 3) == '```' then
has_inner_code_fence = true
break
end
@@ -1736,14 +1803,14 @@ local function make_position_param(window, offset_encoding)
local row, col = unpack(api.nvim_win_get_cursor(window))
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
row = row - 1
- local line = api.nvim_buf_get_lines(buf, row, row+1, true)[1]
+ local line = api.nvim_buf_get_lines(buf, row, row + 1, true)[1]
if not line then
- return { line = 0; character = 0; }
+ return { line = 0, character = 0 }
end
col = _str_utfindex_enc(line, col, offset_encoding)
- return { line = row; character = col; }
+ return { line = row, character = col }
end
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
@@ -1757,8 +1824,8 @@ function M.make_position_params(window, offset_encoding)
local buf = vim.api.nvim_win_get_buf(window)
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
return {
- textDocument = M.make_text_document_params(buf);
- position = make_position_param(window, offset_encoding)
+ textDocument = M.make_text_document_params(buf),
+ position = make_position_param(window, offset_encoding),
}
end
@@ -1766,16 +1833,16 @@ end
---@param bufnr (number) buffer handle or 0 for current, defaults to current
---@returns (string) encoding first client if there is one, nil otherwise
function M._get_offset_encoding(bufnr)
- validate {
- bufnr = {bufnr, 'n', true};
- }
+ validate({
+ bufnr = { bufnr, 'n', true },
+ })
local offset_encoding
for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do
if client.offset_encoding == nil then
vim.notify_once(
- string.format("Client (id: %s) offset_encoding is nil. Do not unset offset_encoding.", client.id),
+ string.format('Client (id: %s) offset_encoding is nil. Do not unset offset_encoding.', client.id),
vim.log.levels.ERROR
)
end
@@ -1783,7 +1850,10 @@ function M._get_offset_encoding(bufnr)
if not offset_encoding then
offset_encoding = this_offset_encoding
elseif offset_encoding ~= this_offset_encoding then
- vim.notify("warning: multiple different client offset_encodings detected for buffer, this is not supported yet", vim.log.levels.WARN)
+ vim.notify(
+ 'warning: multiple different client offset_encodings detected for buffer, this is not supported yet',
+ vim.log.levels.WARN
+ )
end
end
@@ -1805,7 +1875,7 @@ function M.make_range_params(window, offset_encoding)
local position = make_position_param(window, offset_encoding)
return {
textDocument = M.make_text_document_params(buf),
- range = { start = position; ["end"] = position; }
+ range = { start = position, ['end'] = position },
}
end
@@ -1821,11 +1891,11 @@ end
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
---`start_position`, end = `end_position` } }
function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
- validate {
- start_pos = {start_pos, 't', true};
- end_pos = {end_pos, 't', true};
- offset_encoding = {offset_encoding, 's', true};
- }
+ validate({
+ start_pos = { start_pos, 't', true },
+ end_pos = { end_pos, 't', true },
+ offset_encoding = { offset_encoding, 's', true },
+ })
bufnr = bufnr or vim.api.nvim_get_current_buf()
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<'))
@@ -1835,10 +1905,10 @@ function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
B[1] = B[1] - 1
-- account for offset_encoding.
if A[2] > 0 then
- A = {A[1], M.character_offset(bufnr, A[1], A[2], offset_encoding)}
+ A = { A[1], M.character_offset(bufnr, A[1], A[2], offset_encoding) }
end
if B[2] > 0 then
- B = {B[1], M.character_offset(bufnr, B[1], B[2], offset_encoding)}
+ B = { B[1], M.character_offset(bufnr, B[1], B[2], offset_encoding) }
end
-- we need to offset the end character position otherwise we loose the last
-- character of the selection, as LSP end position is exclusive
@@ -1849,9 +1919,9 @@ function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
return {
textDocument = M.make_text_document_params(bufnr),
range = {
- start = {line = A[1], character = A[2]},
- ['end'] = {line = B[1], character = B[2]}
- }
+ start = { line = A[1], character = A[2] },
+ ['end'] = { line = B[1], character = B[2] },
+ },
}
end
@@ -1868,7 +1938,7 @@ end
---@param added
---@param removed
function M.make_workspace_params(added, removed)
- return { event = { added = added; removed = removed; } }
+ return { event = { added = added, removed = removed } }
end
--- Returns indentation size.
---
@@ -1876,7 +1946,7 @@ end
---@param bufnr (number|nil): Buffer handle, defaults to current
---@returns (number) indentation size
function M.get_effective_tabstop(bufnr)
- validate { bufnr = {bufnr, 'n', true} }
+ validate({ bufnr = { bufnr, 'n', true } })
local bo = bufnr and vim.bo[bufnr] or vim.bo
local sw = bo.shiftwidth
return (sw == 0 and bo.tabstop) or sw
@@ -1888,14 +1958,14 @@ end
---@returns `DocumentFormattingParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
function M.make_formatting_params(options)
- validate { options = {options, 't', true} }
+ validate({ options = { options, 't', true } })
options = vim.tbl_extend('keep', options or {}, {
- tabSize = M.get_effective_tabstop();
- insertSpaces = vim.bo.expandtab;
+ tabSize = M.get_effective_tabstop(),
+ insertSpaces = vim.bo.expandtab,
})
return {
- textDocument = { uri = vim.uri_from_bufnr(0) };
- options = options;
+ textDocument = { uri = vim.uri_from_bufnr(0) },
+ options = options,
}
end
@@ -1909,7 +1979,7 @@ end
function M.character_offset(buf, row, col, offset_encoding)
local line = get_line(buf, row)
if offset_encoding == nil then
- vim.notify_once("character_offset must be called with valid offset encoding", vim.log.levels.WARN)
+ vim.notify_once('character_offset must be called with valid offset encoding', vim.log.levels.WARN)
end
-- If the col is past the EOL, use the line length.
if col > #line then
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 172fac3a88..9bbe356f03 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -15,8 +15,8 @@ local vim = vim or {}
--- copied and will throw an error.
---
---@param orig table Table to copy
----@returns New table of copied keys and (nested) values.
-function vim.deepcopy(orig) end -- luacheck: no unused
+---@return table Table of copied keys and (nested) values.
+function vim.deepcopy(orig) end -- luacheck: no unused
vim.deepcopy = (function()
local function _id(v)
return v
@@ -24,7 +24,9 @@ vim.deepcopy = (function()
local deepcopy_funcs = {
table = function(orig, cache)
- if cache[orig] then return cache[orig] end
+ if cache[orig] then
+ return cache[orig]
+ end
local copy = {}
cache[orig] = copy
@@ -46,7 +48,7 @@ vim.deepcopy = (function()
if f then
return f(orig, cache or {})
else
- error("Cannot deepcopy object of type "..type(orig))
+ error('Cannot deepcopy object of type ' .. type(orig))
end
end
end)()
@@ -57,19 +59,19 @@ end)()
---@see https://www.lua.org/pil/20.2.html
---@see http://lua-users.org/wiki/StringLibraryTutorial
---
----@param s String to split
----@param sep Separator string or pattern
----@param plain If `true` use `sep` literally (passed to String.find)
----@returns Iterator over the split components
+---@param s string String to split
+---@param sep string Separator or pattern
+---@param plain boolean If `true` use `sep` literally (passed to string.find)
+---@return function Iterator over the split components
function vim.gsplit(s, sep, plain)
- vim.validate{s={s,'s'},sep={sep,'s'},plain={plain,'b',true}}
+ vim.validate({ s = { s, 's' }, sep = { sep, 's' }, plain = { plain, 'b', true } })
local start = 1
local done = false
local function _pass(i, j, ...)
if i then
- assert(j+1 > start, "Infinite loop detected")
+ assert(j + 1 > start, 'Infinite loop detected')
local seg = s:sub(start, i - 1)
start = j + 1
return seg, ...
@@ -87,7 +89,7 @@ function vim.gsplit(s, sep, plain)
if start == #s then
done = true
end
- return _pass(start+1, start)
+ return _pass(start + 1, start)
end
return _pass(s:find(sep, start, plain))
end
@@ -105,13 +107,13 @@ end
---
---@see |vim.gsplit()|
---
----@param s String to split
----@param sep Separator string or pattern
----@param kwargs Keyword arguments:
+---@param s string String to split
+---@param sep string Separator or pattern
+---@param kwargs table Keyword arguments:
--- - plain: (boolean) If `true` use `sep` literally (passed to string.find)
--- - trimempty: (boolean) If `true` remove empty items from the front
--- and back of the list
----@returns List-like table of the split components.
+---@return table List of split components
function vim.split(s, sep, kwargs)
local plain
local trimempty = false
@@ -119,7 +121,7 @@ function vim.split(s, sep, kwargs)
-- Support old signature for backward compatibility
plain = kwargs
else
- vim.validate { kwargs = {kwargs, 't', true} }
+ vim.validate({ kwargs = { kwargs, 't', true } })
kwargs = kwargs or {}
plain = kwargs.plain
trimempty = kwargs.trimempty
@@ -128,7 +130,7 @@ function vim.split(s, sep, kwargs)
local t = {}
local skip = trimempty
for c in vim.gsplit(s, sep, plain) do
- if c ~= "" then
+ if c ~= '' then
skip = false
end
@@ -139,7 +141,7 @@ function vim.split(s, sep, kwargs)
if trimempty then
for i = #t, 1, -1 do
- if t[i] ~= "" then
+ if t[i] ~= '' then
break
end
table.remove(t, i)
@@ -154,10 +156,10 @@ end
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@param t Table
----@returns list of keys
+---@param t table Table
+---@return table List of keys
function vim.tbl_keys(t)
- assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
+ assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
local keys = {}
for k, _ in pairs(t) do
@@ -169,10 +171,10 @@ end
--- Return a list of all values used in a table.
--- However, the order of the return table of values is not guaranteed.
---
----@param t Table
----@returns list of values
+---@param t table Table
+---@return table List of values
function vim.tbl_values(t)
- assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
+ assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
local values = {}
for _, v in pairs(t) do
@@ -183,10 +185,11 @@ end
--- Apply a function to all values of a table.
---
----@param func function or callable table
----@param t table
+---@param func function|table Function or callable table
+---@param t table Table
+---@return table Table of transformed values
function vim.tbl_map(func, t)
- vim.validate{func={func,'c'},t={t,'t'}}
+ vim.validate({ func = { func, 'c' }, t = { t, 't' } })
local rettab = {}
for k, v in pairs(t) do
@@ -197,10 +200,11 @@ end
--- Filter a table using a predicate function
---
----@param func function or callable table
----@param t table
+---@param func function|table Function or callable table
+---@param t table Table
+---@return table Table of filtered values
function vim.tbl_filter(func, t)
- vim.validate{func={func,'c'},t={t,'t'}}
+ vim.validate({ func = { func, 'c' }, t = { t, 't' } })
local rettab = {}
for _, entry in pairs(t) do
@@ -213,13 +217,13 @@ end
--- Checks if a list-like (vector) table contains `value`.
---
----@param t Table to check
----@param value Value to compare
----@returns true if `t` contains `value`
+---@param t table Table to check
+---@param value any Value to compare
+---@return boolean `true` if `t` contains `value`
function vim.tbl_contains(t, value)
- vim.validate{t={t,'t'}}
+ vim.validate({ t = { t, 't' } })
- for _,v in ipairs(t) do
+ for _, v in ipairs(t) do
if v == value then
return true
end
@@ -231,25 +235,26 @@ end
---
---@see https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@param t Table to check
+---@param t table Table to check
+---@return boolean `true` if `t` is empty
function vim.tbl_isempty(t)
- assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
+ assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
return next(t) == nil
end
---- we only merge empty tables or tables that are not a list
+--- We only merge empty tables or tables that are not a list
---@private
local function can_merge(v)
- return type(v) == "table" and (vim.tbl_isempty(v) or not vim.tbl_islist(v))
+ return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.tbl_islist(v))
end
local function tbl_extend(behavior, deep_extend, ...)
- if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
- error('invalid "behavior": '..tostring(behavior))
+ if behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force' then
+ error('invalid "behavior": ' .. tostring(behavior))
end
if select('#', ...) < 2 then
- error('wrong number of arguments (given '..tostring(1 + select('#', ...))..', expected at least 3)')
+ error('wrong number of arguments (given ' .. tostring(1 + select('#', ...)) .. ', expected at least 3)')
end
local ret = {}
@@ -259,15 +264,15 @@ local function tbl_extend(behavior, deep_extend, ...)
for i = 1, select('#', ...) do
local tbl = select(i, ...)
- vim.validate{["after the second argument"] = {tbl,'t'}}
+ vim.validate({ ['after the second argument'] = { tbl, 't' } })
if tbl then
for k, v in pairs(tbl) do
if deep_extend and can_merge(v) and can_merge(ret[k]) then
ret[k] = tbl_extend(behavior, true, ret[k], v)
elseif behavior ~= 'force' and ret[k] ~= nil then
if behavior == 'error' then
- error('key found in more than one map: '..k)
- end -- Else behavior is "keep".
+ error('key found in more than one map: ' .. k)
+ end -- Else behavior is "keep".
else
ret[k] = v
end
@@ -281,11 +286,12 @@ end
---
---@see |extend()|
---
----@param behavior Decides what to do if a key is found in more than one map:
+---@param behavior string Decides what to do if a key is found in more than one map:
--- - "error": raise an error
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
----@param ... Two or more map-like tables.
+---@param ... table Two or more map-like tables
+---@return table Merged table
function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...)
end
@@ -294,25 +300,30 @@ end
---
---@see |tbl_extend()|
---
----@param behavior Decides what to do if a key is found in more than one map:
+---@param behavior string Decides what to do if a key is found in more than one map:
--- - "error": raise an error
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
----@param ... Two or more map-like tables.
+---@param ... table Two or more map-like tables
+---@return table Merged table
function vim.tbl_deep_extend(behavior, ...)
return tbl_extend(behavior, true, ...)
end
--- Deep compare values for equality
---
---- Tables are compared recursively unless they both provide the `eq` methamethod.
+--- Tables are compared recursively unless they both provide the `eq` metamethod.
--- All other types are compared using the equality `==` operator.
----@param a first value
----@param b second value
----@returns `true` if values are equals, else `false`.
+---@param a any First value
+---@param b any Second value
+---@return boolean `true` if values are equals, else `false`
function vim.deep_equal(a, b)
- if a == b then return true end
- if type(a) ~= type(b) then return false end
+ if a == b then
+ return true
+ end
+ if type(a) ~= type(b) then
+ return false
+ end
if type(a) == 'table' then
for k, v in pairs(a) do
if not vim.deep_equal(v, b[k]) then
@@ -332,15 +343,22 @@ end
--- Add the reverse lookup values to an existing table.
--- For example:
--- ``tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }``
---
---Do note that it *modifies* the input.
----@param o table The table to add the reverse to.
+---
+--- Note that this *modifies* the input.
+---@param o table Table to add the reverse to
+---@return table o
function vim.tbl_add_reverse_lookup(o)
local keys = vim.tbl_keys(o)
for _, k in ipairs(keys) do
local v = o[k]
if o[v] then
- error(string.format("The reverse lookup found an existing value for %q while processing key %q", tostring(v), tostring(k)))
+ error(
+ string.format(
+ 'The reverse lookup found an existing value for %q while processing key %q',
+ tostring(v),
+ tostring(k)
+ )
+ )
end
o[v] = k
end
@@ -349,19 +367,19 @@ end
--- Index into a table (first argument) via string keys passed as subsequent arguments.
--- Return `nil` if the key does not exist.
---_
+---
--- Examples:
--- <pre>
--- vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
--- vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
--- </pre>
---
----@param o Table to index
----@param ... Optional strings (0 or more, variadic) via which to index the table
+---@param o table Table to index
+---@param ... string Optional strings (0 or more, variadic) via which to index the table
---
----@returns nested value indexed by key if it exists, else nil
+---@return any Nested value indexed by key (if it exists), else nil
function vim.tbl_get(o, ...)
- local keys = {...}
+ local keys = { ... }
if #keys == 0 then
return
end
@@ -383,18 +401,18 @@ end
---
---@see |vim.tbl_extend()|
---
----@param dst list which will be modified and appended to.
----@param src list from which values will be inserted.
----@param start Start index on src. defaults to 1
----@param finish Final index on src. defaults to #src
----@returns dst
+---@param dst table List which will be modified and appended to
+---@param src table List from which values will be inserted
+---@param start number Start index on src. Defaults to 1
+---@param finish number Final index on src. Defaults to `#src`
+---@return table dst
function vim.list_extend(dst, src, start, finish)
- vim.validate {
- dst = {dst, 't'};
- src = {src, 't'};
- start = {start, 'n', true};
- finish = {finish, 'n', true};
- }
+ vim.validate({
+ dst = { dst, 't' },
+ src = { src, 't' },
+ start = { start, 'n', true },
+ finish = { finish, 'n', true },
+ })
for i = start or 1, finish or #src do
table.insert(dst, src[i])
end
@@ -406,15 +424,15 @@ end
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@param t List-like table
----@returns Flattened copy of the given list-like table.
+---@param t table List-like table
+---@return table Flattened copy of the given list-like table
function vim.tbl_flatten(t)
local result = {}
local function _tbl_flatten(_t)
local n = #_t
for i = 1, n do
local v = _t[i]
- if type(v) == "table" then
+ if type(v) == 'table' then
_tbl_flatten(v)
elseif v then
table.insert(result, v)
@@ -431,8 +449,8 @@ end
--- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result,
--- for example from |rpcrequest()| or |vim.fn|.
---
----@param t Table
----@returns `true` if array-like table, else `false`.
+---@param t table Table
+---@return boolean `true` if array-like table, else `false`
function vim.tbl_islist(t)
if type(t) ~= 'table' then
return false
@@ -441,7 +459,7 @@ function vim.tbl_islist(t)
local count = 0
for k, _ in pairs(t) do
- if type(k) == "number" then
+ if type(k) == 'number' then
count = count + 1
else
return false
@@ -468,26 +486,28 @@ end
--- </pre>
---
---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
----@param t Table
----@returns Number that is the number of the value in table
+---@param t table Table
+---@return number Number of non-nil values in table
function vim.tbl_count(t)
- vim.validate{t={t,'t'}}
+ vim.validate({ t = { t, 't' } })
local count = 0
- for _ in pairs(t) do count = count + 1 end
+ for _ in pairs(t) do
+ count = count + 1
+ end
return count
end
--- Creates a copy of a table containing only elements from start to end (inclusive)
---
----@param list table table
----@param start integer Start range of slice
----@param finish integer End range of slice
----@returns Copy of table sliced from start to finish (inclusive)
+---@param list table Table
+---@param start number Start range of slice
+---@param finish number End range of slice
+---@return table Copy of table sliced from start to finish (inclusive)
function vim.list_slice(list, start, finish)
local new_list = {}
for i = start or 1, finish or #list do
- new_list[#new_list+1] = list[i]
+ new_list[#new_list + 1] = list[i]
end
return new_list
end
@@ -495,40 +515,40 @@ end
--- Trim whitespace (Lua pattern "%s") from both sides of a string.
---
---@see https://www.lua.org/pil/20.2.html
----@param s String to trim
----@returns String with whitespace removed from its beginning and end
+---@param s string String to trim
+---@return string String with whitespace removed from its beginning and end
function vim.trim(s)
- vim.validate{s={s,'s'}}
+ vim.validate({ s = { s, 's' } })
return s:match('^%s*(.*%S)') or ''
end
--- Escapes magic chars in a Lua pattern.
---
---@see https://github.com/rxi/lume
----@param s String to escape
----@returns %-escaped pattern string
+---@param s string String to escape
+---@return string %-escaped pattern string
function vim.pesc(s)
- vim.validate{s={s,'s'}}
+ vim.validate({ s = { s, 's' } })
return s:gsub('[%(%)%.%%%+%-%*%?%[%]%^%$]', '%%%1')
end
--- Tests if `s` starts with `prefix`.
---
----@param s (string) a string
----@param prefix (string) a prefix
----@return (boolean) true if `prefix` is a prefix of s
+---@param s string String
+---@param prefix string Prefix to match
+---@return boolean `true` if `prefix` is a prefix of `s`
function vim.startswith(s, prefix)
- vim.validate { s = {s, 's'}; prefix = {prefix, 's'}; }
+ vim.validate({ s = { s, 's' }, prefix = { prefix, 's' } })
return s:sub(1, #prefix) == prefix
end
--- Tests if `s` ends with `suffix`.
---
----@param s (string) a string
----@param suffix (string) a suffix
----@return (boolean) true if `suffix` is a suffix of s
+---@param s string String
+---@param suffix string Suffix to match
+---@return boolean `true` if `suffix` is a suffix of `s`
function vim.endswith(s, suffix)
- vim.validate { s = {s, 's'}; suffix = {suffix, 's'}; }
+ vim.validate({ s = { s, 's' }, suffix = { suffix, 's' } })
return #suffix == 0 or s:sub(-#suffix) == suffix
end
@@ -568,7 +588,7 @@ end
---
--- </pre>
---
----@param opt table of parameter names to validations. Each key is a parameter
+---@param opt table Names of parameters to validate. Each key is a parameter
--- name; each value is a tuple in one of these forms:
--- 1. (arg_value, type_name, optional)
--- - arg_value: argument value
@@ -582,18 +602,24 @@ end
--- only if the argument is valid. Can optionally return an additional
--- informative error message as the second returned value.
--- - msg: (optional) error string if validation fails
-function vim.validate(opt) end -- luacheck: no unused
+function vim.validate(opt) end -- luacheck: no unused
do
local type_names = {
- ['table'] = 'table', t = 'table',
- ['string'] = 'string', s = 'string',
- ['number'] = 'number', n = 'number',
- ['boolean'] = 'boolean', b = 'boolean',
- ['function'] = 'function', f = 'function',
- ['callable'] = 'callable', c = 'callable',
- ['nil'] = 'nil',
- ['thread'] = 'thread',
+ ['table'] = 'table',
+ t = 'table',
+ ['string'] = 'string',
+ s = 'string',
+ ['number'] = 'number',
+ n = 'number',
+ ['boolean'] = 'boolean',
+ b = 'boolean',
+ ['function'] = 'function',
+ f = 'function',
+ ['callable'] = 'callable',
+ c = 'callable',
+ ['nil'] = 'nil',
+ ['thread'] = 'thread',
['userdata'] = 'userdata',
}
@@ -612,21 +638,21 @@ do
return false, string.format('opt[%s]: expected table, got %s', param_name, type(spec))
end
- local val = spec[1] -- Argument value.
- local types = spec[2] -- Type name, or callable.
+ local val = spec[1] -- Argument value
+ local types = spec[2] -- Type name, or callable
local optional = (true == spec[3])
if type(types) == 'string' then
- types = {types}
+ types = { types }
end
if vim.is_callable(types) then
- -- Check user-provided validation function.
+ -- Check user-provided validation function
local valid, optional_message = types(val)
if not valid then
- local error_message = string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), tostring(val))
+ local error_message = string.format('%s: expected %s, got %s', param_name, (spec[3] or '?'), tostring(val))
if optional_message ~= nil then
- error_message = error_message .. string.format(". Info: %s", optional_message)
+ error_message = error_message .. string.format('. Info: %s', optional_message)
end
return false, error_message
@@ -646,10 +672,10 @@ do
end
end
if not success then
- return false, string.format("%s: expected %s, got %s", param_name, table.concat(types, '|'), type(val))
+ return false, string.format('%s: expected %s, got %s', param_name, table.concat(types, '|'), type(val))
end
else
- return false, string.format("invalid type name: %s", tostring(types))
+ return false, string.format('invalid type name: %s', tostring(types))
end
end
@@ -665,12 +691,16 @@ do
end
--- Returns true if object `f` can be called as a function.
---
----@param f Any object
----@return true if `f` is callable, else false
+---@param f any Any object
+---@return boolean `true` if `f` is callable, else `false`
function vim.is_callable(f)
- if type(f) == 'function' then return true end
+ if type(f) == 'function' then
+ return true
+ end
local m = getmetatable(f)
- if m == nil then return false end
+ if m == nil then
+ return false
+ end
return type(m.__call) == 'function'
end
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 55398d8180..70f2c425ed 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -1,32 +1,32 @@
local a = vim.api
-local query = require'vim.treesitter.query'
-local language = require'vim.treesitter.language'
-local LanguageTree = require'vim.treesitter.languagetree'
+local query = require('vim.treesitter.query')
+local language = require('vim.treesitter.language')
+local LanguageTree = require('vim.treesitter.languagetree')
-- TODO(bfredl): currently we retain parsers for the lifetime of the buffer.
-- Consider use weak references to release parser if all plugins are done with
-- it.
local parsers = {}
-local M = vim.tbl_extend("error", query, language)
+local M = vim.tbl_extend('error', query, language)
M.language_version = vim._ts_get_language_version()
M.minimum_language_version = vim._ts_get_minimum_language_version()
setmetatable(M, {
- __index = function (t, k)
- if k == "highlighter" then
- t[k] = require'vim.treesitter.highlighter'
- return t[k]
- elseif k == "language" then
- t[k] = require"vim.treesitter.language"
- return t[k]
- elseif k == "query" then
- t[k] = require"vim.treesitter.query"
- return t[k]
- end
- end
- })
+ __index = function(t, k)
+ if k == 'highlighter' then
+ t[k] = require('vim.treesitter.highlighter')
+ return t[k]
+ elseif k == 'language' then
+ t[k] = require('vim.treesitter.language')
+ return t[k]
+ elseif k == 'query' then
+ t[k] = require('vim.treesitter.query')
+ return t[k]
+ end
+ end,
+})
--- Creates a new parser.
---
@@ -63,7 +63,11 @@ function M._create_parser(bufnr, lang, opts)
self:_on_reload(...)
end
- a.nvim_buf_attach(self:source(), false, {on_bytes=bytes_cb, on_detach=detach_cb, on_reload=reload_cb, preview=true})
+ a.nvim_buf_attach(
+ self:source(),
+ false,
+ { on_bytes = bytes_cb, on_detach = detach_cb, on_reload = reload_cb, preview = true }
+ )
self:parse()
@@ -87,7 +91,7 @@ function M.get_parser(bufnr, lang, opts)
bufnr = a.nvim_get_current_buf()
end
if lang == nil then
- lang = a.nvim_buf_get_option(bufnr, "filetype")
+ lang = a.nvim_buf_get_option(bufnr, 'filetype')
end
if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
@@ -105,10 +109,10 @@ end
---@param lang The language of this string
---@param opts Options to pass to the created language tree
function M.get_string_parser(str, lang, opts)
- vim.validate {
+ vim.validate({
str = { str, 'string' },
- lang = { lang, 'string' }
- }
+ lang = { lang, 'string' },
+ })
language.require_language(lang)
return LanguageTree.new(str, lang, opts)
diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua
index 53ccc6e88d..aa9db6b71b 100644
--- a/runtime/lua/vim/treesitter/health.lua
+++ b/runtime/lua/vim/treesitter/health.lua
@@ -15,24 +15,22 @@ function M.check()
local report_error = vim.fn['health#report_error']
local parsers = M.list_parsers()
- report_info(string.format("Runtime ABI version : %d", ts.language_version))
+ report_info(string.format('Runtime ABI version : %d', ts.language_version))
for _, parser in pairs(parsers) do
- local parsername = vim.fn.fnamemodify(parser, ":t:r")
+ local parsername = vim.fn.fnamemodify(parser, ':t:r')
local is_loadable, ret = pcall(ts.language.require_language, parsername)
if not is_loadable then
- report_error(string.format("Impossible to load parser for %s: %s", parsername, ret))
+ report_error(string.format('Impossible to load parser for %s: %s', parsername, ret))
elseif ret then
local lang = ts.language.inspect_language(parsername)
- report_ok(string.format("Loaded parser for %s: ABI version %d",
- parsername, lang._abi_version))
+ report_ok(string.format('Loaded parser for %s: ABI version %d', parsername, lang._abi_version))
else
- report_error(string.format("Unable to load parser for %s", parsername))
+ report_error(string.format('Unable to load parser for %s', parsername))
end
end
end
return M
-
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 0ec4ab37ec..453fed0576 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -1,5 +1,5 @@
local a = vim.api
-local query = require"vim.treesitter.query"
+local query = require('vim.treesitter.query')
-- support reload for quick experimentation
local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {}
@@ -10,13 +10,13 @@ TSHighlighter.active = TSHighlighter.active or {}
local TSHighlighterQuery = {}
TSHighlighterQuery.__index = TSHighlighterQuery
-local ns = a.nvim_create_namespace("treesitter/highlighter")
+local ns = a.nvim_create_namespace('treesitter/highlighter')
local _default_highlights = {}
local _link_default_highlight_once = function(from, to)
if not _default_highlights[from] then
_default_highlights[from] = true
- vim.cmd(string.format("highlight default link %s %s", from, to))
+ vim.cmd(string.format('highlight default link %s %s', from, to))
end
return from
@@ -31,65 +31,65 @@ local subcapture_fallback = {
shortened = shortened:match('(.*)%.')
rtn = shortened and rawget(self, shortened)
end
- rawset(self, capture, rtn or "__notfound")
+ rawset(self, capture, rtn or '__notfound')
return rtn
- end
+ end,
}
TSHighlighter.hl_map = setmetatable({
- ["error"] = "Error",
- ["text.underline"] = "Underlined",
- ["todo"] = "Todo",
- ["debug"] = "Debug",
-
--- Miscs
- ["comment"] = "Comment",
- ["punctuation.delimiter"] = "Delimiter",
- ["punctuation.bracket"] = "Delimiter",
- ["punctuation.special"] = "Delimiter",
-
--- Constants
- ["constant"] = "Constant",
- ["constant.builtin"] = "Special",
- ["constant.macro"] = "Define",
- ["define"] = "Define",
- ["macro"] = "Macro",
- ["string"] = "String",
- ["string.regex"] = "String",
- ["string.escape"] = "SpecialChar",
- ["character"] = "Character",
- ["character.special"] = "SpecialChar",
- ["number"] = "Number",
- ["boolean"] = "Boolean",
- ["float"] = "Float",
-
--- Functions
- ["function"] = "Function",
- ["function.special"] = "Function",
- ["function.builtin"] = "Special",
- ["function.macro"] = "Macro",
- ["parameter"] = "Identifier",
- ["method"] = "Function",
- ["field"] = "Identifier",
- ["property"] = "Identifier",
- ["constructor"] = "Special",
-
--- Keywords
- ["conditional"] = "Conditional",
- ["repeat"] = "Repeat",
- ["label"] = "Label",
- ["operator"] = "Operator",
- ["keyword"] = "Keyword",
- ["exception"] = "Exception",
-
- ["type"] = "Type",
- ["type.builtin"] = "Type",
- ["type.qualifier"] = "Type",
- ["type.definition"] = "Typedef",
- ["storageclass"] = "StorageClass",
- ["structure"] = "Structure",
- ["include"] = "Include",
- ["preproc"] = "PreProc",
+ ['error'] = 'Error',
+ ['text.underline'] = 'Underlined',
+ ['todo'] = 'Todo',
+ ['debug'] = 'Debug',
+
+ -- Miscs
+ ['comment'] = 'Comment',
+ ['punctuation.delimiter'] = 'Delimiter',
+ ['punctuation.bracket'] = 'Delimiter',
+ ['punctuation.special'] = 'Delimiter',
+
+ -- Constants
+ ['constant'] = 'Constant',
+ ['constant.builtin'] = 'Special',
+ ['constant.macro'] = 'Define',
+ ['define'] = 'Define',
+ ['macro'] = 'Macro',
+ ['string'] = 'String',
+ ['string.regex'] = 'String',
+ ['string.escape'] = 'SpecialChar',
+ ['character'] = 'Character',
+ ['character.special'] = 'SpecialChar',
+ ['number'] = 'Number',
+ ['boolean'] = 'Boolean',
+ ['float'] = 'Float',
+
+ -- Functions
+ ['function'] = 'Function',
+ ['function.special'] = 'Function',
+ ['function.builtin'] = 'Special',
+ ['function.macro'] = 'Macro',
+ ['parameter'] = 'Identifier',
+ ['method'] = 'Function',
+ ['field'] = 'Identifier',
+ ['property'] = 'Identifier',
+ ['constructor'] = 'Special',
+
+ -- Keywords
+ ['conditional'] = 'Conditional',
+ ['repeat'] = 'Repeat',
+ ['label'] = 'Label',
+ ['operator'] = 'Operator',
+ ['keyword'] = 'Keyword',
+ ['exception'] = 'Exception',
+
+ ['type'] = 'Type',
+ ['type.builtin'] = 'Type',
+ ['type.qualifier'] = 'Type',
+ ['type.definition'] = 'Typedef',
+ ['storageclass'] = 'StorageClass',
+ ['structure'] = 'Structure',
+ ['include'] = 'Include',
+ ['preproc'] = 'PreProc',
}, subcapture_fallback)
---@private
@@ -113,13 +113,13 @@ function TSHighlighterQuery.new(lang, query_string)
rawset(table, capture, id)
return id
- end
+ end,
})
if query_string then
self._query = query.parse_query(lang, query_string)
else
- self._query = query.get_query(lang, "highlights")
+ self._query = query.get_query(lang, 'highlights')
end
return self
@@ -152,17 +152,23 @@ end
function TSHighlighter.new(tree, opts)
local self = setmetatable({}, TSHighlighter)
- if type(tree:source()) ~= "number" then
- error("TSHighlighter can not be used with a string parser source.")
+ if type(tree:source()) ~= 'number' then
+ error('TSHighlighter can not be used with a string parser source.')
end
opts = opts or {}
self.tree = tree
- tree:register_cbs {
- on_changedtree = function(...) self:on_changedtree(...) end;
- on_bytes = function(...) self:on_bytes(...) end;
- on_detach = function(...) self:on_detach(...) end;
- }
+ tree:register_cbs({
+ on_changedtree = function(...)
+ self:on_changedtree(...)
+ end,
+ on_bytes = function(...)
+ self:on_bytes(...)
+ end,
+ on_detach = function(...)
+ self:on_detach(...)
+ end,
+ })
self.bufnr = tree:source()
self.edit_count = 0
@@ -181,7 +187,7 @@ function TSHighlighter.new(tree, opts)
end
end
- a.nvim_buf_set_option(self.bufnr, "syntax", "")
+ a.nvim_buf_set_option(self.bufnr, 'syntax', '')
TSHighlighter.active[self.bufnr] = self
@@ -190,7 +196,7 @@ function TSHighlighter.new(tree, opts)
-- syntax FileType autocmds. Later on we should integrate with the
-- `:syntax` and `set syntax=...` machinery properly.
if vim.g.syntax_on ~= 1 then
- vim.api.nvim_command("runtime! syntax/synload.vim")
+ vim.api.nvim_command('runtime! syntax/synload.vim')
end
self.tree:parse()
@@ -210,7 +216,7 @@ function TSHighlighter:get_highlight_state(tstree)
if not self._highlight_states[tstree] then
self._highlight_states[tstree] = {
next_row = 0,
- iter = nil
+ iter = nil,
}
end
@@ -235,7 +241,7 @@ end
---@private
function TSHighlighter:on_changedtree(changes)
for _, ch in ipairs(changes or {}) do
- a.nvim__buf_redraw_range(self.bufnr, ch[1], ch[3]+1)
+ a.nvim__buf_redraw_range(self.bufnr, ch[1], ch[3] + 1)
end
end
@@ -253,19 +259,25 @@ end
---@private
local function on_line_impl(self, buf, line)
self.tree:for_each_tree(function(tstree, tree)
- if not tstree then return end
+ if not tstree then
+ return
+ end
local root_node = tstree:root()
local root_start_row, _, root_end_row, _ = root_node:range()
-- Only worry about trees within the line range
- if root_start_row > line or root_end_row < line then return end
+ if root_start_row > line or root_end_row < line then
+ return
+ end
local state = self:get_highlight_state(tstree)
local highlighter_query = self:get_query(tree:lang())
-- Some injected languages may not have highlight queries.
- if not highlighter_query:query() then return end
+ if not highlighter_query:query() then
+ return
+ end
if state.iter == nil then
state.iter = highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1)
@@ -274,19 +286,22 @@ local function on_line_impl(self, buf, line)
while line >= state.next_row do
local capture, node, metadata = state.iter()
- if capture == nil then break end
+ if capture == nil then
+ break
+ end
local start_row, start_col, end_row, end_col = node:range()
local hl = highlighter_query.hl_cache[capture]
if hl and end_row >= line then
- a.nvim_buf_set_extmark(buf, ns, start_row, start_col,
- { end_line = end_row, end_col = end_col,
- hl_group = hl,
- ephemeral = true,
- priority = tonumber(metadata.priority) or 100, -- Low but leaves room below
- conceal = metadata.conceal,
- })
+ a.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
+ end_line = end_row,
+ end_col = end_col,
+ hl_group = hl,
+ ephemeral = true,
+ priority = tonumber(metadata.priority) or 100, -- Low but leaves room below
+ conceal = metadata.conceal,
+ })
end
if start_row > line then
state.next_row = start_row
@@ -298,7 +313,9 @@ end
---@private
function TSHighlighter._on_line(_, _win, buf, line, _)
local self = TSHighlighter.active[buf]
- if not self then return end
+ if not self then
+ return
+ end
on_line_impl(self, buf, line)
end
@@ -324,9 +341,9 @@ function TSHighlighter._on_win(_, _win, buf, _topline)
end
a.nvim_set_decoration_provider(ns, {
- on_buf = TSHighlighter._on_buf;
- on_win = TSHighlighter._on_win;
- on_line = TSHighlighter._on_line;
+ on_buf = TSHighlighter._on_buf,
+ on_win = TSHighlighter._on_win,
+ on_line = TSHighlighter._on_line,
})
return TSHighlighter
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 8b106108df..dfb6f5be84 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -22,13 +22,15 @@ function M.require_language(lang, path, silent)
end
-- TODO(bfredl): help tag?
- error("no parser for '"..lang.."' language, see :help treesitter-parsers")
+ error("no parser for '" .. lang .. "' language, see :help treesitter-parsers")
end
path = paths[1]
end
if silent then
- return pcall(function() vim._ts_add_language(path, lang) end)
+ return pcall(function()
+ vim._ts_add_language(path, lang)
+ end)
else
vim._ts_add_language(path, lang)
end
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index b83df65151..2157112d2f 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -1,6 +1,6 @@
local a = vim.api
-local query = require'vim.treesitter.query'
-local language = require'vim.treesitter.language'
+local query = require('vim.treesitter.query')
+local language = require('vim.treesitter.language')
local LanguageTree = {}
LanguageTree.__index = LanguageTree
@@ -32,9 +32,10 @@ function LanguageTree.new(source, lang, opts)
_regions = {},
_trees = {},
_opts = opts,
- _injection_query = injections[lang]
- and query.parse_query(lang, injections[lang])
- or query.get_query(lang, "injections"),
+ _injection_query = injections[lang] and query.parse_query(lang, injections[lang]) or query.get_query(
+ lang,
+ 'injections'
+ ),
_valid = false,
_parser = vim._create_ts_parser(lang),
_callbacks = {
@@ -42,11 +43,10 @@ function LanguageTree.new(source, lang, opts)
bytes = {},
detach = {},
child_added = {},
- child_removed = {}
+ child_removed = {},
},
}, LanguageTree)
-
return self
end
@@ -264,11 +264,11 @@ end
---@param regions A list of regions this tree should manage and parse.
function LanguageTree:set_included_regions(regions)
-- TODO(vigoux): I don't think string parsers are useful for now
- if type(self._source) == "number" then
+ if type(self._source) == 'number' then
-- Transform the tables from 4 element long to 6 element long (with byte offset)
for _, region in ipairs(regions) do
for i, range in ipairs(region) do
- if type(range) == "table" and #range == 4 then
+ if type(range) == 'table' and #range == 4 then
local start_row, start_col, end_row, end_col = unpack(range)
-- Easy case, this is a buffer parser
-- TODO(vigoux): proper byte computation here, and account for EOL ?
@@ -303,7 +303,9 @@ end
--- instead of using the entire nodes range.
---@private
function LanguageTree:_get_injections()
- if not self._injection_query then return {} end
+ if not self._injection_query then
+ return {}
+ end
local injections = {}
@@ -311,7 +313,9 @@ function LanguageTree:_get_injections()
local root_node = tree:root()
local start_line, _, end_line, _ = root_node:range()
- for pattern, match, metadata in self._injection_query:iter_matches(root_node, self._source, start_line, end_line+1) do
+ for pattern, match, metadata in
+ self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1)
+ do
local lang = nil
local ranges = {}
local combined = metadata.combined
@@ -322,8 +326,8 @@ function LanguageTree:_get_injections()
local content = metadata.content
-- Allow for captured nodes to be used
- if type(content) == "number" then
- content = {match[content]}
+ if type(content) == 'number' then
+ content = { match[content] }
end
if content then
@@ -342,15 +346,15 @@ function LanguageTree:_get_injections()
local name = self._injection_query.captures[id]
-- Lang should override any other language tag
- if name == "language" and not lang then
+ if name == 'language' and not lang then
lang = query.get_node_text(node, self._source)
- elseif name == "combined" then
+ elseif name == 'combined' then
combined = true
- elseif name == "content" and #ranges == 0 then
+ elseif name == 'content' and #ranges == 0 then
table.insert(ranges, node)
- -- Ignore any tags that start with "_"
- -- Allows for other tags to be used in matches
- elseif string.sub(name, 1, 1) ~= "_" then
+ -- Ignore any tags that start with "_"
+ -- Allows for other tags to be used in matches
+ elseif string.sub(name, 1, 1) ~= '_' then
if not lang then
lang = name
end
@@ -414,10 +418,19 @@ function LanguageTree:_do_callback(cb_name, ...)
end
---@private
-function LanguageTree:_on_bytes(bufnr, changed_tick,
- start_row, start_col, start_byte,
- old_row, old_col, old_byte,
- new_row, new_col, new_byte)
+function LanguageTree:_on_bytes(
+ bufnr,
+ changed_tick,
+ start_row,
+ start_col,
+ start_byte,
+ old_row,
+ old_col,
+ old_byte,
+ new_row,
+ new_col,
+ new_byte
+)
self:invalidate()
local old_end_col = old_col + ((old_row == 0) and start_col or 0)
@@ -426,16 +439,33 @@ function LanguageTree:_on_bytes(bufnr, changed_tick,
-- Edit all trees recursively, together BEFORE emitting a bytes callback.
-- In most cases this callback should only be called from the root tree.
self:for_each_tree(function(tree)
- tree:edit(start_byte,start_byte+old_byte,start_byte+new_byte,
- start_row, start_col,
- start_row+old_row, old_end_col,
- start_row+new_row, new_end_col)
+ tree:edit(
+ start_byte,
+ start_byte + old_byte,
+ start_byte + new_byte,
+ start_row,
+ start_col,
+ start_row + old_row,
+ old_end_col,
+ start_row + new_row,
+ new_end_col
+ )
end)
- self:_do_callback('bytes', bufnr, changed_tick,
- start_row, start_col, start_byte,
- old_row, old_col, old_byte,
- new_row, new_col, new_byte)
+ self:_do_callback(
+ 'bytes',
+ bufnr,
+ changed_tick,
+ start_row,
+ start_col,
+ start_byte,
+ old_row,
+ old_col,
+ old_byte,
+ new_row,
+ new_col,
+ new_byte
+ )
end
---@private
@@ -443,7 +473,6 @@ function LanguageTree:_on_reload()
self:invalidate(true)
end
-
---@private
function LanguageTree:_on_detach(...)
self:invalidate(true)
@@ -459,7 +488,9 @@ end
--- - `on_child_added` : emitted when a child is added to the tree.
--- - `on_child_removed` : emitted when a child is removed from the tree.
function LanguageTree:register_cbs(cbs)
- if not cbs then return end
+ if not cbs then
+ return
+ end
if cbs.on_changedtree then
table.insert(self._callbacks.changedtree, cbs.on_changedtree)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 8383551b5f..3c4c8fdb96 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -1,5 +1,5 @@
local a = vim.api
-local language = require'vim.treesitter.language'
+local language = require('vim.treesitter.language')
-- query: pattern matching on trees
-- predicate matching is implemented in lua
@@ -43,7 +43,9 @@ function M.get_query_files(lang, query_name, is_included)
local query_path = string.format('queries/%s/%s.scm', lang, query_name)
local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true))
- if #lang_files == 0 then return {} end
+ if #lang_files == 0 then
+ return {}
+ end
local base_langs = {}
@@ -52,7 +54,7 @@ function M.get_query_files(lang, query_name, is_included)
-- ;+ inherits: ({language},)*{language}
--
-- {language} ::= {lang} | ({lang})
- local MODELINE_FORMAT = "^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$"
+ local MODELINE_FORMAT = '^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$'
for _, file in ipairs(lang_files) do
local modeline = safe_read(file, '*l')
@@ -62,7 +64,7 @@ function M.get_query_files(lang, query_name, is_included)
if langlist then
for _, incllang in ipairs(vim.split(langlist, ',', true)) do
- local is_optional = incllang:match("%(.*%)")
+ local is_optional = incllang:match('%(.*%)')
if is_optional then
if not is_included then
@@ -90,7 +92,7 @@ end
local function read_query_files(filenames)
local contents = {}
- for _,filename in ipairs(filenames) do
+ for _, filename in ipairs(filenames) do
table.insert(contents, safe_read(filename, '*a'))
end
@@ -142,7 +144,7 @@ local query_cache = setmetatable({}, {
__index = function(tbl, key)
rawset(tbl, key, {})
return rawget(tbl, key)
- end
+ end,
})
--- Parse {query} as a string. (If the query is in a file, the caller
@@ -185,7 +187,7 @@ function M.get_node_text(node, source)
local start_row, start_col, start_byte = node:start()
local end_row, end_col, end_byte = node:end_()
- if type(source) == "number" then
+ if type(source) == 'number' then
local lines
local eof_row = a.nvim_buf_line_count(source)
if start_row >= eof_row then
@@ -201,56 +203,56 @@ function M.get_node_text(node, source)
if #lines > 0 then
if #lines == 1 then
- lines[1] = string.sub(lines[1], start_col+1, end_col)
+ lines[1] = string.sub(lines[1], start_col + 1, end_col)
else
- lines[1] = string.sub(lines[1], start_col+1)
+ lines[1] = string.sub(lines[1], start_col + 1)
lines[#lines] = string.sub(lines[#lines], 1, end_col)
end
end
- return table.concat(lines, "\n")
- elseif type(source) == "string" then
- return source:sub(start_byte+1, end_byte)
+ return table.concat(lines, '\n')
+ elseif type(source) == 'string' then
+ return source:sub(start_byte + 1, end_byte)
end
end
-- Predicate handler receive the following arguments
-- (match, pattern, bufnr, predicate)
local predicate_handlers = {
- ["eq?"] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- local node_text = M.get_node_text(node, source)
-
- local str
- if type(predicate[3]) == "string" then
- -- (#eq? @aa "foo")
- str = predicate[3]
- else
- -- (#eq? @aa @bb)
- str = M.get_node_text(match[predicate[3]], source)
- end
+ ['eq?'] = function(match, _, source, predicate)
+ local node = match[predicate[2]]
+ local node_text = M.get_node_text(node, source)
- if node_text ~= str or str == nil then
- return false
- end
+ local str
+ if type(predicate[3]) == 'string' then
+ -- (#eq? @aa "foo")
+ str = predicate[3]
+ else
+ -- (#eq? @aa @bb)
+ str = M.get_node_text(match[predicate[3]], source)
+ end
+
+ if node_text ~= str or str == nil then
+ return false
+ end
- return true
+ return true
end,
- ["lua-match?"] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- local regex = predicate[3]
- return string.find(M.get_node_text(node, source), regex)
+ ['lua-match?'] = function(match, _, source, predicate)
+ local node = match[predicate[2]]
+ local regex = predicate[3]
+ return string.find(M.get_node_text(node, source), regex)
end,
- ["match?"] = (function()
- local magic_prefixes = {['\\v']=true, ['\\m']=true, ['\\M']=true, ['\\V']=true}
+ ['match?'] = (function()
+ local magic_prefixes = { ['\\v'] = true, ['\\m'] = true, ['\\M'] = true, ['\\V'] = true }
---@private
local function check_magic(str)
- if string.len(str) < 2 or magic_prefixes[string.sub(str,1,2)] then
+ if string.len(str) < 2 or magic_prefixes[string.sub(str, 1, 2)] then
return str
end
- return '\\v'..str
+ return '\\v' .. str
end
local compiled_vim_regexes = setmetatable({}, {
@@ -258,7 +260,7 @@ local predicate_handlers = {
local res = vim.regex(check_magic(pattern))
rawset(t, pattern, res)
return res
- end
+ end,
})
return function(match, _, source, pred)
@@ -268,11 +270,11 @@ local predicate_handlers = {
end
end)(),
- ["contains?"] = function(match, _, source, predicate)
+ ['contains?'] = function(match, _, source, predicate)
local node = match[predicate[2]]
local node_text = M.get_node_text(node, source)
- for i=3,#predicate do
+ for i = 3, #predicate do
if string.find(node_text, predicate[i], 1, true) then
return true
end
@@ -281,19 +283,19 @@ local predicate_handlers = {
return false
end,
- ["any-of?"] = function(match, _, source, predicate)
+ ['any-of?'] = function(match, _, source, predicate)
local node = match[predicate[2]]
local node_text = M.get_node_text(node, source)
-- Since 'predicate' will not be used by callers of this function, use it
-- to store a string set built from the list of words to check against.
- local string_set = predicate["string_set"]
+ local string_set = predicate['string_set']
if not string_set then
string_set = {}
- for i=3,#predicate do
+ for i = 3, #predicate do
string_set[predicate[i]] = true
end
- predicate["string_set"] = string_set
+ predicate['string_set'] = string_set
end
return string_set[node_text]
@@ -301,15 +303,14 @@ local predicate_handlers = {
}
-- As we provide lua-match? also expose vim-match?
-predicate_handlers["vim-match?"] = predicate_handlers["match?"]
-
+predicate_handlers['vim-match?'] = predicate_handlers['match?']
-- Directives store metadata or perform side effects against a match.
-- Directives should always end with a `!`.
-- Directive handler receive the following arguments
-- (match, pattern, bufnr, predicate, metadata)
local directive_handlers = {
- ["set!"] = function(_, _, _, pred, metadata)
+ ['set!'] = function(_, _, _, pred, metadata)
if #pred == 4 then
-- (#set! @capture "key" "value")
local capture = pred[2]
@@ -324,9 +325,9 @@ local directive_handlers = {
end,
-- Shifts the range of a node.
-- Example: (#offset! @_node 0 1 0 -1)
- ["offset!"] = function(match, _, _, pred, metadata)
+ ['offset!'] = function(match, _, _, pred, metadata)
local offset_node = match[pred[2]]
- local range = {offset_node:range()}
+ local range = { offset_node:range() }
local start_row_offset = pred[3] or 0
local start_col_offset = pred[4] or 0
local end_row_offset = pred[5] or 0
@@ -339,9 +340,9 @@ local directive_handlers = {
-- If this produces an invalid range, we just skip it.
if range[1] < range[3] or (range[1] == range[3] and range[2] <= range[4]) then
- metadata.content = {range}
+ metadata.content = { range }
end
- end
+ end,
}
--- Adds a new predicate to be used in queries
@@ -351,7 +352,7 @@ local directive_handlers = {
--- signature will be (match, pattern, bufnr, predicate)
function M.add_predicate(name, handler, force)
if predicate_handlers[name] and not force then
- error(string.format("Overriding %s", name))
+ error(string.format('Overriding %s', name))
end
predicate_handlers[name] = handler
@@ -364,7 +365,7 @@ end
--- signature will be (match, pattern, bufnr, predicate)
function M.add_directive(name, handler, force)
if directive_handlers[name] and not force then
- error(string.format("Overriding %s", name))
+ error(string.format('Overriding %s', name))
end
directive_handlers[name] = handler
@@ -387,7 +388,7 @@ end
---@private
local function is_directive(name)
- return string.sub(name, -1) == "!"
+ return string.sub(name, -1) == '!'
end
---@private
@@ -404,7 +405,7 @@ function Query:match_preds(match, pattern, source)
-- Skip over directives... they will get processed after all the predicates.
if not is_directive(pred[1]) then
- if string.sub(pred[1], 1, 4) == "not-" then
+ if string.sub(pred[1], 1, 4) == 'not-' then
pred_name = string.sub(pred[1], 5)
is_not = true
else
@@ -415,7 +416,7 @@ function Query:match_preds(match, pattern, source)
local handler = predicate_handlers[pred_name]
if not handler then
- error(string.format("No handler for %s", pred[1]))
+ error(string.format('No handler for %s', pred[1]))
return false
end
@@ -438,7 +439,7 @@ function Query:apply_directives(match, pattern, source, metadata)
local handler = directive_handlers[pred[1]]
if not handler then
- error(string.format("No handler for %s", pred[1]))
+ error(string.format('No handler for %s', pred[1]))
return
end
@@ -447,7 +448,6 @@ function Query:apply_directives(match, pattern, source, metadata)
end
end
-
--- Returns the start and stop value if set else the node's range.
-- When the node's range is used, the stop is incremented by 1
-- to make the search inclusive.
@@ -492,7 +492,7 @@ end
---@returns The matching capture id
---@returns The captured node
function Query:iter_captures(node, source, start, stop)
- if type(source) == "number" and source == 0 then
+ if type(source) == 'number' and source == 0 then
source = vim.api.nvim_get_current_buf()
end
@@ -549,7 +549,7 @@ end
---@returns The matching pattern id
---@returns The matching match
function Query:iter_matches(node, source, start, stop)
- if type(source) == "number" and source == 0 then
+ if type(source) == 'number' and source == 0 then
source = vim.api.nvim_get_current_buf()
end
diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua
index 165dada1b8..77bca7f6c4 100644
--- a/runtime/lua/vim/ui.lua
+++ b/runtime/lua/vim/ui.lua
@@ -37,12 +37,12 @@ local M = {}
--- </pre>
function M.select(items, opts, on_choice)
- vim.validate {
+ vim.validate({
items = { items, 'table', false },
on_choice = { on_choice, 'function', false },
- }
+ })
opts = opts or {}
- local choices = {opts.prompt or 'Select one of:'}
+ local choices = { opts.prompt or 'Select one of:' }
local format_item = opts.format_item or tostring
for i, item in pairs(items) do
table.insert(choices, string.format('%d: %s', i, format_item(item)))
@@ -83,9 +83,9 @@ end
--- end)
--- </pre>
function M.input(opts, on_confirm)
- vim.validate {
+ vim.validate({
on_confirm = { on_confirm, 'function', false },
- }
+ })
opts = opts or {}
local input = vim.fn.input(opts)
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 11b661cd1a..d6b0b7410e 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -3,7 +3,6 @@
-- https://tools.ietf.org/html/rfc2732
-- https://tools.ietf.org/html/rfc2396
-
local uri_decode
do
local schar = string.char
@@ -14,7 +13,7 @@ do
return schar(tonumber(hex, 16))
end
uri_decode = function(str)
- return str:gsub("%%([a-fA-F0-9][a-fA-F0-9])", hex_to_char)
+ return str:gsub('%%([a-fA-F0-9][a-fA-F0-9])', hex_to_char)
end
end
@@ -23,33 +22,36 @@ do
local PATTERNS = {
--- RFC 2396
-- https://tools.ietf.org/html/rfc2396#section-2.2
- rfc2396 = "^A-Za-z0-9%-_.!~*'()";
+ rfc2396 = "^A-Za-z0-9%-_.!~*'()",
--- RFC 2732
-- https://tools.ietf.org/html/rfc2732
- rfc2732 = "^A-Za-z0-9%-_.!~*'()[]";
+ rfc2732 = "^A-Za-z0-9%-_.!~*'()[]",
--- RFC 3986
-- https://tools.ietf.org/html/rfc3986#section-2.2
- rfc3986 = "^A-Za-z0-9%-._~!$&'()*+,;=:@/";
+ rfc3986 = "^A-Za-z0-9%-._~!$&'()*+,;=:@/",
}
local sbyte, tohex = string.byte
if jit then
- tohex = require'bit'.tohex
+ tohex = require('bit').tohex
else
- tohex = function(b) return string.format("%02x", b) end
+ tohex = function(b)
+ return string.format('%02x', b)
+ end
end
---@private
local function percent_encode_char(char)
- return "%"..tohex(sbyte(char), 2)
+ return '%' .. tohex(sbyte(char), 2)
end
uri_encode = function(text, rfc)
- if not text then return end
+ if not text then
+ return
+ end
local pattern = PATTERNS[rfc] or PATTERNS.rfc3986
- return text:gsub("(["..pattern.."])", percent_encode_char)
+ return text:gsub('([' .. pattern .. '])', percent_encode_char)
end
end
-
---@private
local function is_windows_file_uri(uri)
return uri:match('^file:/+[a-zA-Z]:') ~= nil
@@ -59,16 +61,16 @@ end
---@param path string Path to file
---@return string URI
local function uri_from_fname(path)
- local volume_path, fname = path:match("^([a-zA-Z]:)(.*)")
+ local volume_path, fname = path:match('^([a-zA-Z]:)(.*)')
local is_windows = volume_path ~= nil
if is_windows then
- path = volume_path..uri_encode(fname:gsub("\\", "/"))
+ path = volume_path .. uri_encode(fname:gsub('\\', '/'))
else
path = uri_encode(path)
end
- local uri_parts = {"file://"}
+ local uri_parts = { 'file://' }
if is_windows then
- table.insert(uri_parts, "/")
+ table.insert(uri_parts, '/')
end
table.insert(uri_parts, path)
return table.concat(uri_parts)
@@ -82,11 +84,11 @@ local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
---@return string URI
local function uri_from_bufnr(bufnr)
local fname = vim.api.nvim_buf_get_name(bufnr)
- local volume_path = fname:match("^([a-zA-Z]:).*")
+ local volume_path = fname:match('^([a-zA-Z]:).*')
local is_windows = volume_path ~= nil
local scheme
if is_windows then
- fname = fname:gsub("\\", "/")
+ fname = fname:gsub('\\', '/')
scheme = fname:match(WINDOWS_URI_SCHEME_PATTERN)
else
scheme = fname:match(URI_SCHEME_PATTERN)
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index ab1871fe60..4f2f7b942d 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -2,7 +2,7 @@
"
" Author: Bram Moolenaar
" Copyright: Vim license applies, see ":help license"
-" Last Change: 2022 May 04
+" Last Change: 2022 May 09
"
" WORK IN PROGRESS - The basics works stable, more to come
" Note: In general you need at least GDB 7.12 because this provides the
@@ -205,8 +205,8 @@ func s:CheckGdbRunning()
return 'ok'
endfunc
+" Open a terminal window without a job, to run the debugged program in.
func s:StartDebug_term(dict)
- " Open a terminal window without a job, to run the debugged program in.
execute s:vertical ? 'vnew' : 'new'
let s:pty_job_id = termopen('tail -f /dev/null;#gdb program')
if s:pty_job_id == 0
@@ -365,8 +365,8 @@ func s:StartDebug_term(dict)
call s:StartDebugCommon(a:dict)
endfunc
+" Open a window with a prompt buffer to run gdb in.
func s:StartDebug_prompt(dict)
- " Open a window with a prompt buffer to run gdb in.
if s:vertical
vertical new
else
diff --git a/runtime/syntax/query.lua b/runtime/syntax/query.lua
index e24ff65360..8f40b1cb8a 100644
--- a/runtime/syntax/query.lua
+++ b/runtime/syntax/query.lua
@@ -3,4 +3,4 @@
-- Last Change: 2022 Apr 13
-- it's a lisp!
-vim.cmd [[ runtime! syntax/lisp.vim ]]
+vim.cmd([[ runtime! syntax/lisp.vim ]])
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 0e6ec19ff8..5a0dd4f2d7 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -120,9 +120,6 @@ else
com! -nargs=* VimFoldt <args>
endif
-" commands not picked up by the generator (due to non-standard format) {{{2
-syn keyword vimCommand contained py3
-
" Deprecated variable options {{{2
if exists("g:vim_minlines")
let g:vimsyn_minlines= g:vim_minlines
diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua
index ff60b6cce7..7e9d649cb4 100644
--- a/scripts/genvimvim.lua
+++ b/scripts/genvimvim.lua
@@ -44,12 +44,13 @@ local function cmd_kw(prev_cmd, cmd)
end
-- Exclude these from the vimCommand keyword list, they are handled specially
--- in syntax/vim.vim (vimAugroupKey, vimAutoCmd). #9327
-local function is_autocmd_cmd(cmd)
+-- in syntax/vim.vim (vimAugroupKey, vimAutoCmd, vimSubst). #9327
+local function is_special_cased_cmd(cmd)
return (cmd == 'augroup'
or cmd == 'autocmd'
or cmd == 'doautocmd'
- or cmd == 'doautoall')
+ or cmd == 'doautoall'
+ or cmd == 'substitute')
end
local vimcmd_start = 'syn keyword vimCommand contained '
@@ -60,7 +61,7 @@ for _, cmd_desc in ipairs(ex_cmds.cmds) do
w('\n' .. vimcmd_start)
end
local cmd = cmd_desc.command
- if cmd:match('%w') and cmd ~= 'z' and not is_autocmd_cmd(cmd) then
+ if cmd:match('%w') and cmd ~= 'z' and not is_special_cased_cmd(cmd) then
w(' ' .. cmd_kw(prev_cmd, cmd))
end
prev_cmd = cmd
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index c32370517c..6a206066b8 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -403,6 +403,29 @@ function TLua2DoX_filter.readfile(this,AppStamp,Filename)
if string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment
state = 'in_magic_comment'
local magic = string.sub(line, 4 + offset)
+
+ local magic_split = string_split(magic, ' ')
+
+ local type_index = 2
+ if magic_split[1] == 'param' then
+ type_index = type_index + 1
+ end
+
+ if magic_split[type_index] == 'number' or
+ magic_split[type_index] == 'number|nil' or
+ magic_split[type_index] == 'string' or
+ magic_split[type_index] == 'string|nil' or
+ magic_split[type_index] == 'table' or
+ magic_split[type_index] == 'table|nil' or
+ magic_split[type_index] == 'boolean' or
+ magic_split[type_index] == 'boolean|nil' or
+ magic_split[type_index] == 'function' or
+ magic_split[type_index] == 'function|nil'
+ then
+ magic_split[type_index] = '(' .. magic_split[type_index] .. ')'
+ end
+ magic = table.concat(magic_split, ' ')
+
outStream:writeln('/// @' .. magic)
fn_magic = checkComment4fn(fn_magic,magic)
elseif string.sub(line,3,3)=='-' then -- it's a nonmagic doc comment
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 57f51d9d46..e7e8f0b274 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -239,6 +239,10 @@ preprocess_patch() {
LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/highlight\(\.[ch]\)/\1\/highlight_group\2/g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
+ # Rename keymap.h to keycodes.h
+ LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/keymap\.h/\1\/keycodes.h/g' \
+ "$file" > "$file".tmp && mv "$file".tmp "$file"
+
# Rename test_urls.vim to check_urls.vim
LC_ALL=C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls\.vim\)@\1/scripts/check\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index e6f70033d0..2a323bdea0 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -185,15 +185,8 @@ if(NOT MSVC)
set_source_files_properties(
${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion")
- # gperf generates ANSI-C with incorrect linkage, ignore it.
- check_c_compiler_flag(-Wstatic-in-inline HAS_WSTATIC_IN_INLINE)
- if(HAS_WSTATIC_IN_INLINE)
- set_source_files_properties(
- eval/funcs.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-static-in-inline -Wno-conversion")
- else()
- set_source_files_properties(
- eval/funcs.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
- endif()
+ set_source_files_properties(
+ eval/funcs.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
endif()
if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$")
@@ -408,14 +401,9 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua
)
-if(NOT GPERF_PRG)
- message(FATAL_ERROR "gperf was not found.")
-endif()
add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
COMMAND ${LUA_PRG} ${FUNCS_GENERATOR}
- ${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
- COMMAND ${GPERF_PRG}
- ${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS}
+ ${CMAKE_CURRENT_LIST_DIR} ${LUA_SHARED_MODULE_SOURCE} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA}
)
list(APPEND NVIM_GENERATED_FOR_SOURCES
diff --git a/src/nvim/README.md b/src/nvim/README.md
index c7cb233c73..9417629691 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -38,7 +38,7 @@ alternate file (e.g. stderr) use `LOG_CALLSTACK_TO_FILE(FILE*)`. Requires
Many log messages have a shared prefix, such as "UI" or "RPC". Use the shell to
filter the log, e.g. at DEBUG level you might want to exclude UI messages:
- tail -F ~/.cache/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
+ tail -F ~/.local/state/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
Build with ASAN
---------------
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 45dadae1dd..9842975d62 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -262,7 +262,7 @@ void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *e
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param start First line index
-/// @param end Last line index (exclusive)
+/// @param end Last line index, exclusive
/// @param strict_indexing Whether out-of-bounds should be an error.
/// @param[out] err Error details, if any
/// @return Array of lines, or empty array for unloaded buffer.
@@ -358,7 +358,7 @@ static bool check_string_array(Array arr, bool disallow_nl, Error *err)
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param start First line index
-/// @param end Last line index (exclusive)
+/// @param end Last line index, exclusive
/// @param strict_indexing Whether out-of-bounds should be an error.
/// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any
@@ -514,24 +514,25 @@ end:
/// Sets (replaces) a range in the buffer
///
-/// This is recommended over nvim_buf_set_lines when only modifying parts of a
-/// line, as extmarks will be preserved on non-modified parts of the touched
+/// This is recommended over |nvim_buf_set_lines()| when only modifying parts of
+/// a line, as extmarks will be preserved on non-modified parts of the touched
/// lines.
///
-/// Indexing is zero-based and end-exclusive.
+/// Indexing is zero-based. Row indices are end-inclusive, and column indices
+/// are end-exclusive.
///
-/// To insert text at a given index, set `start` and `end` ranges to the same
-/// index. To delete a range, set `replacement` to an array containing
-/// an empty string, or simply an empty array.
+/// To insert text at a given `(row, column)` location, use `start_row = end_row
+/// = row` and `start_col = end_col = col`. To delete the text in a range, use
+/// `replacement = {}`.
///
-/// Prefer nvim_buf_set_lines when adding or deleting entire lines only.
+/// Prefer |nvim_buf_set_lines()| if you are only adding or deleting entire lines.
///
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param start_row First line index
-/// @param start_col First column
-/// @param end_row Last line index
-/// @param end_col Last column
+/// @param start_col Starting column (byte offset) on first line
+/// @param end_row Last line index, inclusive
+/// @param end_col Ending column (byte offset) on last line, exclusive
/// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any
void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, Integer start_col,
@@ -760,16 +761,17 @@ end:
/// This differs from |nvim_buf_get_lines()| in that it allows retrieving only
/// portions of a line.
///
-/// Indexing is zero-based. Column indices are end-exclusive.
+/// Indexing is zero-based. Row indices are end-inclusive, and column indices
+/// are end-exclusive.
///
/// Prefer |nvim_buf_get_lines()| when retrieving entire lines.
///
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param start_row First line index
-/// @param start_col Starting byte offset of first line
-/// @param end_row Last line index
-/// @param end_col Ending byte offset of last line (exclusive)
+/// @param start_col Starting column (byte offset) on first line
+/// @param end_row Last line index, inclusive
+/// @param end_col Ending column (byte offset) on last line, exclusive
/// @param opts Optional parameters. Currently unused.
/// @param[out] err Error details, if any
/// @return Array of lines, or empty array for unloaded buffer.
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 5baffaf505..78f8ed3cca 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -155,5 +155,44 @@ return {
create_augroup = {
"clear";
};
+ cmd = {
+ "cmd";
+ "range";
+ "count";
+ "reg";
+ "bang";
+ "args";
+ "magic";
+ "mods";
+ "nargs";
+ "addr";
+ "nextcmd";
+ };
+ cmd_magic = {
+ "file";
+ "bar";
+ };
+ cmd_mods = {
+ "silent";
+ "emsg_silent";
+ "sandbox";
+ "noautocmd";
+ "browse";
+ "confirm";
+ "hide";
+ "keepalt";
+ "keepjumps";
+ "keepmarks";
+ "keeppatterns";
+ "lockmarks";
+ "noswapfile";
+ "tab";
+ "verbose";
+ "vertical";
+ "split";
+ };
+ cmd_opts = {
+ "output";
+ };
}
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index eb86964a72..542e5c4953 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -19,6 +19,7 @@
#include "nvim/decoration.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
@@ -1690,3 +1691,175 @@ int init_sign_text(char **sign_text, char *text)
return OK;
}
+
+/// Check if a string contains only whitespace characters.
+bool string_iswhite(String str)
+{
+ for (size_t i = 0; i < str.size; i++) {
+ if (!ascii_iswhite(str.data[i])) {
+ // Found a non-whitespace character
+ return false;
+ } else if (str.data[i] == NUL) {
+ // Terminate at first occurence of a NUL character
+ break;
+ }
+ }
+ return true;
+}
+
+// Add modifier string for command into the command line. Includes trailing whitespace if non-empty.
+// @return OK or FAIL.
+static int add_cmd_modifier_str(char *cmdline, size_t *pos, const size_t bufsize,
+ CmdParseInfo *cmdinfo)
+{
+#define APPEND_MODIFIER(...) \
+ do { \
+ if (*pos < bufsize) { \
+ *pos += (size_t)snprintf(cmdline + *pos, bufsize - *pos, __VA_ARGS__); \
+ } \
+ if (*pos < bufsize) { \
+ cmdline[*pos] = ' '; \
+ *pos += 1; \
+ } else { \
+ goto err; \
+ } \
+ } while (0)
+
+#define APPEND_MODIFIER_IF(cond, mod) \
+ do { \
+ if (cond) { \
+ APPEND_MODIFIER(mod); \
+ } \
+ } while (0)
+
+ if (cmdinfo->cmdmod.tab != 0) {
+ APPEND_MODIFIER("%dtab", cmdinfo->cmdmod.tab - 1);
+ }
+ if (cmdinfo->verbose != -1) {
+ APPEND_MODIFIER("%ldverbose", cmdinfo->verbose);
+ }
+
+ switch (cmdinfo->cmdmod.split & (WSP_ABOVE | WSP_BELOW | WSP_TOP | WSP_BOT)) {
+ case WSP_ABOVE:
+ APPEND_MODIFIER("aboveleft");
+ break;
+ case WSP_BELOW:
+ APPEND_MODIFIER("belowright");
+ break;
+ case WSP_TOP:
+ APPEND_MODIFIER("topleft");
+ break;
+ case WSP_BOT:
+ APPEND_MODIFIER("botright");
+ break;
+ default:
+ break;
+ }
+
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.split & WSP_VERT, "vertical");
+
+ if (cmdinfo->emsg_silent) {
+ APPEND_MODIFIER("silent!");
+ } else if (cmdinfo->silent) {
+ APPEND_MODIFIER("silent");
+ }
+
+ APPEND_MODIFIER_IF(cmdinfo->sandbox, "sandbox");
+ APPEND_MODIFIER_IF(cmdinfo->noautocmd, "noautocmd");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.browse, "browse");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.confirm, "confirm");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.hide, "hide");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepalt, "keepalt");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepjumps, "keepjumps");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepmarks, "keepmarks");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.keeppatterns, "keeppatterns");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.lockmarks, "lockmarks");
+ APPEND_MODIFIER_IF(cmdinfo->cmdmod.noswapfile, "noswapfile");
+
+ return OK;
+err:
+ return FAIL;
+
+#undef APPEND_MODIFIER
+#undef APPEND_MODIFIER_IF
+}
+
+/// Build cmdline string for command, used by `nvim_cmd()`.
+///
+/// @return OK or FAIL.
+int build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char **args,
+ size_t argc)
+{
+ const size_t bufsize = IOSIZE;
+ size_t pos = 0;
+ char *cmdline = xcalloc(bufsize, sizeof(char));
+
+#define CMDLINE_APPEND(...) \
+ do { \
+ if (pos < bufsize) { \
+ pos += (size_t)snprintf(cmdline + pos, bufsize - pos, __VA_ARGS__); \
+ } else { \
+ goto err; \
+ } \
+ } while (0)
+
+ // Command modifiers.
+ if (add_cmd_modifier_str(cmdline, &pos, bufsize, cmdinfo) == FAIL) {
+ goto err;
+ }
+
+ // Command range / count.
+ if (eap->argt & EX_RANGE) {
+ if (eap->addr_count == 1) {
+ CMDLINE_APPEND("%ld", eap->line2);
+ } else if (eap->addr_count > 1) {
+ CMDLINE_APPEND("%ld,%ld", eap->line1, eap->line2);
+ eap->addr_count = 2; // Make sure address count is not greater than 2
+ }
+ }
+
+ // Keep the index of the position where command name starts, so eap->cmd can point to it.
+ size_t cmdname_idx = pos;
+ CMDLINE_APPEND("%s", eap->cmd);
+ eap->cmd = cmdline + cmdname_idx;
+
+ // Command bang.
+ if (eap->argt & EX_BANG && eap->forceit) {
+ CMDLINE_APPEND("!");
+ }
+
+ // Command register.
+ if (eap->argt & EX_REGSTR && eap->regname) {
+ CMDLINE_APPEND(" %c", eap->regname);
+ }
+
+ // Iterate through each argument and store the starting position and length of each argument in
+ // the cmdline string in `eap->args` and `eap->arglens`, respectively.
+ eap->args = xcalloc(argc, sizeof(char *));
+ eap->arglens = xcalloc(argc, sizeof(size_t));
+ for (size_t i = 0; i < argc; i++) {
+ eap->args[i] = cmdline + pos + 1; // add 1 to skip the leading space.
+ eap->arglens[i] = STRLEN(args[i]);
+ CMDLINE_APPEND(" %s", args[i]);
+ }
+ eap->argc = argc;
+ // If there isn't an argument, make eap->arg point to end of cmd
+ eap->arg = argc > 0 ? eap->args[0] : cmdline + pos;
+
+ // Replace, :make and :grep with 'makeprg' and 'grepprg'.
+ char *p = replace_makeprg(eap, eap->arg, cmdlinep);
+ if (p != eap->arg) {
+ // If replace_makeprg modified the cmdline string, correct the argument pointers.
+ assert(argc == 1);
+ eap->arg = p;
+ eap->args[0] = p;
+ }
+
+ *cmdlinep = cmdline;
+ return OK;
+err:
+ xfree(cmdline);
+ return FAIL;
+
+#undef CMDLINE_APPEND
+}
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index c4a301839f..02f406d686 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -10,10 +10,14 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vimscript.h"
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds2.h"
+#include "nvim/ops.h"
+#include "nvim/strings.h"
+#include "nvim/vim.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
#include "nvim/window.h"
@@ -22,7 +26,9 @@
# include "api/vimscript.c.generated.h"
#endif
-/// Executes Vimscript (multiline block of Ex-commands), like anonymous
+#define IS_USER_CMDIDX(idx) ((int)(idx) < 0)
+
+/// Executes Vimscript (multiline block of Ex commands), like anonymous
/// |:source|.
///
/// Unlike |nvim_command()| this function supports heredocs, script-scope (s:),
@@ -32,6 +38,7 @@
///
/// @see |execute()|
/// @see |nvim_command()|
+/// @see |nvim_cmd()|
///
/// @param src Vimscript code
/// @param output Capture and return all (non-error, non-shell |:!|) output
@@ -89,13 +96,16 @@ theend:
return (String)STRING_INIT;
}
-/// Executes an ex-command.
+/// Executes an Ex command.
///
/// On execution error: fails with VimL error, does not update v:errmsg.
///
-/// @see |nvim_exec()|
+/// Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script
+/// or an Ex command directly, use |nvim_exec()|. To construct an Ex command using a structured
+/// format and then execute it, use |nvim_cmd()|. To modify an Ex command before evaluating it, use
+/// |nvim_parse_cmd()| in conjunction with |nvim_cmd()|.
///
-/// @param command Ex-command string
+/// @param command Ex command string
/// @param[out] err Error details (Vim error), if any
void nvim_command(String command, Error *err)
FUNC_API_SINCE(1)
@@ -978,3 +988,370 @@ end:
xfree(cmdline);
return result;
}
+
+/// Executes an Ex command.
+///
+/// Unlike |nvim_command()| this command takes a structured Dictionary instead of a String. This
+/// allows for easier construction and manipulation of an Ex command. This also allows for things
+/// such as having spaces inside a command argument, expanding filenames in a command that otherwise
+/// doesn't expand filenames, etc.
+///
+/// @see |nvim_exec()|
+/// @see |nvim_command()|
+///
+/// @param cmd Command to execute. Must be a Dictionary that can contain the same values as
+/// the return value of |nvim_parse_cmd()| except "addr", "nargs" and "nextcmd"
+/// which are ignored if provided. All values except for "cmd" are optional.
+/// @param opts Optional parameters.
+/// - output: (boolean, default false) Whether to return command output.
+/// @param[out] err Error details, if any.
+/// @return Command output (non-error, non-shell |:!|) if `output` is true, else empty string.
+String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error *err)
+ FUNC_API_SINCE(10)
+{
+ exarg_T ea;
+ memset(&ea, 0, sizeof(ea));
+ ea.verbose_save = -1;
+ ea.save_msg_silent = -1;
+
+ CmdParseInfo cmdinfo;
+ memset(&cmdinfo, 0, sizeof(cmdinfo));
+ cmdinfo.verbose = -1;
+
+ char *cmdline = NULL;
+ char *cmdname = NULL;
+ char **args = NULL;
+ size_t argc = 0;
+
+ String retv = (String)STRING_INIT;
+
+#define OBJ_TO_BOOL(var, value, default, varname) \
+ do { \
+ var = api_object_to_bool(value, varname, default, err); \
+ if (ERROR_SET(err)) { \
+ goto end; \
+ } \
+ } while (0)
+
+#define VALIDATION_ERROR(...) \
+ do { \
+ api_set_error(err, kErrorTypeValidation, __VA_ARGS__); \
+ goto end; \
+ } while (0)
+
+ bool output;
+ OBJ_TO_BOOL(output, opts->output, false, "'output'");
+
+ // First, parse the command name and check if it exists and is valid.
+ if (!HAS_KEY(cmd->cmd) || cmd->cmd.type != kObjectTypeString
+ || cmd->cmd.data.string.data[0] == NUL) {
+ VALIDATION_ERROR("'cmd' must be a non-empty String");
+ }
+
+ cmdname = string_to_cstr(cmd->cmd.data.string);
+ ea.cmd = cmdname;
+
+ char *p = find_ex_command(&ea, NULL);
+
+ // If this looks like an undefined user command and there are CmdUndefined
+ // autocommands defined, trigger the matching autocommands.
+ if (p != NULL && ea.cmdidx == CMD_SIZE && ASCII_ISUPPER(*ea.cmd)
+ && has_event(EVENT_CMDUNDEFINED)) {
+ p = xstrdup(cmdname);
+ int ret = apply_autocmds(EVENT_CMDUNDEFINED, (char_u *)p, (char_u *)p, true, NULL);
+ xfree(p);
+ // If the autocommands did something and didn't cause an error, try
+ // finding the command again.
+ p = (ret && !aborting()) ? find_ex_command(&ea, NULL) : ea.cmd;
+ }
+
+ if (p == NULL || ea.cmdidx == CMD_SIZE) {
+ VALIDATION_ERROR("Command not found: %s", cmdname);
+ }
+ if (is_cmd_ni(ea.cmdidx)) {
+ VALIDATION_ERROR("Command not implemented: %s", cmdname);
+ }
+
+ // Get the command flags so that we can know what type of arguments the command uses.
+ // Not required for a user command since `find_ex_command` already deals with it in that case.
+ if (!IS_USER_CMDIDX(ea.cmdidx)) {
+ ea.argt = get_cmd_argt(ea.cmdidx);
+ }
+
+ // Parse command arguments since it's needed to get the command address type.
+ if (HAS_KEY(cmd->args)) {
+ if (cmd->args.type != kObjectTypeArray) {
+ VALIDATION_ERROR("'args' must be an Array");
+ }
+ // Check if every argument is valid
+ for (size_t i = 0; i < cmd->args.data.array.size; i++) {
+ Object elem = cmd->args.data.array.items[i];
+ if (elem.type != kObjectTypeString) {
+ VALIDATION_ERROR("Command argument must be a String");
+ } else if (string_iswhite(elem.data.string)) {
+ VALIDATION_ERROR("Command argument must have non-whitespace characters");
+ }
+ }
+
+ argc = cmd->args.data.array.size;
+ bool argc_valid;
+
+ // Check if correct number of arguments is used.
+ switch (ea.argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
+ case EX_EXTRA | EX_NOSPC | EX_NEEDARG:
+ argc_valid = argc == 1;
+ break;
+ case EX_EXTRA | EX_NOSPC:
+ argc_valid = argc <= 1;
+ break;
+ case EX_EXTRA | EX_NEEDARG:
+ argc_valid = argc >= 1;
+ break;
+ case EX_EXTRA:
+ argc_valid = true;
+ break;
+ default:
+ argc_valid = argc == 0;
+ break;
+ }
+
+ if (!argc_valid) {
+ argc = 0; // Ensure that args array isn't erroneously freed at the end.
+ VALIDATION_ERROR("Incorrect number of arguments supplied");
+ }
+
+ if (argc != 0) {
+ args = xcalloc(argc, sizeof(char *));
+
+ for (size_t i = 0; i < argc; i++) {
+ args[i] = string_to_cstr(cmd->args.data.array.items[i].data.string);
+ }
+ }
+ }
+
+ // Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()`
+ // since it only ever checks the first argument.
+ set_cmd_addr_type(&ea, argc > 0 ? (char_u *)args[0] : NULL);
+
+ if (HAS_KEY(cmd->range)) {
+ if (!(ea.argt & EX_RANGE)) {
+ VALIDATION_ERROR("Command cannot accept a range");
+ } else if (cmd->range.type != kObjectTypeArray) {
+ VALIDATION_ERROR("'range' must be an Array");
+ } else if (cmd->range.data.array.size > 2) {
+ VALIDATION_ERROR("'range' cannot contain more than two elements");
+ }
+
+ Array range = cmd->range.data.array;
+ ea.addr_count = (int)range.size;
+
+ for (size_t i = 0; i < range.size; i++) {
+ Object elem = range.items[i];
+ if (elem.type != kObjectTypeInteger || elem.data.integer < 0) {
+ VALIDATION_ERROR("'range' element must be a non-negative Integer");
+ }
+ }
+
+ if (range.size > 0) {
+ ea.line1 = range.items[0].data.integer;
+ ea.line2 = range.items[range.size - 1].data.integer;
+ }
+
+ if (invalid_range(&ea) != NULL) {
+ VALIDATION_ERROR("Invalid range provided");
+ }
+ }
+ if (ea.addr_count == 0) {
+ if (ea.argt & EX_DFLALL) {
+ set_cmd_dflall_range(&ea); // Default range for range=%
+ } else {
+ ea.line1 = ea.line2 = get_cmd_default_range(&ea); // Default range.
+
+ if (ea.addr_type == ADDR_OTHER) {
+ // Default is 1, not cursor.
+ ea.line2 = 1;
+ }
+ }
+ }
+
+ if (HAS_KEY(cmd->count)) {
+ if (!(ea.argt & EX_COUNT)) {
+ VALIDATION_ERROR("Command cannot accept a count");
+ } else if (cmd->count.type != kObjectTypeInteger || cmd->count.data.integer < 0) {
+ VALIDATION_ERROR("'count' must be a non-negative Integer");
+ }
+ set_cmd_count(&ea, cmd->count.data.integer, true);
+ }
+
+ if (HAS_KEY(cmd->reg)) {
+ if (!(ea.argt & EX_REGSTR)) {
+ VALIDATION_ERROR("Command cannot accept a register");
+ } else if (cmd->reg.type != kObjectTypeString || cmd->reg.data.string.size != 1) {
+ VALIDATION_ERROR("'reg' must be a single character");
+ }
+ char regname = cmd->reg.data.string.data[0];
+ if (regname == '=') {
+ VALIDATION_ERROR("Cannot use register \"=");
+ } else if (!valid_yank_reg(regname, ea.cmdidx != CMD_put && !IS_USER_CMDIDX(ea.cmdidx))) {
+ VALIDATION_ERROR("Invalid register: \"%c", regname);
+ }
+ ea.regname = (uint8_t)regname;
+ }
+
+ OBJ_TO_BOOL(ea.forceit, cmd->bang, false, "'bang'");
+ if (ea.forceit && !(ea.argt & EX_BANG)) {
+ VALIDATION_ERROR("Command cannot accept a bang");
+ }
+
+ if (HAS_KEY(cmd->magic)) {
+ if (cmd->magic.type != kObjectTypeDictionary) {
+ VALIDATION_ERROR("'magic' must be a Dictionary");
+ }
+
+ Dict(cmd_magic) magic = { 0 };
+ if (!api_dict_to_keydict(&magic, KeyDict_cmd_magic_get_field,
+ cmd->magic.data.dictionary, err)) {
+ goto end;
+ }
+
+ OBJ_TO_BOOL(cmdinfo.magic.file, magic.file, ea.argt & EX_XFILE, "'magic.file'");
+ OBJ_TO_BOOL(cmdinfo.magic.bar, magic.bar, ea.argt & EX_TRLBAR, "'magic.bar'");
+ } else {
+ cmdinfo.magic.file = ea.argt & EX_XFILE;
+ cmdinfo.magic.bar = ea.argt & EX_TRLBAR;
+ }
+
+ if (HAS_KEY(cmd->mods)) {
+ if (cmd->mods.type != kObjectTypeDictionary) {
+ VALIDATION_ERROR("'mods' must be a Dictionary");
+ }
+
+ Dict(cmd_mods) mods = { 0 };
+ if (!api_dict_to_keydict(&mods, KeyDict_cmd_mods_get_field, cmd->mods.data.dictionary, err)) {
+ goto end;
+ }
+
+ if (HAS_KEY(mods.tab)) {
+ if (mods.tab.type != kObjectTypeInteger || mods.tab.data.integer < 0) {
+ VALIDATION_ERROR("'mods.tab' must be a non-negative Integer");
+ }
+ cmdinfo.cmdmod.tab = (int)mods.tab.data.integer + 1;
+ }
+
+ if (HAS_KEY(mods.verbose)) {
+ if (mods.verbose.type != kObjectTypeInteger || mods.verbose.data.integer <= 0) {
+ VALIDATION_ERROR("'mods.verbose' must be a non-negative Integer");
+ }
+ cmdinfo.verbose = mods.verbose.data.integer;
+ }
+
+ bool vertical;
+ OBJ_TO_BOOL(vertical, mods.vertical, false, "'mods.vertical'");
+ cmdinfo.cmdmod.split |= (vertical ? WSP_VERT : 0);
+
+ if (HAS_KEY(mods.split)) {
+ if (mods.split.type != kObjectTypeString) {
+ VALIDATION_ERROR("'mods.split' must be a String");
+ }
+
+ if (STRCMP(mods.split.data.string.data, "aboveleft") == 0
+ || STRCMP(mods.split.data.string.data, "leftabove") == 0) {
+ cmdinfo.cmdmod.split |= WSP_ABOVE;
+ } else if (STRCMP(mods.split.data.string.data, "belowright") == 0
+ || STRCMP(mods.split.data.string.data, "rightbelow") == 0) {
+ cmdinfo.cmdmod.split |= WSP_BELOW;
+ } else if (STRCMP(mods.split.data.string.data, "topleft") == 0) {
+ cmdinfo.cmdmod.split |= WSP_TOP;
+ } else if (STRCMP(mods.split.data.string.data, "botright") == 0) {
+ cmdinfo.cmdmod.split |= WSP_BOT;
+ } else {
+ VALIDATION_ERROR("Invalid value for 'mods.split'");
+ }
+ }
+
+ OBJ_TO_BOOL(cmdinfo.silent, mods.silent, false, "'mods.silent'");
+ OBJ_TO_BOOL(cmdinfo.emsg_silent, mods.emsg_silent, false, "'mods.emsg_silent'");
+ OBJ_TO_BOOL(cmdinfo.sandbox, mods.sandbox, false, "'mods.sandbox'");
+ OBJ_TO_BOOL(cmdinfo.noautocmd, mods.noautocmd, false, "'mods.noautocmd'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.browse, mods.browse, false, "'mods.browse'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.confirm, mods.confirm, false, "'mods.confirm'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.hide, mods.hide, false, "'mods.hide'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.keepalt, mods.keepalt, false, "'mods.keepalt'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.keepjumps, mods.keepjumps, false, "'mods.keepjumps'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.keepmarks, mods.keepmarks, false, "'mods.keepmarks'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.keeppatterns, mods.keeppatterns, false, "'mods.keeppatterns'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.lockmarks, mods.lockmarks, false, "'mods.lockmarks'");
+ OBJ_TO_BOOL(cmdinfo.cmdmod.noswapfile, mods.noswapfile, false, "'mods.noswapfile'");
+
+ if (cmdinfo.sandbox && !(ea.argt & EX_SBOXOK)) {
+ VALIDATION_ERROR("Command cannot be run in sandbox");
+ }
+ }
+
+ // Finally, build the command line string that will be stored inside ea.cmdlinep.
+ // This also sets the values of ea.cmd, ea.arg, ea.args and ea.arglens.
+ if (build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc) == FAIL) {
+ goto end;
+ }
+ ea.cmdlinep = &cmdline;
+
+ garray_T capture_local;
+ const int save_msg_silent = msg_silent;
+ garray_T * const save_capture_ga = capture_ga;
+
+ if (output) {
+ ga_init(&capture_local, 1, 80);
+ capture_ga = &capture_local;
+ }
+
+ try_start();
+ if (output) {
+ msg_silent++;
+ }
+
+ WITH_SCRIPT_CONTEXT(channel_id, {
+ execute_cmd(&ea, &cmdinfo);
+ });
+
+ if (output) {
+ capture_ga = save_capture_ga;
+ msg_silent = save_msg_silent;
+ }
+ try_end(err);
+
+ if (ERROR_SET(err)) {
+ goto clear_ga;
+ }
+
+ if (output && capture_local.ga_len > 1) {
+ retv = (String){
+ .data = capture_local.ga_data,
+ .size = (size_t)capture_local.ga_len,
+ };
+ // redir usually (except :echon) prepends a newline.
+ if (retv.data[0] == '\n') {
+ memmove(retv.data, retv.data + 1, retv.size - 1);
+ retv.data[retv.size - 1] = '\0';
+ retv.size = retv.size - 1;
+ }
+ goto end;
+ }
+clear_ga:
+ if (output) {
+ ga_clear(&capture_local);
+ }
+end:
+ xfree(cmdline);
+ xfree(cmdname);
+ xfree(ea.args);
+ xfree(ea.arglens);
+ for (size_t i = 0; i < argc; i++) {
+ xfree(args[i]);
+ }
+ xfree(args);
+
+ return retv;
+
+#undef OBJ_TO_BOOL
+#undef VALIDATION_ERROR
+}
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 30e5edb4d0..18c8a2c250 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -2366,7 +2366,7 @@ static char_u *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case)
{
// First try the short file name, then the long file name.
char_u *match = fname_match(rmp, buf->b_sfname, ignore_case);
- if (match == NULL) {
+ if (match == NULL && rmp->regprog != NULL) {
match = fname_match(rmp, buf->b_ffname, ignore_case);
}
return match;
@@ -2387,7 +2387,7 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case)
rmp->rm_ic = p_fic || ignore_case;
if (vim_regexec(rmp, name, (colnr_T)0)) {
match = name;
- } else {
+ } else if (rmp->regprog != NULL) {
// Replace $(HOME) with '~' and try matching again.
p = home_replace_save(NULL, name);
if (vim_regexec(rmp, p, (colnr_T)0)) {
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 90a6f81cc0..c2e61271c7 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -29,7 +29,7 @@
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index cf5f86b3f7..ee00736b63 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -80,9 +80,6 @@ typedef enum {
kSomeMatchStrPos, ///< Data for matchstrpos().
} SomeMatchType;
-KHASH_MAP_INIT_STR(functions, VimLFuncDef)
-
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/funcs.c.generated.h"
@@ -134,14 +131,11 @@ char *get_function_name(expand_T *xp, int idx)
return (char *)name;
}
}
- while ((size_t)++intidx < ARRAY_SIZE(functions)
- && functions[intidx].name[0] == '\0') {}
- if ((size_t)intidx >= ARRAY_SIZE(functions)) {
+ const char *const key = functions[++intidx].name;
+ if (!key) {
return NULL;
}
-
- const char *const key = functions[intidx].name;
const size_t key_len = strlen(key);
memcpy(IObuff, key, key_len);
IObuff[key_len] = '(';
@@ -178,18 +172,19 @@ char *get_expr_name(expand_T *xp, int idx)
/// @param[in] name Name of the function.
///
/// @return pointer to the function definition or NULL if not found.
-const VimLFuncDef *find_internal_func(const char *const name)
+const EvalFuncDef *find_internal_func(const char *const name)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
size_t len = strlen(name);
- return find_internal_func_gperf(name, len);
+ int index = find_internal_func_hash(name, len);
+ return index >= 0 ? &functions[index] : NULL;
}
int call_internal_func(const char_u *const fname, const int argcount, typval_T *const argvars,
typval_T *const rettv)
FUNC_ATTR_NONNULL_ALL
{
- const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
+ const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef == NULL) {
return ERROR_UNKNOWN;
} else if (argcount < fdef->min_argc) {
@@ -207,7 +202,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T
typval_T *const rettv, typval_T *const basetv)
FUNC_ATTR_NONNULL_ALL
{
- const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
+ const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef == NULL) {
return ERROR_UNKNOWN;
} else if (fdef->base_arg == BASE_NONE) {
@@ -9842,6 +9837,10 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = get_xdg_home(kXDGDataHome);
} else if (strequal(p, "cache")) {
rettv->vval.v_string = get_xdg_home(kXDGCacheHome);
+ } else if (strequal(p, "state")) {
+ rettv->vval.v_string = get_xdg_home(kXDGStateHome);
+ } else if (strequal(p, "log")) {
+ rettv->vval.v_string = get_xdg_home(kXDGStateHome);
} else if (strequal(p, "config_dirs")) {
get_xdg_var_list(kXDGConfigDirs, rettv);
} else if (strequal(p, "data_dirs")) {
diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h
index c6a0cb959e..4ab4c8f800 100644
--- a/src/nvim/eval/funcs.h
+++ b/src/nvim/eval/funcs.h
@@ -9,19 +9,19 @@ typedef void (*FunPtr)(void);
/// Prototype of C function that implements VimL function
typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
-/// Special flags for base_arg @see VimLFuncDef
+/// Special flags for base_arg @see EvalFuncDef
#define BASE_NONE 0 ///< Not a method (no base argument).
#define BASE_LAST UINT8_MAX ///< Use the last argument as the method base.
/// Structure holding VimL function definition
-typedef struct fst {
+typedef struct {
char *name; ///< Name of the function.
uint8_t min_argc; ///< Minimal number of arguments.
uint8_t max_argc; ///< Maximal number of arguments.
uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
VimLFunc func; ///< Function implementation.
FunPtr data; ///< Userdata for function implementation.
-} VimLFuncDef;
+} EvalFuncDef;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/funcs.h.generated.h"
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index a51f805984..d8dd3da9e6 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -175,6 +175,9 @@ enum {
/// Arguments used for Ex commands.
struct exarg {
char *arg; ///< argument of the command
+ char **args; ///< starting position of command arguments
+ size_t *arglens; ///< length of command arguments
+ size_t argc; ///< number of command arguments
char *nextcmd; ///< next command (NULL if none)
char *cmd; ///< the name of the command (except for :make)
char **cmdlinep; ///< pointer to pointer of allocated cmdline
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index fc66677537..2173494be9 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -41,7 +41,7 @@
#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
#include "nvim/input.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
#include "nvim/mark.h"
@@ -1218,7 +1218,7 @@ static char *skip_colon_white(const char *p, bool skipleadingwhite)
/// Set the addr type for command
///
/// @param p pointer to character after command name in cmdline
-static void set_cmd_addr_type(exarg_T *eap, char_u *p)
+void set_cmd_addr_type(exarg_T *eap, char_u *p)
{
// ea.addr_type for user commands is set by find_ucmd
if (IS_USER_CMDIDX(eap->cmdidx)) {
@@ -1239,8 +1239,48 @@ static void set_cmd_addr_type(exarg_T *eap, char_u *p)
}
}
+/// Get default range number for command based on its address type
+linenr_T get_cmd_default_range(exarg_T *eap)
+{
+ switch (eap->addr_type) {
+ case ADDR_LINES:
+ case ADDR_OTHER:
+ // Default is the cursor line number. Avoid using an invalid
+ // line number though.
+ return MIN(curwin->w_cursor.lnum, curbuf->b_ml.ml_line_count);
+ break;
+ case ADDR_WINDOWS:
+ return CURRENT_WIN_NR;
+ break;
+ case ADDR_ARGUMENTS:
+ return MIN(curwin->w_arg_idx + 1, ARGCOUNT);
+ break;
+ case ADDR_LOADED_BUFFERS:
+ case ADDR_BUFFERS:
+ return curbuf->b_fnum;
+ break;
+ case ADDR_TABS:
+ return CURRENT_TAB_NR;
+ break;
+ case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ return 1;
+ break;
+ case ADDR_QUICKFIX:
+ return (linenr_T)qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
+ return qf_get_cur_valid_idx(eap);
+ break;
+ default:
+ return 0;
+ // Will give an error later if a range is found.
+ break;
+ }
+}
+
/// Set default command range for -range=% based on the addr type of the command
-static void set_cmd_default_range(exarg_T *eap)
+void set_cmd_dflall_range(exarg_T *eap)
{
buf_T *buf;
@@ -1320,6 +1360,25 @@ static void parse_register(exarg_T *eap)
}
}
+// Change line1 and line2 of Ex command to use count
+void set_cmd_count(exarg_T *eap, long count, bool validate)
+{
+ if (eap->addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
+ eap->line2 = count;
+ if (eap->addr_count == 0) {
+ eap->addr_count = 1;
+ }
+ } else {
+ eap->line1 = eap->line2;
+ eap->line2 += count - 1;
+ eap->addr_count++;
+ // Be vi compatible: no error message for out of range.
+ if (validate && eap->line2 > curbuf->b_ml.ml_line_count) {
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ }
+ }
+}
+
static int parse_count(exarg_T *eap, char **errormsg, bool validate)
{
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
@@ -1338,25 +1397,19 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate)
}
return FAIL;
}
- if (eap->addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
- eap->line2 = n;
- if (eap->addr_count == 0) {
- eap->addr_count = 1;
- }
- } else {
- eap->line1 = eap->line2;
- eap->line2 += n - 1;
- eap->addr_count++;
- // Be vi compatible: no error message for out of range.
- if (validate && eap->line2 > curbuf->b_ml.ml_line_count) {
- eap->line2 = curbuf->b_ml.ml_line_count;
- }
- }
+ set_cmd_count(eap, n, validate);
}
return OK;
}
+/// Check if command is not implemented
+bool is_cmd_ni(cmdidx_T cmdidx)
+{
+ return !IS_USER_CMDIDX(cmdidx) && (cmdnames[cmdidx].cmd_func == ex_ni
+ || cmdnames[cmdidx].cmd_func == ex_script_ni);
+}
+
/// Parse command line and return information about the first command.
///
/// @param cmdline Command line string
@@ -1394,14 +1447,17 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
if (eap->save_msg_silent != -1) {
cmdinfo->silent = !!msg_silent;
msg_silent = eap->save_msg_silent;
+ eap->save_msg_silent = -1;
}
if (eap->did_esilent) {
cmdinfo->emsg_silent = true;
emsg_silent--;
+ eap->did_esilent = false;
}
if (eap->did_sandbox) {
cmdinfo->sandbox = true;
sandbox--;
+ eap->did_sandbox = false;
}
if (cmdmod.save_ei != NULL) {
cmdinfo->noautocmd = true;
@@ -1411,6 +1467,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
if (eap->verbose_save != -1) {
cmdinfo->verbose = p_verbose;
p_verbose = eap->verbose_save;
+ eap->verbose_save = -1;
} else {
cmdinfo->verbose = -1;
}
@@ -1424,7 +1481,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
if (*eap->cmd == '*') {
eap->cmd = skipwhite(eap->cmd + 1);
}
- p = find_command(eap, NULL);
+ p = find_ex_command(eap, NULL);
// Set command address type and parse command range
set_cmd_addr_type(eap, (char_u *)p);
@@ -1494,7 +1551,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
}
// Set default range for command if required
if ((eap->argt & EX_DFLALL) && eap->addr_count == 0) {
- set_cmd_default_range(eap);
+ set_cmd_dflall_range(eap);
}
// Parse register and count
@@ -1519,6 +1576,148 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
return true;
}
+/// Execute an Ex command using parsed command line information.
+/// Does not do any validation of the Ex command arguments.
+///
+/// @param eap Ex-command arguments
+/// @param cmdinfo Command parse information
+void execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo)
+{
+#define ERROR(msg) \
+ do { \
+ emsg(msg); \
+ goto end; \
+ } while (0)
+
+ char *errormsg = NULL;
+ cmdmod_T save_cmdmod = cmdmod;
+ cmdmod = cmdinfo->cmdmod;
+
+ // Apply command modifiers
+ if (cmdinfo->silent) {
+ eap->save_msg_silent = msg_silent;
+ msg_silent++;
+ }
+ if (cmdinfo->emsg_silent) {
+ eap->did_esilent = true;
+ emsg_silent++;
+ }
+ if (cmdinfo->sandbox) {
+ eap->did_sandbox = true;
+ sandbox++;
+ }
+ if (cmdinfo->noautocmd) {
+ cmdmod.save_ei = (char *)vim_strsave(p_ei);
+ set_string_option_direct("ei", -1, (char_u *)"all", OPT_FREE, SID_NONE);
+ }
+ if (cmdinfo->verbose != -1) {
+ eap->verbose_save = p_verbose;
+ p_verbose = cmdinfo->verbose;
+ }
+
+ if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY)
+ // allow :put in terminals
+ && !(curbuf->terminal && eap->cmdidx == CMD_put)) {
+ ERROR(_(e_modifiable));
+ }
+ if (text_locked() && !(eap->argt & EX_CMDWIN)
+ && !IS_USER_CMDIDX(eap->cmdidx)) {
+ ERROR(_(get_text_locked_msg()));
+ }
+ // Disallow editing another buffer when "curbuf->b_ro_locked" is set.
+ // Do allow ":checktime" (it is postponed).
+ // Do allow ":edit" (check for an argument later).
+ // Do allow ":file" with no arguments
+ if (!(eap->argt & EX_CMDWIN)
+ && eap->cmdidx != CMD_checktime
+ && eap->cmdidx != CMD_edit
+ && !(eap->cmdidx == CMD_file && *eap->arg == NUL)
+ && !IS_USER_CMDIDX(eap->cmdidx)
+ && curbuf_locked()) {
+ ERROR(_(e_cannot_edit_other_buf));
+ }
+
+ if (((eap->argt & EX_WHOLEFOLD) || eap->addr_count >= 2) && !global_busy
+ && eap->addr_type == ADDR_LINES) {
+ // Put the first line at the start of a closed fold, put the last line
+ // at the end of a closed fold.
+ (void)hasFolding(eap->line1, &eap->line1, NULL);
+ (void)hasFolding(eap->line2, NULL, &eap->line2);
+ }
+
+ // If filename expansion is enabled, expand filenames
+ if (cmdinfo->magic.file) {
+ if (expand_filename(eap, (char_u **)eap->cmdlinep, &errormsg) == FAIL) {
+ ERROR(errormsg);
+ }
+ }
+
+ // Accept buffer name. Cannot be used at the same time with a buffer
+ // number. Don't do this for a user command.
+ if ((eap->argt & EX_BUFNAME) && *eap->arg != NUL && eap->addr_count == 0
+ && !IS_USER_CMDIDX(eap->cmdidx)) {
+ if (eap->args == NULL) {
+ // If argument positions are not specified, search the argument for the buffer name.
+ // :bdelete, :bwipeout and :bunload take several arguments, separated by spaces:
+ // find next space (skipping over escaped characters).
+ // The others take one argument: ignore trailing spaces.
+ char *p;
+
+ if (eap->cmdidx == CMD_bdelete || eap->cmdidx == CMD_bwipeout
+ || eap->cmdidx == CMD_bunload) {
+ p = (char *)skiptowhite_esc((char_u *)eap->arg);
+ } else {
+ p = eap->arg + STRLEN(eap->arg);
+ while (p > eap->arg && ascii_iswhite(p[-1])) {
+ p--;
+ }
+ }
+ eap->line2 = buflist_findpat((char_u *)eap->arg, (char_u *)p, (eap->argt & EX_BUFUNL) != 0,
+ false, false);
+ eap->addr_count = 1;
+ eap->arg = skipwhite(p);
+ } else {
+ // If argument positions are specified, just use the first argument
+ eap->line2 = buflist_findpat((char_u *)eap->args[0],
+ (char_u *)(eap->args[0] + eap->arglens[0]),
+ (eap->argt & EX_BUFUNL) != 0, false, false);
+ eap->addr_count = 1;
+ // Shift each argument by 1
+ if (eap->args != NULL) {
+ for (size_t i = 0; i < eap->argc - 1; i++) {
+ eap->args[i] = eap->args[i + 1];
+ }
+ // Make the last argument point to the NUL terminator at the end of string
+ eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1];
+ eap->argc -= 1;
+ }
+ eap->arg = eap->args[0];
+ }
+ if (eap->line2 < 0) { // failed
+ goto end;
+ }
+ }
+
+ // Execute the command
+ if (IS_USER_CMDIDX(eap->cmdidx)) {
+ // Execute a user-defined command.
+ do_ucmd(eap);
+ } else {
+ // Call the function to execute the command.
+ eap->errmsg = NULL;
+ (cmdnames[eap->cmdidx].cmd_func)(eap);
+ if (eap->errmsg != NULL) {
+ ERROR(_(eap->errmsg));
+ }
+ }
+end:
+ // Undo command modifiers
+ undo_cmdmod(eap, msg_scroll);
+ cmdmod = save_cmdmod;
+
+#undef ERROR
+}
+
/// Execute one Ex command.
///
/// If 'sourcing' is TRUE, the command will be included in the error message.
@@ -1606,7 +1805,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
if (*ea.cmd == '*') {
ea.cmd = skipwhite(ea.cmd + 1);
}
- p = find_command(&ea, NULL);
+ p = find_ex_command(&ea, NULL);
// Count this line for profiling if skip is TRUE.
if (do_profiling == PROF_YES
@@ -1732,7 +1931,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
xfree(p);
// If the autocommands did something and didn't cause an error, try
// finding the command again.
- p = (ret && !aborting()) ? find_command(&ea, NULL) : ea.cmd;
+ p = (ret && !aborting()) ? find_ex_command(&ea, NULL) : ea.cmd;
}
if (p == NULL) {
@@ -1759,10 +1958,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
}
// set when Not Implemented
- const int ni = !IS_USER_CMDIDX(ea.cmdidx)
- && (cmdnames[ea.cmdidx].cmd_func == ex_ni
- || cmdnames[ea.cmdidx].cmd_func == ex_script_ni);
-
+ const int ni = is_cmd_ni(ea.cmdidx);
// Forced commands.
if (*p == '!' && ea.cmdidx != CMD_substitute
@@ -1976,7 +2172,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
}
if ((ea.argt & EX_DFLALL) && ea.addr_count == 0) {
- set_cmd_default_range(&ea);
+ set_cmd_dflall_range(&ea);
}
// Parse register and count
@@ -2544,6 +2740,7 @@ static void undo_cmdmod(const exarg_T *eap, int save_msg_scroll)
}
+
/// Parse the address range, if any, in "eap".
/// May set the last search pattern, unless "silent" is true.
///
@@ -2557,47 +2754,7 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
// Repeat for all ',' or ';' separated addresses.
for (;;) {
eap->line1 = eap->line2;
- switch (eap->addr_type) {
- case ADDR_LINES:
- case ADDR_OTHER:
- // Default is the cursor line number. Avoid using an invalid
- // line number though.
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- eap->line2 = curbuf->b_ml.ml_line_count;
- } else {
- eap->line2 = curwin->w_cursor.lnum;
- }
- break;
- case ADDR_WINDOWS:
- eap->line2 = CURRENT_WIN_NR;
- break;
- case ADDR_ARGUMENTS:
- eap->line2 = curwin->w_arg_idx + 1;
- if (eap->line2 > ARGCOUNT) {
- eap->line2 = ARGCOUNT;
- }
- break;
- case ADDR_LOADED_BUFFERS:
- case ADDR_BUFFERS:
- eap->line2 = curbuf->b_fnum;
- break;
- case ADDR_TABS:
- eap->line2 = CURRENT_TAB_NR;
- break;
- case ADDR_TABS_RELATIVE:
- case ADDR_UNSIGNED:
- eap->line2 = 1;
- break;
- case ADDR_QUICKFIX:
- eap->line2 = (linenr_T)qf_get_cur_idx(eap);
- break;
- case ADDR_QUICKFIX_VALID:
- eap->line2 = qf_get_cur_valid_idx(eap);
- break;
- case ADDR_NONE:
- // Will give an error later if a range is found.
- break;
- }
+ eap->line2 = get_cmd_default_range(eap);
eap->cmd = skipwhite(eap->cmd);
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
eap->addr_count == 0, address_count++);
@@ -2772,7 +2929,7 @@ static void append_command(char *cmd)
/// "full" is set to TRUE if the whole command name matched.
///
/// @return NULL for an ambiguous user command.
-static char *find_command(exarg_T *eap, int *full)
+char *find_ex_command(exarg_T *eap, int *full)
FUNC_ATTR_NONNULL_ARG(1)
{
int len;
@@ -2859,7 +3016,7 @@ static char *find_command(exarg_T *eap, int *full)
for (; (int)eap->cmdidx < CMD_SIZE;
eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1)) {
- if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd,
+ if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, eap->cmd,
(size_t)len) == 0) {
if (full != NULL
&& cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL) {
@@ -3076,7 +3233,7 @@ int cmd_exists(const char *const name)
ea.cmd = (char *)((*name == '2' || *name == '3') ? name + 1 : name);
ea.cmdidx = (cmdidx_T)0;
int full = false;
- p = find_command(&ea, &full);
+ p = find_ex_command(&ea, &full);
if (p == NULL) {
return 3;
}
@@ -3108,7 +3265,7 @@ void f_fullcommand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
ea.cmdidx = (cmdidx_T)0;
- char *p = find_command(&ea, NULL);
+ char *p = find_ex_command(&ea, NULL);
if (p == NULL || ea.cmdidx == CMD_SIZE) {
return;
}
@@ -3431,7 +3588,7 @@ const char *set_one_cmd_context(expand_T *xp, const char *buff)
xp->xp_shell = TRUE;
#endif
// When still after the command name expand executables.
- if ((char_u *)xp->xp_pattern == (char_u *)skipwhite(arg)) {
+ if (xp->xp_pattern == skipwhite(arg)) {
xp->xp_context = EXPAND_SHELLCMD;
}
}
@@ -4416,7 +4573,7 @@ static void ex_script_ni(exarg_T *eap)
/// Check range in Ex command for validity.
///
/// @return NULL when valid, error message when invalid.
-static char *invalid_range(exarg_T *eap)
+char *invalid_range(exarg_T *eap)
{
buf_T *buf;
if (eap->line1 < 0 || eap->line2 < 0 || eap->line1 > eap->line2) {
@@ -4535,7 +4692,7 @@ static char *skip_grep_pat(exarg_T *eap)
/// For the ":make" and ":grep" commands insert the 'makeprg'/'grepprg' option
/// in the command line, so that things like % get expanded.
-static char *replace_makeprg(exarg_T *eap, char *p, char **cmdlinep)
+char *replace_makeprg(exarg_T *eap, char *p, char **cmdlinep)
{
char *new_cmdline;
char *program;
@@ -4773,7 +4930,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp)
return OK;
}
-/// Replace part of the command line, keeping eap->cmd, eap->arg and
+/// Replace part of the command line, keeping eap->cmd, eap->arg, eap->args and
/// eap->nextcmd correct.
/// "src" points to the part that is to be replaced, of length "srclen".
/// "repl" is the replacement string.
@@ -4792,6 +4949,7 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch
i += STRLEN(eap->nextcmd); // add space for next command
}
char *new_cmdline = xmalloc(i);
+ size_t offset = (size_t)(src - *cmdlinep);
/*
* Copy the stuff before the expanded part.
@@ -4799,7 +4957,7 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch
* Copy what came after the expanded part.
* Copy the next commands, if there are any.
*/
- i = (size_t)(src - *cmdlinep); // length of part before match
+ i = offset; // length of part before match
memmove(new_cmdline, *cmdlinep, i);
memmove(new_cmdline + i, repl, len);
@@ -4814,6 +4972,19 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch
}
eap->cmd = new_cmdline + (eap->cmd - *cmdlinep);
eap->arg = new_cmdline + (eap->arg - *cmdlinep);
+
+ for (size_t j = 0; j < eap->argc; j++) {
+ if (offset >= (size_t)(eap->args[j] - *cmdlinep)) {
+ // If replaced text is after or in the same position as the argument,
+ // the argument's position relative to the beginning of the cmdline stays the same.
+ eap->args[j] = new_cmdline + (eap->args[j] - *cmdlinep);
+ } else {
+ // Otherwise, argument gets shifted alongside the replaced text.
+ // The amount of the shift is equal to the difference of the old and new string length.
+ eap->args[j] = new_cmdline + (eap->args[j] - *cmdlinep) + (len - srclen);
+ }
+ }
+
if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command) {
eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep);
}
@@ -5077,7 +5248,9 @@ static int get_tabpage_arg(exarg_T *eap)
tab_number = 0;
} else {
tab_number = (int)eap->line2;
- if (!unaccept_arg0 && *skipwhite(*eap->cmdlinep) == '-') {
+ char *cmdp = eap->cmd;
+ while (--cmdp > *eap->cmdlinep && (*cmdp == ' ' || ascii_isdigit(*cmdp))) {}
+ if (!unaccept_arg0 && *cmdp == '-') {
tab_number--;
if (tab_number < unaccept_arg0) {
eap->errmsg = e_invarg;
@@ -6002,7 +6175,7 @@ bool uc_split_args_iter(const char *arg, size_t arglen, size_t *end, char *buf,
}
/// split and quote args for <f-args>
-static char *uc_split_args(char *arg, size_t *lenp)
+static char *uc_split_args(char *arg, char **args, size_t *arglens, size_t argc, size_t *lenp)
{
char *buf;
char *p;
@@ -6010,61 +6183,107 @@ static char *uc_split_args(char *arg, size_t *lenp)
int len;
// Precalculate length
- p = arg;
len = 2; // Initial and final quotes
+ if (args == NULL) {
+ p = arg;
- while (*p) {
- if (p[0] == '\\' && p[1] == '\\') {
- len += 2;
- p += 2;
- } else if (p[0] == '\\' && ascii_iswhite(p[1])) {
- len += 1;
- p += 2;
- } else if (*p == '\\' || *p == '"') {
- len += 2;
- p += 1;
- } else if (ascii_iswhite(*p)) {
- p = skipwhite(p);
- if (*p == NUL) {
- break;
+ while (*p) {
+ if (p[0] == '\\' && p[1] == '\\') {
+ len += 2;
+ p += 2;
+ } else if (p[0] == '\\' && ascii_iswhite(p[1])) {
+ len += 1;
+ p += 2;
+ } else if (*p == '\\' || *p == '"') {
+ len += 2;
+ p += 1;
+ } else if (ascii_iswhite(*p)) {
+ p = skipwhite(p);
+ if (*p == NUL) {
+ break;
+ }
+ len += 3; // ","
+ } else {
+ const int charlen = utfc_ptr2len(p);
+
+ len += charlen;
+ p += charlen;
}
- len += 3; // ","
- } else {
- const int charlen = utfc_ptr2len(p);
+ }
+ } else {
+ for (size_t i = 0; i < argc; i++) {
+ p = args[i];
+ const char *arg_end = args[i] + arglens[i];
+
+ while (p < arg_end) {
+ if (*p == '\\' || *p == '"') {
+ len += 2;
+ p += 1;
+ } else {
+ const int charlen = utfc_ptr2len(p);
- len += charlen;
- p += charlen;
+ len += charlen;
+ p += charlen;
+ }
+ }
+
+ if (i != argc - 1) {
+ len += 3; // ","
+ }
}
}
buf = xmalloc((size_t)len + 1);
- p = arg;
q = buf;
*q++ = '"';
- while (*p) {
- if (p[0] == '\\' && p[1] == '\\') {
- *q++ = '\\';
- *q++ = '\\';
- p += 2;
- } else if (p[0] == '\\' && ascii_iswhite(p[1])) {
- *q++ = p[1];
- p += 2;
- } else if (*p == '\\' || *p == '"') {
- *q++ = '\\';
- *q++ = *p++;
- } else if (ascii_iswhite(*p)) {
- p = skipwhite(p);
- if (*p == NUL) {
- break;
+
+ if (args == NULL) {
+ p = arg;
+ while (*p) {
+ if (p[0] == '\\' && p[1] == '\\') {
+ *q++ = '\\';
+ *q++ = '\\';
+ p += 2;
+ } else if (p[0] == '\\' && ascii_iswhite(p[1])) {
+ *q++ = p[1];
+ p += 2;
+ } else if (*p == '\\' || *p == '"') {
+ *q++ = '\\';
+ *q++ = *p++;
+ } else if (ascii_iswhite(*p)) {
+ p = skipwhite(p);
+ if (*p == NUL) {
+ break;
+ }
+ *q++ = '"';
+ *q++ = ',';
+ *q++ = '"';
+ } else {
+ mb_copy_char((const char_u **)&p, (char_u **)&q);
+ }
+ }
+ } else {
+ for (size_t i = 0; i < argc; i++) {
+ p = args[i];
+ const char *arg_end = args[i] + arglens[i];
+
+ while (p < arg_end) {
+ if (*p == '\\' || *p == '"') {
+ *q++ = '\\';
+ *q++ = *p++;
+ } else {
+ mb_copy_char((const char_u **)&p, (char_u **)&q);
+ }
+ }
+ if (i != argc - 1) {
+ *q++ = '"';
+ *q++ = ',';
+ *q++ = '"';
}
- *q++ = '"';
- *q++ = ',';
- *q++ = '"';
- } else {
- mb_copy_char((const char_u **)&p, (char_u **)&q);
}
}
+
*q++ = '"';
*q = 0;
@@ -6201,7 +6420,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar
case 2: // Quote and split (<f-args>)
// This is hard, so only do it once, and cache the result
if (*split_buf == NULL) {
- *split_buf = uc_split_args(eap->arg, split_len);
+ *split_buf = uc_split_args(eap->arg, eap->args, eap->arglens, eap->argc, split_len);
}
result = *split_len;
@@ -9887,7 +10106,7 @@ bool cmd_can_preview(char *cmd)
if (*ea.cmd == '*') {
ea.cmd = skipwhite(ea.cmd + 1);
}
- char *end = find_command(&ea, NULL);
+ char *end = find_ex_command(&ea, NULL);
switch (ea.cmdidx) {
case CMD_substitute:
@@ -10278,3 +10497,9 @@ void verify_command(char *cmd)
msg("` `.:.`.,:iii;;;;;;;;iii;;;:` `.`` "
" `nW");
}
+
+/// Get argt of command with id
+uint32_t get_cmd_argt(cmdidx_T cmdidx)
+{
+ return cmdnames[(int)cmdidx].cmd_argt;
+}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index d4665ac031..a7e843704f 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -33,12 +33,13 @@
#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
+#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
#include "nvim/indent.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/lib/kvec.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
@@ -2522,7 +2523,7 @@ char *get_text_locked_msg(void)
bool curbuf_locked(void)
{
if (curbuf->b_ro_locked > 0) {
- emsg(_("E788: Not allowed to edit another buffer now"));
+ emsg(_(e_cannot_edit_other_buf));
return true;
}
return allbuf_locked();
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 045f778e4c..4554af5356 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -27,7 +27,7 @@
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index 945fa5099f..f094a04c07 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -1,9 +1,12 @@
local mpack = require('mpack')
local nvimsrcdir = arg[1]
-local autodir = arg[2]
-local metadata_file = arg[3]
-local funcs_file = arg[4]
+local shared_file = arg[2]
+local autodir = arg[3]
+local metadata_file = arg[4]
+local funcs_file = arg[5]
+
+_G.vim = loadfile(shared_file)()
if nvimsrcdir == '--help' then
print([[
@@ -20,7 +23,9 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path
local funcsfname = autodir .. '/funcs.generated.h'
-local gperfpipe = io.open(funcsfname .. '.gperf', 'wb')
+local hashy = require'generators.hashy'
+
+local hashpipe = io.open(funcsfname, 'wb')
local funcs = require('eval').funcs
local metadata = mpack.unpack(io.open(metadata_file, 'rb'):read("*all"))
@@ -38,21 +43,15 @@ local funcsdata = io.open(funcs_file, 'w')
funcsdata:write(mpack.pack(funcs))
funcsdata:close()
-gperfpipe:write([[
-%language=ANSI-C
-%global-table
-%readonly-tables
-%define initializer-suffix ,0,0,BASE_NONE,NULL,NULL
-%define word-array-name functions
-%define hash-function-name hash_internal_func_gperf
-%define lookup-function-name find_internal_func_gperf
-%omit-struct-type
-%struct-type
-VimLFuncDef;
-%%
-]])
-for name, def in pairs(funcs) do
+local names = vim.tbl_keys(funcs)
+
+local neworder, hashfun = hashy.hashy_hash("find_internal_func", names, function (idx)
+ return "functions["..idx.."].name"
+end)
+hashpipe:write("static const EvalFuncDef functions[] = {\n")
+for _, name in ipairs(neworder) do
+ local def = funcs[name]
local args = def.args or 0
if type(args) == 'number' then
args = {args, args}
@@ -62,7 +61,10 @@ for name, def in pairs(funcs) do
local base = def.base or "BASE_NONE"
local func = def.func or ('f_' .. name)
local data = def.data or "NULL"
- gperfpipe:write(('%s, %s, %s, %s, &%s, (FunPtr)%s\n')
+ hashpipe:write((' { "%s", %s, %s, %s, &%s, (FunPtr)%s },\n')
:format(name, args[1], args[2], base, func, data))
end
-gperfpipe:close()
+hashpipe:write(' { NULL, 0, 0, BASE_NONE, NULL, NULL },\n')
+hashpipe:write("};\n\n")
+hashpipe:write(hashfun)
+hashpipe:close()
diff --git a/src/nvim/generators/hashy.lua b/src/nvim/generators/hashy.lua
index fac24c810a..b10bafb9f9 100644
--- a/src/nvim/generators/hashy.lua
+++ b/src/nvim/generators/hashy.lua
@@ -77,7 +77,7 @@ function M.switcher(put, tab, maxlen, worst_buck_size)
put "break;\n"
end
put " default: break;\n"
- put " }\n "
+ put " }\n "
else
local startidx = #neworder
table.insert(neworder, posbuck[keys[1]][1])
@@ -85,7 +85,7 @@ function M.switcher(put, tab, maxlen, worst_buck_size)
put("low = "..startidx.."; ")
if bucky then put("high = "..endidx.."; ") end
end
- put " break;\n"
+ put "break;\n"
end
end
put " default: break;\n"
@@ -105,17 +105,23 @@ function M.hashy_hash(name, strings, access)
end
local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size)
if worst_buck_size > 1 then
- error [[ not implemented yet ]] -- TODO(bfredl)
+ put ([[
+ for (int i = low; i < high; i++) {
+ if (!memcmp(str, ]]..access("i")..[[, len)) {
+ return i;
+ }
+ }
+ return -1;
+]])
else
- put [[
- if (low < 0) {
+ put ([[
+ if (low < 0 || memcmp(str, ]]..access("low")..[[, len)) {
return -1;
}
- ]]
- put("if(memcmp(str, "..access("low")..", len)) {\n return -1;\n }\n")
- put " return low;\n"
- put "}\n\n"
+ return low;
+]])
end
+ put "}\n\n"
return neworder, table.concat(stats)
end
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index c0a5a14f7b..df45de2abf 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -31,7 +31,7 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/input.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ef8ff11bf8..1a1f9bd866 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -997,6 +997,7 @@ EXTERN char e_listarg[] INIT(= N_("E686: Argument of %s must be a List"));
EXTERN char e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String"));
+EXTERN char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now"));
EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s"));
EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
diff --git a/src/nvim/keymap.c b/src/nvim/keycodes.c
index b184b42354..676ddcf8d4 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keycodes.c
@@ -9,7 +9,7 @@
#include "nvim/charset.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -17,12 +17,10 @@
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "keymap.c.generated.h"
+# include "keycodes.c.generated.h"
#endif
-/*
- * Some useful tables.
- */
+// Some useful tables.
static const struct modmasktable {
uint16_t mod_mask; ///< Bit-mask for particular key modifier.
@@ -43,10 +41,9 @@ static const struct modmasktable {
// NOTE: when adding an entry, update MAX_KEY_NAME_LEN!
};
-/*
- * Shifted key terminal codes and their unshifted equivalent.
- * Don't add mouse codes here, they are handled separately!
- */
+// Shifted key terminal codes and their unshifted equivalent.
+// Don't add mouse codes here, they are handled separately!
+
#define MOD_KEYS_ENTRY_SIZE 5
static char_u modifier_keys_table[] =
@@ -461,10 +458,7 @@ int handle_x_keys(const int key)
return key;
}
-/*
- * Return a string which contains the name of the given key when the given
- * modifiers are down.
- */
+/// @return a string which contains the name of the given key when the given modifiers are down.
char_u *get_special_key_name(int c, int modifiers)
{
static char_u string[MAX_KEY_NAME_LEN + 1];
@@ -481,10 +475,8 @@ char_u *get_special_key_name(int c, int modifiers)
c = KEY2TERMCAP1(c);
}
- /*
- * Translate shifted special keys into unshifted keys and set modifier.
- * Same for CTRL and ALT modifiers.
- */
+ // Translate shifted special keys into unshifted keys and set modifier.
+ // Same for CTRL and ALT modifiers.
if (IS_SPECIAL(c)) {
for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE) {
if (KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
@@ -500,10 +492,8 @@ char_u *get_special_key_name(int c, int modifiers)
// try to find the key in the special key table
table_idx = find_special_key_in_table(c);
- /*
- * When not a known special key, and not a printable character, try to
- * extract modifiers.
- */
+ // When not a known special key, and not a printable character, try to
+ // extract modifiers.
if (c > 0
&& utf_char2len(c) == 1) {
if (table_idx < 0
@@ -798,10 +788,8 @@ static int extract_modifiers(int key, int *modp, const bool simplify, bool *cons
return key;
}
-/*
- * Try to find key "c" in the special key table.
- * Return the index when found, -1 when not found.
- */
+/// Try to find key "c" in the special key table.
+/// @return the index when found, -1 when not found.
int find_special_key_in_table(int c)
{
int i;
@@ -844,10 +832,8 @@ int get_special_key_code(const char_u *name)
return 0;
}
-/*
- * Look up the given mouse code to return the relevant information in the other
- * arguments. Return which button is down or was released.
- */
+/// Look up the given mouse code to return the relevant information in the other arguments.
+/// @return which button is down or was released.
int get_mouse_button(int code, bool *is_click, bool *is_drag)
{
int i;
@@ -1009,7 +995,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
} else {
result[dlen++] = *src;
}
- ++src;
+ src++;
}
}
result[dlen] = NUL;
diff --git a/src/nvim/keymap.h b/src/nvim/keycodes.h
index 9febd472f9..631a9f68d3 100644
--- a/src/nvim/keymap.h
+++ b/src/nvim/keycodes.h
@@ -1,13 +1,11 @@
-#ifndef NVIM_KEYMAP_H
-#define NVIM_KEYMAP_H
+#ifndef NVIM_KEYCODES_H
+#define NVIM_KEYCODES_H
#include "nvim/strings.h"
-/*
- * Keycode definitions for special keys.
- *
- * Any special key code sequences are replaced by these codes.
- */
+// Keycode definitions for special keys.
+//
+// Any special key code sequences are replaced by these codes.
//
// For MS-DOS some keys produce codes larger than 0xff. They are split into two
@@ -15,66 +13,49 @@
//
#define K_NUL (0xce) // for MS-DOS: special key follows
-/*
- * K_SPECIAL is the first byte of a special key code and is always followed by
- * two bytes.
- * The second byte can have any value. ASCII is used for normal termcap
- * entries, 0x80 and higher for special keys, see below.
- * The third byte is guaranteed to be between 0x02 and 0x7f.
- */
-
+/// K_SPECIAL is the first byte of a special key code and is always followed by
+/// two bytes.
+/// The second byte can have any value. ASCII is used for normal termcap
+/// entries, 0x80 and higher for special keys, see below.
+/// The third byte is guaranteed to be between 0x02 and 0x7f.
#define K_SPECIAL (0x80)
-/*
- * Positive characters are "normal" characters.
- * Negative characters are special key codes. Only characters below -0x200
- * are used to so that the absolute value can't be mistaken for a single-byte
- * character.
- */
+/// Positive characters are "normal" characters.
+/// Negative characters are special key codes. Only characters below -0x200
+/// are used to so that the absolute value can't be mistaken for a single-byte
+/// character.
#define IS_SPECIAL(c) ((c) < 0)
-/*
- * Characters 0x0100 - 0x01ff have a special meaning for abbreviations.
- * Multi-byte characters also have ABBR_OFF added, thus are above 0x0200.
- */
+/// Characters 0x0100 - 0x01ff have a special meaning for abbreviations.
+/// Multi-byte characters also have ABBR_OFF added, thus are above 0x0200.
#define ABBR_OFF 0x100
-/*
- * NUL cannot be in the input string, therefore it is replaced by
- * K_SPECIAL KS_ZERO KE_FILLER
- */
+/// NUL cannot be in the input string, therefore it is replaced by
+/// K_SPECIAL KS_ZERO KE_FILLER
#define KS_ZERO 255
-/*
- * K_SPECIAL cannot be in the input string, therefore it is replaced by
- * K_SPECIAL KS_SPECIAL KE_FILLER
- */
+/// K_SPECIAL cannot be in the input string, therefore it is replaced by
+/// K_SPECIAL KS_SPECIAL KE_FILLER
#define KS_SPECIAL 254
-/*
- * KS_EXTRA is used for keys that have no termcap name
- * K_SPECIAL KS_EXTRA KE_xxx
- */
+/// KS_EXTRA is used for keys that have no termcap name
+/// K_SPECIAL KS_EXTRA KE_xxx
#define KS_EXTRA 253
-/*
- * KS_MODIFIER is used when a modifier is given for a (special) key
- * K_SPECIAL KS_MODIFIER bitmask
- */
+/// KS_MODIFIER is used when a modifier is given for a (special) key
+/// K_SPECIAL KS_MODIFIER bitmask
#define KS_MODIFIER 252
-/*
- * These are used for the GUI
- * K_SPECIAL KS_xxx KE_FILLER
- */
+// These are used for the GUI
+// K_SPECIAL KS_xxx KE_FILLER
+
#define KS_MOUSE 251
#define KS_MENU 250
#define KS_VER_SCROLLBAR 249
#define KS_HOR_SCROLLBAR 248
-/*
- * Used for switching Select mode back on after a mapping or menu.
- */
+// Used for switching Select mode back on after a mapping or menu.
+
#define KS_SELECT 245
#define K_SELECT_STRING (char_u *)"\200\365X"
@@ -87,30 +68,24 @@
// Used for menu in a tab pages line.
#define KS_TABMENU 239
-/*
- * Filler used after KS_SPECIAL and others
- */
+/// Filler used after KS_SPECIAL and others
#define KE_FILLER ('X')
-/*
- * translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back
- */
+// translation of three byte code "K_SPECIAL a b" into int "K_xxx" and back
+
#define TERMCAP2KEY(a, b) (-((a) + ((int)(b) << 8)))
#define KEY2TERMCAP0(x) ((-(x)) & 0xff)
#define KEY2TERMCAP1(x) (((unsigned)(-(x)) >> 8) & 0xff)
-/*
- * get second or third byte when translating special key code into three bytes
- */
+// get second or third byte when translating special key code into three bytes
+
#define K_SECOND(c) ((c) == K_SPECIAL ? KS_SPECIAL : (c) == \
NUL ? KS_ZERO : KEY2TERMCAP0(c))
#define K_THIRD(c) (((c) == K_SPECIAL || (c) == \
NUL) ? KE_FILLER : KEY2TERMCAP1(c))
-/*
- * get single int code from second byte after K_SPECIAL
- */
+/// get single int code from second byte after K_SPECIAL
#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \
KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b))
@@ -247,9 +222,8 @@ enum key_extra {
KE_COMMAND = 104, // <Cmd> special key
};
-/*
- * the three byte codes are replaced with the following int when using vgetc()
- */
+// the three byte codes are replaced with the following int when using vgetc()
+
#define K_ZERO TERMCAP2KEY(KS_ZERO, KE_FILLER)
#define K_UP TERMCAP2KEY('k', 'u')
@@ -430,10 +404,9 @@ enum key_extra {
#define K_TABLINE TERMCAP2KEY(KS_TABLINE, KE_FILLER)
#define K_TABMENU TERMCAP2KEY(KS_TABMENU, KE_FILLER)
-/*
- * Symbols for pseudo keys which are translated from the real key symbols
- * above.
- */
+// Symbols for pseudo keys which are translated from the real key symbols
+// above.
+
#define K_LEFTMOUSE TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE)
#define K_LEFTMOUSE_NM TERMCAP2KEY(KS_EXTRA, KE_LEFTMOUSE_NM)
#define K_LEFTDRAG TERMCAP2KEY(KS_EXTRA, KE_LEFTDRAG)
@@ -486,11 +459,8 @@ enum key_extra {
#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK| \
MOD_MASK_4CLICK)
-/*
- * The length of the longest special key name, including modifiers.
- * Current longest is <M-C-S-T-D-A-4-ScrollWheelRight> (length includes '<' and
- * '>').
- */
+/// The length of the longest special key name, including modifiers.
+/// Current longest is <M-C-S-T-D-A-4-ScrollWheelRight> (length includes '<' and '>').
#define MAX_KEY_NAME_LEN 32
// Maximum length of a special key event as tokens. This includes modifiers.
@@ -524,6 +494,6 @@ enum {
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "keymap.h.generated.h"
+# include "keycodes.h.generated.h"
#endif
-#endif // NVIM_KEYMAP_H
+#endif // NVIM_KEYCODES_H
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 7d50ecf69e..815d53b570 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -51,7 +51,7 @@ static bool log_try_create(char *fname)
/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty.
///
-/// Tries $NVIM_LOG_FILE, or falls back to $XDG_CACHE_HOME/nvim/log. Path to log
+/// Tries $NVIM_LOG_FILE, or falls back to $XDG_STATE_HOME/nvim/log. Path to log
/// file is cached, so only the first call has effect, unless first call was not
/// successful. Failed initialization indicates either a bug in expand_env()
/// or both $NVIM_LOG_FILE and $HOME environment variables are undefined.
@@ -69,16 +69,16 @@ static bool log_path_init(void)
|| log_file_path[0] == '\0'
|| os_isdir((char_u *)log_file_path)
|| !log_try_create(log_file_path)) {
- // Make kXDGCacheHome if it does not exist.
- char *cachehome = get_xdg_home(kXDGCacheHome);
+ // Make kXDGStateHome if it does not exist.
+ char *loghome = get_xdg_home(kXDGStateHome);
char *failed_dir = NULL;
bool log_dir_failure = false;
- if (!os_isdir((char_u *)cachehome)) {
- log_dir_failure = (os_mkdir_recurse(cachehome, 0700, &failed_dir) != 0);
+ if (!os_isdir((char_u *)loghome)) {
+ log_dir_failure = (os_mkdir_recurse(loghome, 0700, &failed_dir) != 0);
}
- XFREE_CLEAR(cachehome);
+ XFREE_CLEAR(loghome);
// Invalid $NVIM_LOG_FILE or failed to expand; fall back to default.
- char *defaultpath = stdpaths_user_cache_subpath("log");
+ char *defaultpath = stdpaths_user_state_subpath("log", 0, true);
size_t len = xstrlcpy(log_file_path, defaultpath, size);
xfree(defaultpath);
// Fall back to .nvimlog
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 29ed40af03..9758cee0a5 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1863,8 +1863,8 @@ void nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap)
if (cmd->uc_argt & EX_NOSPC) {
// Commands where nargs = 1 or "?" fargs is the same as args
lua_rawseti(lstate, -2, 1);
- } else {
- // Commands with more than one possible argument we split
+ } else if (eap->args == NULL) {
+ // For commands with more than one possible argument, split if argument list isn't available.
lua_pop(lstate, 1); // Pop the reference of opts.args
size_t length = STRLEN(eap->arg);
size_t end = 0;
@@ -1881,6 +1881,13 @@ void nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap)
}
}
xfree(buf);
+ } else {
+ // If argument list is available, just use it.
+ lua_pop(lstate, 1);
+ for (size_t i = 0; i < eap->argc; i++) {
+ lua_pushlstring(lstate, eap->args[i], eap->arglens[i]);
+ lua_rawseti(lstate, -2, (int)i + 1);
+ }
}
lua_setfield(lstate, -2, "fargs");
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 4ea9329a71..c7408c6260 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1992,6 +1992,31 @@ theend:
convert_setup(&vimconv, NULL, NULL);
}
+/// @return true if string "s" is a valid utf-8 string.
+/// When "end" is NULL stop at the first NUL.
+/// When "end" is positive stop there.
+bool utf_valid_string(const char_u *s, const char_u *end)
+{
+ const char_u *p = s;
+
+ while (end == NULL ? *p != NUL : p < end) {
+ int l = utf8len_tab_zero[*p];
+ if (l == 0) {
+ return false; // invalid lead byte
+ }
+ if (end != NULL && p + l > end) {
+ return false; // incomplete byte sequence
+ }
+ p++;
+ while (--l > 0) {
+ if ((*p++ & 0xc0) != 0x80) {
+ return false; // invalid trail byte
+ }
+ }
+ }
+ return true;
+}
+
/*
* If the cursor moves on an trail byte, set the cursor on the lead byte.
* Thus it moves left if necessary.
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 14084df4d4..7b254f1b62 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -18,7 +18,7 @@
#include "nvim/ex_docmd.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 29473ac2b6..52eafe6e26 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -24,7 +24,7 @@
#include "nvim/getchar.h"
#include "nvim/highlight.h"
#include "nvim/input.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c54cc3ed09..a983ff4436 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -33,7 +33,7 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/mark.h"
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 66d9d2843c..b1e9226937 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -49,7 +49,7 @@
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/indent_c.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/macros.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
@@ -491,17 +491,17 @@ void set_init_1(bool clean_arg)
#endif
false);
- char *backupdir = stdpaths_user_data_subpath("backup", 2, true);
+ char *backupdir = stdpaths_user_state_subpath("backup", 2, true);
const size_t backupdir_len = strlen(backupdir);
backupdir = xrealloc(backupdir, backupdir_len + 3);
memmove(backupdir + 2, backupdir, backupdir_len + 1);
memmove(backupdir, ".,", 2);
set_string_default("backupdir", backupdir, true);
- set_string_default("viewdir", stdpaths_user_data_subpath("view", 2, true),
+ set_string_default("viewdir", stdpaths_user_state_subpath("view", 2, true),
true);
- set_string_default("directory", stdpaths_user_data_subpath("swap", 2, true),
+ set_string_default("directory", stdpaths_user_state_subpath("swap", 2, true),
true);
- set_string_default("undodir", stdpaths_user_data_subpath("undo", 2, true),
+ set_string_default("undodir", stdpaths_user_state_subpath("undo", 2, true),
true);
// Set default for &runtimepath. All necessary expansions are performed in
// this function.
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 64e5a7f229..c99d2869da 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -13,7 +13,7 @@
#include "nvim/ex_cmds2.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 5b824d23f4..5d6ffc1db1 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -14,6 +14,7 @@ static const char *xdg_env_vars[] = {
[kXDGConfigHome] = "XDG_CONFIG_HOME",
[kXDGDataHome] = "XDG_DATA_HOME",
[kXDGCacheHome] = "XDG_CACHE_HOME",
+ [kXDGStateHome] = "XDG_STATE_HOME",
[kXDGRuntimeDir] = "XDG_RUNTIME_DIR",
[kXDGConfigDirs] = "XDG_CONFIG_DIRS",
[kXDGDataDirs] = "XDG_DATA_DIRS",
@@ -24,6 +25,7 @@ static const char *const xdg_defaults_env_vars[] = {
[kXDGConfigHome] = "LOCALAPPDATA",
[kXDGDataHome] = "LOCALAPPDATA",
[kXDGCacheHome] = "TEMP",
+ [kXDGStateHome] = "LOCALAPPDATA",
[kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = NULL,
[kXDGDataDirs] = NULL,
@@ -38,6 +40,7 @@ static const char *const xdg_defaults[] = {
[kXDGConfigHome] = "~\\AppData\\Local",
[kXDGDataHome] = "~\\AppData\\Local",
[kXDGCacheHome] = "~\\AppData\\Local\\Temp",
+ [kXDGStateHome] = "~\\AppData\\Local",
[kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = NULL,
[kXDGDataDirs] = NULL,
@@ -45,6 +48,7 @@ static const char *const xdg_defaults[] = {
[kXDGConfigHome] = "~/.config",
[kXDGDataHome] = "~/.local/share",
[kXDGCacheHome] = "~/.cache",
+ [kXDGStateHome] = "~/.local/state",
[kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = "/etc/xdg/",
[kXDGDataDirs] = "/usr/local/share/:/usr/share/",
@@ -133,15 +137,26 @@ char *stdpaths_user_conf_subpath(const char *fname)
/// Return subpath of $XDG_DATA_HOME
///
/// @param[in] fname New component of the path.
+///
+/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`
+char *stdpaths_user_data_subpath(const char *fname)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
+{
+ return concat_fnames_realloc(get_xdg_home(kXDGDataHome), fname, true);
+}
+
+/// Return subpath of $XDG_STATE_HOME
+///
+/// @param[in] fname New component of the path.
/// @param[in] trailing_pathseps Amount of trailing path separators to add.
/// @param[in] escape_commas If true, all commas will be escaped.
///
-/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`.
-char *stdpaths_user_data_subpath(const char *fname, const size_t trailing_pathseps,
- const bool escape_commas)
+/// @return [allocated] `$XDG_STATE_HOME/nvim/{fname}`.
+char *stdpaths_user_state_subpath(const char *fname, const size_t trailing_pathseps,
+ const bool escape_commas)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
- char *ret = concat_fnames_realloc(get_xdg_home(kXDGDataHome), fname, true);
+ char *ret = concat_fnames_realloc(get_xdg_home(kXDGStateHome), fname, true);
const size_t len = strlen(ret);
const size_t numcommas = (escape_commas ? memcnt(ret, ',', len) : 0);
if (numcommas || trailing_pathseps) {
diff --git a/src/nvim/os/stdpaths_defs.h b/src/nvim/os/stdpaths_defs.h
index 44c30df373..f94c511fe7 100644
--- a/src/nvim/os/stdpaths_defs.h
+++ b/src/nvim/os/stdpaths_defs.h
@@ -7,6 +7,7 @@ typedef enum {
kXDGConfigHome, ///< XDG_CONFIG_HOME
kXDGDataHome, ///< XDG_DATA_HOME
kXDGCacheHome, ///< XDG_CACHE_HOME
+ kXDGStateHome, ///< XDG_STATE_HOME
kXDGRuntimeDir, ///< XDG_RUNTIME_DIR
kXDGConfigDirs, ///< XDG_CONFIG_DIRS
kXDGDataDirs, ///< XDG_DATA_DIRS
diff --git a/src/nvim/search.c b/src/nvim/search.c
index bee17e861a..9143632c64 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -5160,7 +5160,7 @@ static void fuzzy_match_in_list(list_T *const l, char_u *const str, const bool m
int j = 0;
const char_u *p = str;
while (*p != NUL) {
- if (!ascii_iswhite(utf_ptr2char((char *)p))) {
+ if (!ascii_iswhite(utf_ptr2char((char *)p)) || matchseq) {
tv_list_append_number(items[match_count].lmatchpos, matches[j]);
j++;
}
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index a3d88a4963..abb6c68474 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -1447,7 +1447,7 @@ static const char *shada_get_default_file(void)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (default_shada_file == NULL) {
- char *shada_dir = stdpaths_user_data_subpath("shada", 0, false);
+ char *shada_dir = stdpaths_user_state_subpath("shada", 0, false);
default_shada_file = concat_fnames_realloc(shada_dir, "main.shada", true);
}
return default_shada_file;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index f099d1b34e..6f0bd04d39 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -302,6 +302,7 @@
#define CF_UPPER 0x02
static char *e_spell_trunc = N_("E758: Truncated spell file");
+static char *e_illegal_character_in_word = N_("E1280: Illegal character in word");
static char *e_afftrailing = N_("Trailing text in %s line %d: %s");
static char *e_affname = N_("Affix name too long in %s line %d: %s");
static char *msg_compressing = N_("Compressing word tree...");
@@ -3927,6 +3928,11 @@ static int store_word(spellinfo_T *spin, char_u *word, int flags, int region, co
char_u foldword[MAXWLEN];
int res = OK;
+ // Avoid adding illegal bytes to the word tree.
+ if (!utf_valid_string(word, NULL)) {
+ return FAIL;
+ }
+
(void)spell_casefold(curwin, word, len, foldword, MAXWLEN);
for (const char_u *p = pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
@@ -5525,6 +5531,11 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo
int i;
char_u *spf;
+ if (!utf_valid_string(word, NULL)) {
+ emsg(_(e_illegal_character_in_word));
+ return;
+ }
+
if (idx == 0) { // use internal wordlist
if (int_wordlist == NULL) {
int_wordlist = vim_tempname();
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index db0e6c8762..d82e337aa6 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -27,7 +27,7 @@
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/indent_c.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
#include "nvim/macros.h"
#include "nvim/mbyte.h"
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index f7d33de4fe..2d3102707c 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -56,7 +56,7 @@
#include "nvim/getchar.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/main.h"
@@ -404,7 +404,7 @@ void terminal_enter(void)
// Disable these options in terminal-mode. They are nonsense because cursor is
// placed at end of buffer to "follow" output. #11072
- win_T *save_curwin = curwin;
+ handle_T save_curwin = curwin->handle;
bool save_w_p_cul = curwin->w_p_cul;
char_u *save_w_p_culopt = NULL;
char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags;
@@ -442,7 +442,7 @@ void terminal_enter(void)
RedrawingDisabled = s->save_rd;
apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf);
- if (save_curwin == curwin) { // save_curwin may be invalid (window closed)!
+ if (save_curwin == curwin->handle) { // Else: window was closed.
curwin->w_p_cul = save_w_p_cul;
if (save_w_p_culopt) {
xfree(curwin->w_p_culopt);
diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim
index a31cdbb49a..9eb768f124 100644
--- a/src/nvim/testdir/test_buffer.vim
+++ b/src/nvim/testdir/test_buffer.vim
@@ -61,4 +61,15 @@ func Test_buffer_scheme()
set shellslash&
endfunc
+" this was using a NULL pointer after failing to use the pattern
+func Test_buf_pattern_invalid()
+ vsplit 0000000
+ silent! buf [0--]\&\zs*\zs*e
+ bwipe!
+
+ vsplit 00000000000000000000000000
+ silent! buf [0--]\&\zs*\zs*e
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_matchfuzzy.vim b/src/nvim/testdir/test_matchfuzzy.vim
index d53f8b0f4d..533aec8d9a 100644
--- a/src/nvim/testdir/test_matchfuzzy.vim
+++ b/src/nvim/testdir/test_matchfuzzy.vim
@@ -135,6 +135,9 @@ func Test_matchfuzzypos()
" match multiple words (separated by space)
call assert_equal([['foo bar baz'], [[8, 9, 10, 0, 1, 2]], [369]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('baz foo'))
+ call assert_equal([[], [], []], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('baz foo', {'matchseq': 1}))
+ call assert_equal([['foo bar baz'], [[0, 1, 2, 8, 9, 10]], [369]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz'))
+ call assert_equal([['foo bar baz'], [[0, 1, 2, 3, 4, 5, 10]], [326]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz', {'matchseq': 1}))
call assert_equal([[], [], []], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('one two'))
call assert_equal([[], [], []], ['foo bar']->matchfuzzypos(" \t "))
call assert_equal([['grace'], [[1, 2, 3, 4, 2, 3, 4, 0, 1, 2, 3, 4]], [657]], ['grace']->matchfuzzypos('race ace grace'))
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index 56ed97cdd9..ce21b8bdc9 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -776,14 +776,6 @@ func Test_spell_screendump()
call delete('XtestSpell')
endfunc
-func Test_spell_single_word()
- new
- silent! norm 0R00
- spell! ßÂ
- silent 0norm 0r$ Dvz=
- bwipe!
-endfunc
-
let g:test_data_aff1 = [
\"SET ISO8859-1",
\"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ",
diff --git a/src/nvim/testdir/test_spell_utf8.vim b/src/nvim/testdir/test_spell_utf8.vim
index 3d159f3352..1d323df67e 100644
--- a/src/nvim/testdir/test_spell_utf8.vim
+++ b/src/nvim/testdir/test_spell_utf8.vim
@@ -768,4 +768,10 @@ func Test_spellfile_value()
set spellfile=Xdir/Xtest.utf-8.add,Xtest_other.add
endfunc
+" Invalid bytes may cause trouble when creating the word list.
+func Test_check_for_valid_word()
+ call assert_fails("spellgood! 0\xac", 'E1280:')
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim
index 30e00e7ad4..848860649e 100644
--- a/src/nvim/testdir/test_undo.vim
+++ b/src/nvim/testdir/test_undo.vim
@@ -733,4 +733,21 @@ func Test_undofile_cryptmethod_blowfish2()
set undofile& undolevels& cryptmethod&
endfunc
+func Test_undo_mark()
+ new
+ " The undo is applied to the only line.
+ call setline(1, 'hello')
+ call feedkeys("ggyiw$p", 'xt')
+ undo
+ call assert_equal([0, 1, 1, 0], getpos("'["))
+ call assert_equal([0, 1, 1, 0], getpos("']"))
+ " The undo removes the last line.
+ call feedkeys("Goaaaa\<Esc>", 'xt')
+ call feedkeys("obbbb\<Esc>", 'xt')
+ undo
+ call assert_equal([0, 2, 1, 0], getpos("'["))
+ call assert_equal([0, 2, 1, 0], getpos("']"))
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index d2dc333855..529eef19a3 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2418,10 +2418,11 @@ static void u_undoredo(int undo, bool do_buf_event)
changed_lines(top + 1, 0, bot, newsize - oldsize, do_buf_event);
- // set '[ and '] mark
+ // Set the '[ mark.
if (top + 1 < curbuf->b_op_start.lnum) {
curbuf->b_op_start.lnum = top + 1;
}
+ // Set the '] mark.
if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) {
curbuf->b_op_end.lnum = top + 1;
} else if (top + newsize > curbuf->b_op_end.lnum) {
@@ -2442,6 +2443,14 @@ static void u_undoredo(int undo, bool do_buf_event)
newlist = uep;
}
+ // Ensure the '[ and '] marks are within bounds.
+ if (curbuf->b_op_start.lnum > curbuf->b_ml.ml_line_count) {
+ curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
+ }
+ if (curbuf->b_op_end.lnum > curbuf->b_ml.ml_line_count) {
+ curbuf->b_op_end.lnum = curbuf->b_ml.ml_line_count;
+ }
+
// Adjust Extmarks
ExtmarkUndoObject undo_info;
if (undo) {
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 4e269bc9d4..1c05387da3 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -31,7 +31,7 @@ enum { NUMBUFLEN = 65, };
#define ROOT_UID 0
#include "nvim/gettext.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/macros.h"
// special attribute addition: Put message in history
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index d68f299277..f39aa2f20b 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local lfs = require('lfs')
local fmt = string.format
local assert_alive = helpers.assert_alive
@@ -25,6 +26,7 @@ local tmpname = helpers.tmpname
local write_file = helpers.write_file
local exec_lua = helpers.exec_lua
local exc_exec = helpers.exc_exec
+local insert = helpers.insert
local pcall_err = helpers.pcall_err
local format_string = helpers.format_string
@@ -3473,4 +3475,149 @@ describe('API', function()
pcall_err(meths.parse_cmd, '4,6Fubar', {}))
end)
end)
+ describe('nvim_cmd', function()
+ it('works', function ()
+ meths.cmd({ cmd = "set", args = { "cursorline" } }, {})
+ eq(true, meths.get_option_value("cursorline", {}))
+ end)
+ it('captures output', function()
+ eq("foo", meths.cmd({ cmd = "echo", args = { '"foo"' } }, { output = true }))
+ end)
+ it('sets correct script context', function()
+ meths.cmd({ cmd = "set", args = { "cursorline" } }, {})
+ local str = meths.exec([[verbose set cursorline?]], true)
+ neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)"))
+ end)
+ it('works with range', function()
+ insert [[
+ line1
+ line2
+ line3
+ line4
+ you didn't expect this
+ line5
+ line6
+ ]]
+ meths.cmd({ cmd = "del", range = {2, 4} }, {})
+ expect [[
+ line1
+ you didn't expect this
+ line5
+ line6
+ ]]
+ end)
+ it('works with count', function()
+ insert [[
+ line1
+ line2
+ line3
+ line4
+ you didn't expect this
+ line5
+ line6
+ ]]
+ meths.cmd({ cmd = "del", range = { 2 }, count = 4 }, {})
+ expect [[
+ line1
+ line5
+ line6
+ ]]
+ end)
+ it('works with register', function()
+ insert [[
+ line1
+ line2
+ line3
+ line4
+ you didn't expect this
+ line5
+ line6
+ ]]
+ meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {})
+ meths.exec("1put a", false)
+ expect [[
+ line1
+ line2
+ line3
+ line4
+ you didn't expect this
+ line5
+ line6
+ ]]
+ end)
+ it('works with bang', function ()
+ meths.create_user_command("Foo", 'echo "<bang>"', { bang = true })
+ eq("!", meths.cmd({ cmd = "Foo", bang = true }, { output = true }))
+ eq("", meths.cmd({ cmd = "Foo", bang = false }, { output = true }))
+ end)
+ it('works with modifiers', function()
+ meths.create_user_command("Foo", 'set verbose', {})
+ eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true }))
+ eq(0, meths.get_option_value("verbose", {}))
+ end)
+ it('works with magic.file', function()
+ exec_lua([[
+ vim.api.nvim_create_user_command("Foo", function(opts)
+ vim.api.nvim_echo({{ opts.fargs[1] }}, false, {})
+ end, { nargs = 1 })
+ ]])
+ eq(lfs.currentdir(),
+ meths.cmd({ cmd = "Foo", args = { '%:p:h' }, magic = { file = true } },
+ { output = true }))
+ end)
+ it('splits arguments correctly', function()
+ meths.exec([[
+ function! FooFunc(...)
+ echo a:000
+ endfunction
+ ]], false)
+ meths.create_user_command("Foo", "call FooFunc(<f-args>)", { nargs = '+' })
+ eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=],
+ meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}},
+ { output = true }))
+ eq([=[['test \ \\ \"""\', 'more\ tests\" ']]=],
+ meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
+ { output = true }))
+ end)
+ it('splits arguments correctly for Lua callback', function()
+ meths.exec_lua([[
+ local function FooFunc(opts)
+ vim.pretty_print(opts.fargs)
+ end
+
+ vim.api.nvim_create_user_command("Foo", FooFunc, { nargs = '+' })
+ ]], {})
+ eq([[{ "a quick", "brown fox", "jumps over the", "lazy dog" }]],
+ meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}},
+ { output = true }))
+ eq([[{ 'test \\ \\\\ \\"""\\', 'more\\ tests\\" ' }]],
+ meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
+ { output = true }))
+ end)
+ it('works with buffer names', function()
+ command("edit foo.txt | edit bar.txt")
+ meths.cmd({ cmd = "buffer", args = { "foo.txt" } }, {})
+ eq("foo.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t"))
+ meths.cmd({ cmd = "buffer", args = { "bar.txt" } }, {})
+ eq("bar.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t"))
+ end)
+ it('triggers CmdUndefined event if command is not found', function()
+ meths.exec_lua([[
+ vim.api.nvim_create_autocmd("CmdUndefined",
+ { pattern = "Foo",
+ callback = function()
+ vim.api.nvim_create_user_command("Foo", "echo 'foo'", {})
+ end
+ })
+ ]], {})
+ eq("foo", meths.cmd({ cmd = "Foo" }, { output = true }))
+ end)
+ it('errors if command is not implemented', function()
+ eq("Command not implemented: popup", pcall_err(meths.cmd, { cmd = "popup" }, {}))
+ end)
+ it('works with empty arguments list', function()
+ meths.cmd({ cmd = "update" }, {})
+ meths.cmd({ cmd = "buffer", count = 0 }, {})
+ end)
+ end)
end)
diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua
index 2494daf99b..3b2c1db350 100644
--- a/test/functional/editor/tabpage_spec.lua
+++ b/test/functional/editor/tabpage_spec.lua
@@ -7,6 +7,7 @@ local neq = helpers.neq
local feed = helpers.feed
local eval = helpers.eval
local exec = helpers.exec
+local funcs = helpers.funcs
describe('tabpage', function()
before_each(clear)
@@ -51,5 +52,13 @@ describe('tabpage', function()
]])
neq(999, eval('g:win_closed'))
end)
-end)
+ it(":tabmove handles modifiers and addr", function()
+ command('tabnew | tabnew | tabnew')
+ eq(4, funcs.nvim_tabpage_get_number(0))
+ command(' silent :keepalt :: ::: silent! - tabmove')
+ eq(3, funcs.nvim_tabpage_get_number(0))
+ command(' silent :keepalt :: ::: silent! -2 tabmove')
+ eq(1, funcs.nvim_tabpage_get_number(0))
+ end)
+end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index f589f5955f..86cdf4ef56 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -766,8 +766,21 @@ function tests.code_action_filter()
isPreferred = true,
command = 'preferred_command',
}
+ local quickfix_action = {
+ title = 'Action 3',
+ kind = 'quickfix',
+ command = 'quickfix_command',
+ }
+ local quickfix_foo_action = {
+ title = 'Action 4',
+ kind = 'quickfix.foo',
+ command = 'quickfix_foo_command',
+ }
+ expect_request('textDocument/codeAction', function()
+ return nil, { action, preferred_action, quickfix_action, quickfix_foo_action, }
+ end)
expect_request('textDocument/codeAction', function()
- return nil, { action, preferred_action, }
+ return nil, { action, preferred_action, quickfix_action, quickfix_foo_action, }
end)
notify('shutdown')
end;
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 6620c9acef..36a53d8d26 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -163,7 +163,7 @@ describe('startup defaults', function()
end)
it("'shadafile' ('viminfofile')", function()
- local env = {XDG_DATA_HOME='Xtest-userdata', XDG_CONFIG_HOME='Xtest-userconfig'}
+ local env = {XDG_DATA_HOME='Xtest-userdata', XDG_STATE_HOME='Xtest-userstate', XDG_CONFIG_HOME='Xtest-userconfig'}
clear{args={}, args_rm={'-i'}, env=env}
-- Default 'shadafile' is empty.
-- This means use the default location. :help shada-file-name
@@ -178,7 +178,7 @@ describe('startup defaults', function()
clear{args={}, args_rm={'-i'}, env=env}
eq({ f }, eval('v:oldfiles'))
os.remove('Xtest-foo')
- rmdir('Xtest-userdata')
+ rmdir('Xtest-userstate')
-- Handles viminfo/viminfofile as alias for shada/shadafile.
eq('\n shadafile=', eval('execute("set shadafile?")'))
@@ -206,7 +206,7 @@ describe('startup defaults', function()
describe('$NVIM_LOG_FILE', function()
local xdgdir = 'Xtest-startup-xdg-logpath'
- local xdgcachedir = xdgdir..'/nvim'
+ local xdgstatedir = xdgdir..'/nvim'
after_each(function()
os.remove('Xtest-logpath')
rmdir(xdgdir)
@@ -218,21 +218,21 @@ describe('startup defaults', function()
}})
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
end)
- it('defaults to stdpath("cache")/log if empty', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
+ it('defaults to stdpath("log")/log if empty', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
clear({env={
- XDG_CACHE_HOME=xdgdir,
+ XDG_STATE_HOME=xdgdir,
NVIM_LOG_FILE='', -- Empty is invalid.
}})
- eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
- it('defaults to stdpath("cache")/log if invalid', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
+ it('defaults to stdpath("log")/log if invalid', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
clear({env={
- XDG_CACHE_HOME=xdgdir,
+ XDG_STATE_HOME=xdgdir,
NVIM_LOG_FILE='.', -- Any directory is invalid.
}})
- eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
end)
end)
@@ -264,6 +264,7 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME=nil,
XDG_DATA_HOME=nil,
XDG_CACHE_HOME=nil,
+ XDG_STATE_HOME=nil,
XDG_RUNTIME_DIR=nil,
XDG_CONFIG_DIRS=nil,
XDG_DATA_DIRS=nil,
@@ -293,6 +294,7 @@ describe('XDG-based defaults', function()
local env_sep = iswin() and ';' or ':'
local data_dir = iswin() and 'nvim-data' or 'nvim'
+ local state_dir = iswin() and 'nvim-data' or 'nvim'
local root_path = iswin() and 'C:' or ''
describe('with too long XDG variables', function()
@@ -303,6 +305,7 @@ describe('XDG-based defaults', function()
.. env_sep.. root_path .. ('/b'):rep(2048)
.. (env_sep .. root_path .. '/c'):rep(512)),
XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
+ XDG_STATE_HOME=(root_path .. ('/X'):rep(4096)),
XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
.. env_sep .. root_path .. ('/B'):rep(2048)
.. (env_sep .. root_path .. '/C'):rep(512)),
@@ -355,13 +358,13 @@ describe('XDG-based defaults', function()
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup//',
+ eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. state_dir .. '/backup//',
(meths.get_option('backupdir'):gsub('\\', '/')))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
(meths.get_option('directory')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
(meths.get_option('undodir')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
(meths.get_option('viewdir')):gsub('\\', '/'))
end)
end)
@@ -372,6 +375,7 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME='$XDG_DATA_HOME',
XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
XDG_DATA_HOME='$XDG_CONFIG_HOME',
+ XDG_STATE_HOME='$XDG_CONFIG_HOME',
XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
}})
end)
@@ -405,13 +409,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
+ eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
@@ -425,13 +429,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
+ eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
end)
end)
@@ -442,6 +446,7 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME=', , ,',
XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
XDG_DATA_HOME=',=,=,',
+ XDG_STATE_HOME=',=,=,',
XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
}})
end)
@@ -484,13 +489,13 @@ describe('XDG-based defaults', function()
.. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
), meths.get_option('runtimepath'))
- eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
+ eq('.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
meths.get_option('backupdir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
meths.get_option('directory'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
meths.get_option('undodir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
meths.get_option('viewdir'))
end)
end)
@@ -499,8 +504,9 @@ end)
describe('stdpath()', function()
-- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
- -- due to XDG_CONFIG_HOME and XDG_DATA_HOME being the same.
+ -- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same.
local datadir = iswin() and 'nvim-data' or 'nvim'
+ local statedir = iswin() and 'nvim-data' or 'nvim'
local env_sep = iswin() and ';' or ':'
it('acceptance', function()
@@ -509,6 +515,7 @@ describe('stdpath()', function()
eq('nvim', funcs.fnamemodify(funcs.stdpath('cache'), ':t'))
eq('nvim', funcs.fnamemodify(funcs.stdpath('config'), ':t'))
eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t'))
+ eq(statedir, funcs.fnamemodify(funcs.stdpath('state'), ':t'))
eq('table', type(funcs.stdpath('config_dirs')))
eq('table', type(funcs.stdpath('data_dirs')))
assert_alive() -- Check for crash. #8393
@@ -582,6 +589,39 @@ describe('stdpath()', function()
end)
end)
+ describe('with "state"' , function ()
+ it('knows XDG_STATE_HOME', function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('/home/docwhat/.local'),
+ }})
+ eq(alter_slashes('/home/docwhat/.local/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/'..statedir), funcs.stdpath('state'))
+ command("let $XDG_STATE_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_STATE_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/'..statedir), funcs.stdpath('state'))
+ end)
+ end)
+
describe('with "cache"' , function ()
it('knows XDG_CACHE_HOME', function()
clear({env={
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 33a8976b79..4cb7636825 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -2753,12 +2753,33 @@ describe('LSP', function()
vim.lsp.commands['executed_preferred'] = function()
end
end
+ vim.lsp.commands['quickfix_command'] = function(cmd)
+ vim.lsp.commands['executed_quickfix'] = function()
+ end
+ end
local bufnr = vim.api.nvim_get_current_buf()
vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
vim.lsp.buf.code_action({ filter = function(a) return a.isPreferred end, apply = true, })
+ vim.lsp.buf.code_action({
+ -- expect to be returned actions 'quickfix' and 'quickfix.foo'
+ context = { only = {'quickfix'}, },
+ apply = true,
+ filter = function(a)
+ if a.kind == 'quickfix.foo' then
+ vim.lsp.commands['filtered_quickfix_foo'] = function() end
+ return false
+ elseif a.kind == 'quickfix' then
+ return true
+ else
+ assert(nil, 'unreachable')
+ end
+ end,
+ })
]])
elseif ctx.method == 'shutdown' then
eq('function', exec_lua[[return type(vim.lsp.commands['executed_preferred'])]])
+ eq('function', exec_lua[[return type(vim.lsp.commands['filtered_quickfix_foo'])]])
+ eq('function', exec_lua[[return type(vim.lsp.commands['executed_quickfix'])]])
client.stop()
end
end
diff --git a/test/symbolic/klee/nvim/keymap.c b/test/symbolic/klee/nvim/keymap.c
index ed5f95a344..1f7f0e0911 100644
--- a/test/symbolic/klee/nvim/keymap.c
+++ b/test/symbolic/klee/nvim/keymap.c
@@ -1,7 +1,7 @@
#include <stdbool.h>
#include "nvim/types.h"
-#include "nvim/keymap.h"
+#include "nvim/keycodes.h"
#include "nvim/ascii.h"
#include "nvim/eval/typval.h"
diff --git a/test/symbolic/klee/viml_expressions_lexer.c b/test/symbolic/klee/viml_expressions_lexer.c
index ee7dc312e9..03c9d66ca4 100644
--- a/test/symbolic/klee/viml_expressions_lexer.c
+++ b/test/symbolic/klee/viml_expressions_lexer.c
@@ -17,7 +17,7 @@
#include "nvim/charset.c"
#include "nvim/garray.c"
#include "nvim/gettext.c"
-#include "nvim/keymap.c"
+#include "nvim/keycodes.c"
#include "nvim/viml/parser/expressions.c"
#define INPUT_SIZE 7
diff --git a/test/symbolic/klee/viml_expressions_parser.c b/test/symbolic/klee/viml_expressions_parser.c
index 9a876ed3fa..b0e1d71127 100644
--- a/test/symbolic/klee/viml_expressions_parser.c
+++ b/test/symbolic/klee/viml_expressions_parser.c
@@ -17,7 +17,7 @@
#include "nvim/garray.c"
#include "nvim/gettext.c"
#include "nvim/viml/parser/expressions.c"
-#include "nvim/keymap.c"
+#include "nvim/keycodes.c"
#define INPUT_SIZE 50
diff --git a/test/unit/keymap_spec.lua b/test/unit/keycodes_spec.lua
index 1f1f32bb9e..5bf27c9232 100644
--- a/test/unit/keymap_spec.lua
+++ b/test/unit/keycodes_spec.lua
@@ -5,10 +5,10 @@ local ffi = helpers.ffi
local eq = helpers.eq
local neq = helpers.neq
-local keymap = helpers.cimport('./src/nvim/keymap.h')
+local keymap = helpers.cimport('./src/nvim/keycodes.h')
local NULL = helpers.NULL
-describe('keymap.c', function()
+describe('keycodes.c', function()
describe('find_special_key()', function()
local srcp = ffi.new('const unsigned char *[1]')
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index d494a96907..21d1f7906a 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -39,7 +39,6 @@ set(DEPS_DOWNLOAD_DIR "${DEPS_BUILD_DIR}/downloads" CACHE PATH "Dependencies dow
option(USE_BUNDLED "Use bundled dependencies." ON)
-option(USE_BUNDLED_GPERF "Use the bundled version of gperf." ${USE_BUNDLED})
option(USE_BUNDLED_UNIBILIUM "Use the bundled unibilium." ${USE_BUNDLED})
option(USE_BUNDLED_LIBTERMKEY "Use the bundled libtermkey." ${USE_BUNDLED})
option(USE_BUNDLED_LIBVTERM "Use the bundled libvterm." ${USE_BUNDLED})
@@ -109,10 +108,6 @@ else()
set(DEPS_C_COMPILER "${CMAKE_C_COMPILER}")
endif()
-if(USE_BUNDLED_GPERF)
- enable_language(CXX)
-endif()
-
if(CMAKE_CXX_COMPILER)
set(DEPS_CXX_COMPILER "${CMAKE_CXX_COMPILER}")
endif()
@@ -170,15 +165,12 @@ set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.1.4.tar.gz)
set(LIBVTERM_SHA256 bc70349e95559c667672fc8c55b9527d9db9ada0fb80a3beda533418d782d3dd)
set(LUV_VERSION 1.43.0-0)
-set(LUV_URL https://github.com/luvit/luv/archive/${LUV_VERSION}.tar.gz)
-set(LUV_SHA256 a36865f34db029e2caa01245a41341a067038c09e94459b50db1346d9fdf82f0)
+set(LUV_URL https://github.com/luvit/luv/archive/c51e7052ec4f0a25058f70c1b4ee99dd36180e59.tar.gz)
+set(LUV_SHA256 cabb7e650f35992686eb95ae167c71614e281cd2979fc804e4e70f8051555728)
set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz)
set(LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416)
-set(GPERF_URL https://github.com/neovim/deps/raw/ff5b4b18a87397a8564016071ae64f64bcd8c635/opt/gperf-3.1.tar.gz)
-set(GPERF_SHA256 588546b945bba4b70b6a3a616e80b4ab466e3f33024a352fc2198112cdbb3ae2)
-
# cat.exe curl.exe curl-ca-bundle.crt diff.exe tee.exe xxd.exe
set(WINTOOLS_URL https://github.com/neovim/deps/raw/d66e306abf5b846484b4f2adffd896bce7e065d2/opt/win32tools.zip)
set(WINTOOLS_SHA256 2fb2f8d69070b3f16e029913fb95008e6be33893d77fc358012396c275a0fdb7)
@@ -242,10 +234,6 @@ if(USE_BUNDLED_LUV)
include(BuildLuv)
endif()
-if(USE_BUNDLED_GPERF)
- include(BuildGperf)
-endif()
-
if(USE_BUNDLED_GETTEXT)
include(BuildGettext)
endif()
diff --git a/third-party/cmake/BuildGperf.cmake b/third-party/cmake/BuildGperf.cmake
deleted file mode 100644
index 5401191150..0000000000
--- a/third-party/cmake/BuildGperf.cmake
+++ /dev/null
@@ -1,68 +0,0 @@
-# Gperf recipe. Gperf is only required when building Neovim, when
-# cross compiling we still want to build for the HOST system, whenever
-# writing a recipe that is meant for cross-compile, use the HOSTDEPS_* variables
-# instead of DEPS_* - check the main CMakeLists.txt for a list.
-
-# BuildGperf(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Reusable function to build Gperf, wraps ExternalProject_Add.
-# Failing to pass a command argument will result in no command being run
-function(BuildGperf)
- cmake_parse_arguments(_gperf
- ""
- ""
- "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _gperf_CONFIGURE_COMMAND AND NOT _gperf_BUILD_COMMAND
- AND NOT _gperf_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(gperf
- PREFIX ${DEPS_BUILD_DIR}
- URL ${GPERF_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/gperf
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/gperf
- -DURL=${GPERF_URL}
- -DEXPECTED_SHA256=${GPERF_SHA256}
- -DTARGET=gperf
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${_gperf_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_gperf_BUILD_COMMAND}"
- INSTALL_COMMAND "${_gperf_INSTALL_COMMAND}")
-endfunction()
-
-set(GPERF_BUILDARGS CC=${HOSTDEPS_C_COMPILER} CXX=${HOSTDEPS_CXX_COMPILER}
- LD=${HOSTDEPS_C_COMPILER})
-
-if(UNIX OR (MINGW AND CMAKE_CROSSCOMPILING))
-
- BuildGperf(
- CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/gperf/configure
- --prefix=${HOSTDEPS_INSTALL_DIR}
- MAKE=${MAKE_PRG} ${GPERF_BUILDARGS}
- INSTALL_COMMAND ${MAKE_PRG} install)
-
-elseif(MSVC OR MINGW)
-
- BuildGperf(
- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/GperfCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/gperf/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/gperf/CMakeLists.txt
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
-
-else()
- message(FATAL_ERROR "Trying to build gperf in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
-endif()
diff --git a/third-party/cmake/GperfCMakeLists.txt b/third-party/cmake/GperfCMakeLists.txt
deleted file mode 100644
index 15ae305ba8..0000000000
--- a/third-party/cmake/GperfCMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(gperf LANGUAGES C CXX)
-
-add_executable(gperf
- lib/getline.cc
- lib/hash.cc
- lib/getopt.c
- lib/getopt1.c
- src/version.cc
- src/positions.cc
- src/options.cc
- src/keyword.cc
- src/keyword-list.cc
- src/input.cc
- src/bool-array.cc
- src/hash-table.cc
- src/search.cc
- src/output.cc
- src/main.cc)
-
-include_directories(lib)
-
-# Copy the config.h template without modifying it
-# because none of the definitions are necessary
-execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/config.h.in ${CMAKE_BINARY_DIR}/config/config.h)
-include_directories(${CMAKE_BINARY_DIR}/config)
-
-include(GNUInstallDirs)
-install(TARGETS gperf
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})