aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/autoload/health/treesitter.vim5
-rw-r--r--runtime/autoload/tutor.vim4
-rw-r--r--runtime/delmenu.vim30
-rw-r--r--runtime/doc/api.txt31
-rw-r--r--runtime/doc/eval.txt181
-rw-r--r--runtime/doc/lsp.txt32
-rw-r--r--runtime/doc/lua.txt4
-rw-r--r--runtime/doc/options.txt2
-rw-r--r--runtime/doc/repeat.txt13
-rw-r--r--runtime/doc/usr_41.txt3
-rw-r--r--runtime/filetype.vim15
-rw-r--r--runtime/lua/vim/lsp.lua236
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua4
-rw-r--r--runtime/lua/vim/lsp/handlers.lua47
-rw-r--r--runtime/lua/vim/lsp/util.lua68
-rw-r--r--runtime/lua/vim/treesitter.lua3
-rw-r--r--runtime/lua/vim/treesitter/health.lua34
-rw-r--r--runtime/lua/vim/treesitter/query.lua14
-rw-r--r--runtime/menu.vim10
19 files changed, 591 insertions, 145 deletions
diff --git a/runtime/autoload/health/treesitter.vim b/runtime/autoload/health/treesitter.vim
new file mode 100644
index 0000000000..5f167310ce
--- /dev/null
+++ b/runtime/autoload/health/treesitter.vim
@@ -0,0 +1,5 @@
+function! health#treesitter#check() abort
+ call health#report_start('Checking treesitter configuration')
+ lua require 'vim.treesitter.health'.check_health()
+endfunction
+
diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim
index 6afe64de84..abf5c5e2c8 100644
--- a/runtime/autoload/tutor.vim
+++ b/runtime/autoload/tutor.vim
@@ -104,6 +104,10 @@ function! tutor#CheckLine(line)
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
let bufn = bufnr('%')
let ctext = getline(a:line)
+ let signs = sign_getplaced('.', {'lnum': a:line})[0].signs
+ if !empty(signs)
+ call sign_unplace('', {'id': signs[0].id})
+ endif
if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)]
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn
else
diff --git a/runtime/delmenu.vim b/runtime/delmenu.vim
index 81df87d346..5c20290152 100644
--- a/runtime/delmenu.vim
+++ b/runtime/delmenu.vim
@@ -2,24 +2,30 @@
" Warning: This also deletes all menus defined by the user!
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2001 May 27
+" Last Change: 2019 Dec 10
aunmenu *
-silent! unlet did_install_default_menus
-silent! unlet did_install_syntax_menu
-if exists("did_menu_trans")
+unlet! g:did_install_default_menus
+unlet! g:did_install_syntax_menu
+
+if exists('g:did_menu_trans')
menutrans clear
- unlet did_menu_trans
+ unlet g:did_menu_trans
endif
-silent! unlet find_help_dialog
+unlet! g:find_help_dialog
-silent! unlet menutrans_help_dialog
-silent! unlet menutrans_path_dialog
-silent! unlet menutrans_tags_dialog
-silent! unlet menutrans_textwidth_dialog
-silent! unlet menutrans_fileformat_dialog
-silent! unlet menutrans_no_file
+unlet! g:menutrans_fileformat_choices
+unlet! g:menutrans_fileformat_dialog
+unlet! g:menutrans_help_dialog
+unlet! g:menutrans_no_file
+unlet! g:menutrans_path_dialog
+unlet! g:menutrans_set_lang_to
+unlet! g:menutrans_spell_add_ARG_to_word_list
+unlet! g:menutrans_spell_change_ARG_to
+unlet! g:menutrans_spell_ignore_ARG
+unlet! g:menutrans_tags_dialog
+unlet! g:menutrans_textwidth_dialog
" vim: set sw=2 :
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 1e287281cf..0c17fa1669 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1311,6 +1311,34 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
and clearing the |EndOfBuffer| region in
'winhighlight'.
+ • `border`: style of (optional) window border. This can
+ either be a string or an array. the string
+ values are:
+ • "none" No border. This is the default
+ • "single" a single line box
+ • "double" a double line box
+ • "shadow" a drop shadow effect by blending
+ with the background. If it is an array it
+ should be an array of eight items or any
+ divisor of eight. The array will specifify
+ the eight chars building up the border in a
+ clockwise fashion starting with the top-left
+ corner. As, an example, the double box style
+ could be specified as: [ "╔", "═" ,"╗", "║",
+ "╝", "═", "╚", "║" ] if the number of chars
+ are less than eight, they will be repeated.
+ Thus an ASCII border could be specified as:
+ [ "/", "-", "\\", "|" ] or all chars the
+ same as: [ "x" ] An empty string can be used
+ to turn off a specific border, for instance:
+ [ "", "", "", ">", "", "", "", "<" ] will
+ only make vertical borders but not
+ horizontal ones. By default `FloatBorder`
+ highlight is used which links to `VertSplit`
+ when not defined. It could also be specified
+ by character: [ {"+", "MyCorner"}, {"x",
+ "MyBorder"} ]
+
Return: ~
Window handle, or 0 on error
@@ -2266,6 +2294,9 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
exists) will be shifted in when new text is
inserted (true for right, false for left).
Defaults to false.
+ • priority: a priority value for the highlight
+ group. For example treesitter highlighting
+ uses a value of 100.
Return: ~
Id of the created/updated extmark
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 2911224de5..c3736d9a3e 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2047,6 +2047,7 @@ assert_inrange({lower}, {upper}, {actual} [, {msg}])
Number assert {actual} is inside the range
assert_match({pat}, {text} [, {msg}])
Number assert {pat} matches {text}
+assert_nobeep({cmd}) Number assert {cmd} does not cause a beep
assert_notequal({exp}, {act} [, {msg}])
Number assert {exp} is not equal {act}
assert_notmatch({pat}, {text} [, {msg}])
@@ -2394,6 +2395,7 @@ shellescape({string} [, {special}])
command argument
shiftwidth([{col}]) Number effective value of 'shiftwidth'
sign_define({name} [, {dict}]) Number define or update a sign
+sign_define({list}) List define or update a list of signs
sign_getdefined([{name}]) List get a list of defined signs
sign_getplaced([{expr} [, {dict}]])
List get a list of placed signs
@@ -2401,9 +2403,12 @@ sign_jump({id}, {group}, {expr})
Number jump to a sign
sign_place({id}, {group}, {name}, {expr} [, {dict}])
Number place a sign
+sign_placelist({list}) List place a list of signs
sign_undefine([{name}]) Number undefine a sign
+sign_undefine({list}) List undefine a list of signs
sign_unplace({group} [, {dict}])
Number unplace a sign
+sign_unplacelist({list}) List unplace a list of signs
simplify({filename}) String simplify filename as much as possible
sin({expr}) Float sine of {expr}
sinh({expr}) Float hyperbolic sine of {expr}
@@ -2638,7 +2643,8 @@ argv([{nr} [, {winid}])
assert_beeps({cmd}) *assert_beeps()*
Run {cmd} and add an error message to |v:errors| if it does
NOT produce a beep or visual bell.
- Also see |assert_fails()| and |assert-return|.
+ Also see |assert_fails()|, |assert_nobeep()| and
+ |assert-return|.
*assert_equal()*
assert_equal({expected}, {actual}, [, {msg}])
@@ -2721,6 +2727,11 @@ assert_match({pattern}, {actual} [, {msg}])
< Will result in a string to be added to |v:errors|:
test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~
+assert_nobeep({cmd}) *assert_nobeep()*
+ Run {cmd} and add an error message to |v:errors| if it
+ produces a beep or visual bell.
+ Also see |assert_beeps()|.
+
*assert_notequal()*
assert_notequal({expected}, {actual} [, {msg}])
The opposite of `assert_equal()`: add an error message to
@@ -5552,13 +5563,14 @@ id({expr}) *id()*
Returns a |String| which is a unique identifier of the
container type (|List|, |Dict| and |Partial|). It is
guaranteed that for the mentioned types `id(v1) ==# id(v2)`
- returns true iff `type(v1) == type(v2) && v1 is v2` (note:
- |v:_null_list| and |v:_null_dict| have the same `id()` with
- different types because they are internally represented as
- a NULL pointers). Currently `id()` returns a hexadecimal
- representanion of the pointers to the containers (i.e. like
- `0x994a40`), same as `printf("%p", {expr})`, but it is advised
- against counting on exact format of return value.
+ returns true iff `type(v1) == type(v2) && v1 is v2`.
+ Note that |v:_null_string|, |v:_null_list|, and |v:_null_dict|
+ have the same `id()` with different types because they are
+ internally represented as a NULL pointers. `id()` returns a
+ hexadecimal representanion of the pointers to the containers
+ (i.e. like `0x994a40`), same as `printf("%p", {expr})`,
+ but it is advised against counting on the exact format of
+ return value.
It is not guaranteed that `id(no_longer_existing_container)`
will not be equal to some other `id()`: new containers may
@@ -7920,6 +7932,7 @@ shiftwidth([{col}]) *shiftwidth()*
will be assumed.
sign_define({name} [, {dict}]) *sign_define()*
+sign_define({list})
Define a new sign named {name} or modify the attributes of an
existing sign. This is similar to the |:sign-define| command.
@@ -7929,24 +7942,38 @@ sign_define({name} [, {dict}]) *sign_define()*
The {name} can be a String or a Number. The optional {dict}
argument specifies the sign attributes. The following values
are supported:
- icon full path to the bitmap file for the sign.
- linehl highlight group used for the whole line the
+ icon full path to the bitmap file for the sign.
+ linehl highlight group used for the whole line the
sign is placed in.
- text text that is displayed when there is no icon
+ text text that is displayed when there is no icon
or the GUI is not being used.
- texthl highlight group used for the text item
- numhl highlight group used for 'number' column at the
+ texthl highlight group used for the text item
+ numhl highlight group used for 'number' column at the
associated line. Overrides |hl-LineNr|,
|hl-CursorLineNr|.
If the sign named {name} already exists, then the attributes
of the sign are updated.
- Returns 0 on success and -1 on failure.
+ The one argument {list} can be used to define a list of signs.
+ Each list item is a dictionary with the above items in {dict}
+ and a 'name' item for the sign name.
+
+ Returns 0 on success and -1 on failure. When the one argument
+ {list} is used, then returns a List of values one for each
+ defined sign.
Examples: >
- call sign_define("mySign", {"text" : "=>", "texthl" :
- \ "Error", "linehl" : "Search"})
+ call sign_define("mySign", {
+ \ "text" : "=>",
+ \ "texthl" : "Error",
+ \ "linehl" : "Search"})
+ call sign_define([
+ \ {'name' : 'sign1',
+ \ 'text' : '=>'},
+ \ {'name' : 'sign2',
+ \ 'text' : '!!'}
+ \ ])
<
sign_getdefined([{name}]) *sign_getdefined()*
Get a list of defined signs and their attributes.
@@ -7958,14 +7985,14 @@ sign_getdefined([{name}]) *sign_getdefined()*
Each list item in the returned value is a dictionary with the
following entries:
- icon full path to the bitmap file of the sign
- linehl highlight group used for the whole line the
+ icon full path to the bitmap file of the sign
+ linehl highlight group used for the whole line the
sign is placed in.
- name name of the sign
- text text that is displayed when there is no icon
+ name name of the sign
+ text text that is displayed when there is no icon
or the GUI is not being used.
- texthl highlight group used for the text item
- numhl highlight group used for 'number' column at the
+ texthl highlight group used for the text item
+ numhl highlight group used for 'number' column at the
associated line. Overrides |hl-LineNr|,
|hl-CursorLineNr|.
@@ -8056,25 +8083,25 @@ sign_jump({id}, {group}, {expr})
<
*sign_place()*
sign_place({id}, {group}, {name}, {expr} [, {dict}])
- Place the sign defined as {name} at line {lnum} in file {expr}
- and assign {id} and {group} to sign. This is similar to the
- |:sign-place| command.
+ Place the sign defined as {name} at line {lnum} in file or
+ buffer {expr} and assign {id} and {group} to sign. This is
+ similar to the |:sign-place| command.
If the sign identifier {id} is zero, then a new identifier is
allocated. Otherwise the specified number is used. {group} is
the sign group name. To use the global sign group, use an
empty string. {group} functions as a namespace for {id}, thus
two groups can use the same IDs. Refer to |sign-identifier|
- for more information.
+ and |sign-group| for more information.
{name} refers to a defined sign.
{expr} refers to a buffer name or number. For the accepted
values, see |bufname()|.
The optional {dict} argument supports the following entries:
- lnum line number in the buffer {expr} where
- the sign is to be placed. For the
- accepted values, see |line()|.
+ lnum line number in the file or buffer
+ {expr} where the sign is to be placed.
+ For the accepted values, see |line()|.
priority priority of the sign. See
|sign-priority| for more information.
@@ -8103,17 +8130,85 @@ sign_place({id}, {group}, {name}, {expr} [, {dict}])
call sign_place(10, 'g3', 'sign4', 'json.c',
\ {'lnum' : 40, 'priority' : 90})
<
+ *sign_placelist()*
+sign_placelist({list})
+ Place one or more signs. This is similar to the
+ |sign_place()| function. The {list} argument specifies the
+ List of signs to place. Each list item is a dict with the
+ following sign attributes:
+ buffer buffer name or number. For the accepted
+ values, see |bufname()|.
+ group sign group. {group} functions as a namespace
+ for {id}, thus two groups can use the same
+ IDs. If not specified or set to an empty
+ string, then the global group is used. See
+ |sign-group| for more information.
+ id sign identifier. If not specified or zero,
+ then a new unique identifier is allocated.
+ Otherwise the specified number is used. See
+ |sign-identifier| for more information.
+ lnum line number in the buffer {expr} where the
+ sign is to be placed. For the accepted values,
+ see |line()|.
+ name name of the sign to place. See |sign_define()|
+ for more information.
+ priority priority of the sign. When multiple signs are
+ placed on a line, the sign with the highest
+ priority is used. If not specified, the
+ default value of 10 is used. See
+ |sign-priority| for more information.
+
+ If {id} refers to an existing sign, then the existing sign is
+ modified to use the specified {name} and/or {priority}.
+
+ Returns a List of sign identifiers. If failed to place a
+ sign, the corresponding list item is set to -1.
+
+ Examples: >
+ " Place sign s1 with id 5 at line 20 and id 10 at line
+ " 30 in buffer a.c
+ let [n1, n2] = sign_place([
+ \ {'id' : 5,
+ \ 'name' : 's1',
+ \ 'buffer' : 'a.c',
+ \ 'lnum' : 20},
+ \ {'id' : 10,
+ \ 'name' : 's1',
+ \ 'buffer' : 'a.c',
+ \ 'lnum' : 30}
+ \ ])
+
+ " Place sign s1 in buffer a.c at line 40 and 50
+ " with auto-generated identifiers
+ let [n1, n2] = sign_place([
+ \ {'name' : 's1',
+ \ 'buffer' : 'a.c',
+ \ 'lnum' : 40},
+ \ {'name' : 's1',
+ \ 'buffer' : 'a.c',
+ \ 'lnum' : 50}
+ \ ])
+<
sign_undefine([{name}]) *sign_undefine()*
+sign_undefine({list})
Deletes a previously defined sign {name}. This is similar to
the |:sign-undefine| command. If {name} is not supplied, then
deletes all the defined signs.
- Returns 0 on success and -1 on failure.
+ The one argument {list} can be used to undefine a list of
+ signs. Each list item is the name of a sign.
+
+ Returns 0 on success and -1 on failure. For the one argument
+ {list} call, returns a list of values one for each undefined
+ sign.
Examples: >
" Delete a sign named mySign
call sign_undefine("mySign")
+ " Delete signs 'sign1' and 'sign2'
+ call sign_undefine(["sign1", "sign2"])
+
" Delete all the signs
call sign_undefine()
<
@@ -8159,6 +8254,32 @@ sign_unplace({group} [, {dict}]) *sign_unplace()*
" Remove all the placed signs from all the buffers
call sign_unplace('*')
<
+sign_unplacelist({list}) *sign_unplacelist()*
+ Remove previously placed signs from one or more buffers. This
+ is similar to the |sign_unplace()| function.
+
+ The {list} argument specifies the List of signs to remove.
+ Each list item is a dict with the following sign attributes:
+ buffer buffer name or number. For the accepted
+ values, see |bufname()|. If not specified,
+ then the specified sign is removed from all
+ the buffers.
+ group sign group name. If not specified or set to an
+ empty string, then the global sign group is
+ used. If set to '*', then all the groups
+ including the global group are used.
+ id sign identifier. If not specified, then all
+ the signs in the specified group are removed.
+
+ Returns a List where an entry is set to 0 if the corresponding
+ sign was successfully removed or -1 on failure.
+
+ Example: >
+ " Remove sign with id 10 from buffer a.vim and sign
+ " with id 20 from buffer b.vim
+ call sign_unplace([{'id' : 10, 'buffer' : "a.vim"},
+ \ {'id' : 20, 'buffer' : 'b.vim'}])
+<
simplify({filename}) *simplify()*
Simplify the file name as much as possible without changing
the meaning. Shortcuts (on MS-Windows) or symbolic links (on
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 67a10c7efb..3c0dbf96c5 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1467,6 +1467,25 @@ progress_handler({_}, {_}, {params}, {client_id})
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
+ *vim.lsp.handlers.signature_help()*
+signature_help({_}, {method}, {result}, {_}, {bufnr}, {config})
+ Parameters: ~
+ {config} table Configuration table.
+ • border: (default=nil)
+ • Add borders to the floating window
+ • See |vim.api.nvim_open_win()|
+
+ See also: ~
+ https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration@seehttps://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition@seehttps://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition@seehttps://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation|lsp-handler| for the method "textDocument/signatureHelp">
+
+ vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(
+ vim.lsp.handlers.signature_help, {
+ -- Use a sharp border with `FloatBorder` highlights
+ border = "single"
+ }
+ )
+<
+
==============================================================================
Lua module: vim.lsp.util *lsp-util*
@@ -1541,13 +1560,20 @@ close_preview_autocmd({events}, {winnr})
|autocmd-events|
*vim.lsp.util.compute_diff()*
-compute_diff({old_lines}, {new_lines}, {start_line_idx}, {end_line_idx})
+compute_diff({old_lines}, {new_lines}, {start_line_idx}, {end_line_idx},
+ {offset_encoding})
Returns the range table for the difference between old and new
lines
Parameters: ~
- {old_lines} table list of lines
- {new_lines} table list of lines
+ {old_lines} table list of lines
+ {new_lines} table list of lines
+ {start_line_idx} int line to begin search for first
+ difference
+ {end_line_idx} int line to begin search for last
+ difference
+ {offset_encoding} string encoding requested by language
+ server
Return: ~
table start_line_idx and start_col_idx of range
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index c2fc25431c..6d007c0e44 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -18,7 +18,8 @@ an idea of what lurks beneath: >
Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
"editor stdlib" (|functions| and Ex commands) and the |API|, all of which can
-be used from Lua code.
+be used from Lua code. A good overview of using Lua in neovim is given by
+https://github.com/nanotee/nvim-lua-guide.
Module conflicts are resolved by "last wins". For example if both of these
are on 'runtimepath':
@@ -831,6 +832,7 @@ 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()*
Invokes |vim-function| or |user-function| {func} with arguments {...}.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 04310ca8d4..651d4c4bc7 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4818,7 +4818,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|xdg| ($XDG_CONFIG_DIRS, defaults to /etc/xdg). This also contains
preferences from system administrator.
3. Data home directory, for plugins installed by user.
- Given by `stdpath("data")`. |$XDG_DATA_HOME|
+ Given by `stdpath("data")/site`. |$XDG_DATA_HOME|
4. nvim/site subdirectories for each directory in $XDG_DATA_DIRS.
This is for plugins which were installed by system administrator,
but are not part of the Nvim distribution. XDG_DATA_DIRS defaults
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 604c969c64..3a7337d2e8 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -804,6 +804,19 @@ DEFINING BREAKPOINTS
< Note that this only works for commands that are executed when
sourcing the file, not for a function defined in that file.
+:breaka[dd] expr {expression}
+ Sets a breakpoint, that will break whenever the {expression}
+ evaluates to a different value. Example: >
+ :breakadd expr g:lnum
+
+< Will break, whenever the global variable lnum changes.
+ Note if you watch a |script-variable| this will break
+ when switching scripts, since the script variable is only
+ valid in the script where it has been defined and if that
+ script is called from several other scripts, this will stop
+ whenever that particular variable will become visible or
+ unaccessible again.
+
The [lnum] is the line number of the breakpoint. Vim will stop at or after
this line. When omitted line 1 is used.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 97aacc1403..21f5dcc815 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -943,8 +943,10 @@ Signs: *sign-functions*
sign_getplaced() get a list of placed signs
sign_jump() jump to a sign
sign_place() place a sign
+ sign_placelist() place a list of signs
sign_undefine() undefine a sign
sign_unplace() unplace a sign
+ sign_unplacelist() unplace a list of signs
Testing: *test-functions*
@@ -958,6 +960,7 @@ Testing: *test-functions*
assert_true() assert that an expression is true
assert_exception() assert that a command throws an exception
assert_beeps() assert that a command beeps
+ assert_nobeep() assert that a command does not cause a beep
assert_fails() assert that a command fails
Timers: *timer-functions*
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 36352db533..b7157a14e7 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2020 Apr 29
+" Last Change: 2021 Apr 05
" Listen very carefully, I will say this only once
if exists("did_load_filetypes")
@@ -1275,6 +1275,11 @@ au BufNewFile,BufRead .povrayrc setf povini
" Povray, Pascal, PHP or assembly
au BufNewFile,BufRead *.inc call dist#ft#FTinc()
+" PowerShell
+au BufNewFile,BufRead *.ps1,*.psd1,*.psm1,*.pssc setf ps1
+au BufNewFile,BufRead *.ps1xml setf ps1xml
+au BufNewFile,BufRead *.cdxml,*.psc1 setf xml
+
" Printcap and Termcap
au BufNewFile,BufRead *printcap
\ let b:ptcap_type = "print" | setf ptcap
@@ -1554,11 +1559,10 @@ au BufNewFile,BufRead catalog setf catalog
" Shell scripts (sh, ksh, bash, bash2, csh); Allow .profile_foo etc.
" Gentoo ebuilds and Arch Linux PKGBUILDs are actually bash scripts
" NOTE: Patterns ending in a star are further down, these have lower priority.
-au BufNewFile,BufRead .bashrc,bashrc,bash.bashrc,.bash[_-]profile,.bash[_-]logout,.bash[_-]aliases,bash-fc[-.],*.bash,*/{,.}bash[_-]completion{,.d,.sh}{,/*},*.ebuild,*.eclass,PKGBUILD call dist#ft#SetFileTypeSH("bash")
+au BufNewFile,BufRead .bashrc,bashrc,bash.bashrc,.bash[_-]profile,.bash[_-]logout,.bash[_-]aliases,bash-fc[-.],*.ebuild,*.bash,*.eclass,PKGBUILD,APKBUILD call dist#ft#SetFileTypeSH("bash")
au BufNewFile,BufRead .kshrc,*.ksh call dist#ft#SetFileTypeSH("ksh")
au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.env call dist#ft#SetFileTypeSH(getline(1))
-
" Shell script (Arch Linux) or PHP file (Drupal)
au BufNewFile,BufRead *.install
\ if getline(1) =~ '<?php' |
@@ -2232,8 +2236,11 @@ au BufNewFile,BufRead .reminders* call s:StarSetf('remind')
" SGML catalog file
au BufNewFile,BufRead sgml.catalog* call s:StarSetf('catalog')
+" avoid doc files being recognized a shell files
+au BufNewFile,BufRead */doc/{,.}bash[_-]completion{,.d,.sh}{,/*} setf text
+
" Shell scripts ending in a star
-au BufNewFile,BufRead .bashrc*,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,bash-fc[-.]*,,PKGBUILD* call dist#ft#SetFileTypeSH("bash")
+au BufNewFile,BufRead .bashrc*,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,bash-fc[-.]*,PKGBUILD*,APKBUILD*,*/{,.}bash[_-]completion{,.d,.sh}{,/*} call dist#ft#SetFileTypeSH("bash")
au BufNewFile,BufRead .kshrc* call dist#ft#SetFileTypeSH("ksh")
au BufNewFile,BufRead .profile* call dist#ft#SetFileTypeSH(getline(1))
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 563ffc479e..59b7180cf1 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -232,6 +232,12 @@ local function validate_client_config(config)
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 nil or a number with the debounce time in milliseconds"
+ )
local cmd, cmd_args = lsp._cmd_parts(config.cmd)
local offset_encoding = valid_encodings.UTF16
@@ -260,21 +266,165 @@ local function buf_get_full_text(bufnr)
end
--@private
+--- Memoizes a function. On first run, the function return value is saved and
+--- immediately returned on subsequent runs.
+---
+--@param fn (function) Function to run
+--@returns (function) Memoized function
+local function once(fn)
+ local value
+ return function(...)
+ if not value then value = fn(...) end
+ return value
+ end
+end
+
+
+local changetracking = {}
+do
+ --- client_id → state
+ ---
+ --- state
+ --- pending_change?: function that the timer starts to trigger didChange
+ --- pending_changes: list of tables with the pending changesets; for incremental_sync only
+ --- use_incremental_sync: bool
+ --- buffers?: table (bufnr → lines); for incremental sync only
+ --- timer?: uv_timer
+ local state_by_client = {}
+
+ function changetracking.init(client, bufnr)
+ local state = state_by_client[client.id]
+ if not state then
+ state = {
+ pending_changes = {};
+ use_incremental_sync = (
+ if_nil(client.config.flags.allow_incremental_sync, true)
+ and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental
+ );
+ }
+ state_by_client[client.id] = state
+ end
+ if not state.use_incremental_sync then
+ return
+ end
+ if not state.buffers then
+ state.buffers = {}
+ end
+ state.buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true)
+ end
+
+ function changetracking.reset_buf(client, bufnr)
+ local state = state_by_client[client.id]
+ if state then
+ changetracking._reset_timer(state)
+ if state.buffers then
+ state.buffers[bufnr] = nil
+ end
+ end
+ end
+
+ function changetracking.reset(client_id)
+ local state = state_by_client[client_id]
+ if state then
+ state_by_client[client_id] = nil
+ changetracking._reset_timer(state)
+ end
+ end
+
+ function changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
+ local incremental_changes = function(client)
+ local cached_buffers = state_by_client[client.id].buffers
+ local lines = nvim_buf_get_lines(bufnr, 0, -1, true)
+ local startline = math.min(firstline + 1, math.min(#cached_buffers[bufnr], #lines))
+ local endline = math.min(-(#lines - new_lastline), -1)
+ local incremental_change = vim.lsp.util.compute_diff(
+ cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or 'utf-16')
+ cached_buffers[bufnr] = lines
+ return incremental_change
+ end
+ local full_changes = once(function()
+ return {
+ text = buf_get_full_text(bufnr);
+ };
+ end)
+ local uri = vim.uri_from_bufnr(bufnr)
+ return function(client)
+ if client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.None then
+ return
+ end
+ local state = state_by_client[client.id]
+ local debounce = client.config.flags.debounce_text_changes
+ if not debounce then
+ local changes = state.use_incremental_sync and incremental_changes(client) or full_changes()
+ client.notify("textDocument/didChange", {
+ textDocument = {
+ uri = uri;
+ version = changedtick;
+ };
+ contentChanges = { changes, }
+ })
+ return
+ end
+ changetracking._reset_timer(state)
+ if state.use_incremental_sync then
+ -- This must be done immediately and cannot be delayed
+ -- The contents would further change and startline/endline may no longer fit
+ table.insert(state.pending_changes, incremental_changes(client))
+ end
+ state.pending_change = function()
+ state.pending_change = nil
+ if client.is_stopped() then
+ return
+ end
+ local contentChanges
+ if state.use_incremental_sync then
+ contentChanges = state.pending_changes
+ state.pending_changes = {}
+ else
+ contentChanges = { full_changes(), }
+ end
+ client.notify("textDocument/didChange", {
+ textDocument = {
+ uri = uri;
+ version = changedtick;
+ };
+ contentChanges = contentChanges
+ })
+ end
+ state.timer = vim.loop.new_timer()
+ -- Must use schedule_wrap because `full_changes()` calls nvim_buf_get_lines
+ state.timer:start(debounce, 0, vim.schedule_wrap(state.pending_change))
+ end
+ end
+
+ function changetracking._reset_timer(state)
+ if state.timer then
+ state.timer:stop()
+ state.timer:close()
+ state.timer = nil
+ end
+ end
+
+ --- Flushes any outstanding change notification.
+ function changetracking.flush(client)
+ local state = state_by_client[client.id]
+ if state then
+ changetracking._reset_timer(state)
+ if state.pending_change then
+ state.pending_change()
+ end
+ end
+ end
+end
+
+
+--@private
--- Default handler for the 'textDocument/didOpen' LSP notification.
---
--@param bufnr (Number) Number of the buffer, or 0 for current
--@param client Client object
local function text_document_did_open_handler(bufnr, client)
- local use_incremental_sync = (
- if_nil(client.config.flags.allow_incremental_sync, true)
- and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental
- )
- if use_incremental_sync then
- if not client._cached_buffers then
- client._cached_buffers = {}
- end
- client._cached_buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true)
- end
+ changetracking.init(client, bufnr)
if not client.resolved_capabilities.text_document_open_close then
return
end
@@ -469,6 +619,9 @@ end
--- server in the initialize request. Invalid/empty values will default to "off"
--@param flags: A table with flags for the client. The current (experimental) flags are:
--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
+--- - debounce_text_changes (number, default nil): Debounce didChange
+--- notifications to the server by the given number in milliseconds. No debounce
+--- occurs if nil
---
--@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
@@ -563,6 +716,7 @@ function lsp.start_client(config)
uninitialized_clients[client_id] = nil
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
+ changetracking.reset(client_id)
all_client_active_buffers[client_id] = nil
for _, client_ids in pairs(all_buffer_active_clients) do
client_ids[client_id] = nil
@@ -721,6 +875,9 @@ function lsp.start_client(config)
handler = resolve_handler(method)
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)
+
local _ = log.debug() and log.debug(log_prefix, "client.request", client_id, method, params, handler, bufnr)
return rpc.request(method, params, function(err, result)
handler(err, method, result, client_id, bufnr)
@@ -765,6 +922,7 @@ function lsp.start_client(config)
function client.stop(force)
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
+ changetracking.reset(client_id)
all_client_active_buffers[client_id] = nil
for _, client_ids in pairs(all_buffer_active_clients) do
client_ids[client_id] = nil
@@ -816,20 +974,6 @@ function lsp.start_client(config)
end
--@private
---- Memoizes a function. On first run, the function return value is saved and
---- immediately returned on subsequent runs.
----
---@param fn (function) Function to run
---@returns (function) Memoized function
-local function once(fn)
- local value
- return function(...)
- if not value then value = fn(...) end
- return value
- end
-end
-
---@private
--@fn text_document_did_change_handler(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size)
--- Notify all attached clients that a buffer has changed.
local text_document_did_change_handler
@@ -848,45 +992,9 @@ do
if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
return
end
-
util.buf_versions[bufnr] = changedtick
-
- local incremental_changes = function(client)
- local lines = nvim_buf_get_lines(bufnr, 0, -1, true)
- local startline = math.min(firstline + 1, math.min(#client._cached_buffers[bufnr], #lines))
- local endline = math.min(-(#lines - new_lastline), -1)
- local incremental_change = vim.lsp.util.compute_diff(
- client._cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or "utf-16")
- client._cached_buffers[bufnr] = lines
- return incremental_change
- end
-
- local full_changes = once(function()
- return {
- text = buf_get_full_text(bufnr);
- };
- end)
-
- local uri = vim.uri_from_bufnr(bufnr)
- for_each_buffer_client(bufnr, function(client)
- local allow_incremental_sync = if_nil(client.config.flags.allow_incremental_sync, true)
- local text_document_did_change = client.resolved_capabilities.text_document_did_change
- local changes
- if text_document_did_change == protocol.TextDocumentSyncKind.None then
- return
- elseif not allow_incremental_sync or text_document_did_change == protocol.TextDocumentSyncKind.Full then
- changes = full_changes(client)
- elseif text_document_did_change == protocol.TextDocumentSyncKind.Incremental then
- changes = incremental_changes(client)
- end
- client.notify("textDocument/didChange", {
- textDocument = {
- uri = uri;
- version = changedtick;
- };
- contentChanges = { changes; }
- })
- end)
+ local compute_change_and_notify = changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
+ for_each_buffer_client(bufnr, compute_change_and_notify)
end
end
@@ -956,9 +1064,7 @@ function lsp.buf_attach_client(bufnr, client_id)
if client.resolved_capabilities.text_document_open_close then
client.notify('textDocument/didClose', params)
end
- if client._cached_buffers then
- client._cached_buffers[bufnr] = nil
- end
+ changetracking.reset_buf(client, bufnr)
end)
util.buf_versions[bufnr] = nil
all_buffer_active_clients[bufnr] = nil
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 4e82c46fef..e6132e78bf 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1140,14 +1140,14 @@ function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
local message_lines = vim.split(diagnostic.message, '\n', true)
table.insert(lines, prefix..message_lines[1])
- table.insert(highlights, {#prefix + 1, hiname})
+ table.insert(highlights, {#prefix, hiname})
for j = 2, #message_lines do
table.insert(lines, message_lines[j])
table.insert(highlights, {0, hiname})
end
end
- local popup_bufnr, winnr = util.open_floating_preview(lines, 'plaintext')
+ local popup_bufnr, winnr = util.open_floating_preview(lines, 'plaintext', opts)
for i, hi in ipairs(highlights) do
local prefixlen, hiname = unpack(hi)
-- Start highlight after the prefix
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index eacbd90077..525ec4ce5b 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -245,9 +245,22 @@ M['textDocument/completion'] = function(_, _, result)
vim.fn.complete(textMatch+1, matches)
end
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
-M['textDocument/hover'] = function(_, method, result)
- util.focusable_float(method, function()
+--- |lsp-handler| for the method "textDocument/hover"
+--- <pre>
+--- vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(
+--- vim.lsp.handlers.hover, {
+--- -- Use a sharp border with `FloatBorder` highlights
+--- border = "single"
+--- }
+--- )
+--- </pre>
+---@param config table Configuration table.
+--- - border: (default=nil)
+--- - Add borders to the floating window
+--- - See |vim.api.nvim_open_win()|
+function M.hover(_, method, result, _, _, config)
+ config = config or {}
+ local bufnr, winnr = util.focusable_float(method, function()
if not (result and result.contents) then
-- return { 'No information available' }
return
@@ -259,13 +272,17 @@ M['textDocument/hover'] = function(_, method, result)
return
end
local bufnr, winnr = util.fancy_floating_markdown(markdown_lines, {
- pad_left = 1; pad_right = 1;
+ border = config.border
})
util.close_preview_autocmd({"CursorMoved", "BufHidden", "InsertCharPre"}, winnr)
return bufnr, winnr
end)
+ return bufnr, winnr
end
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
+M['textDocument/hover'] = M.hover
+
--@private
--- Jumps to a location. Used as a handler for multiple LSP methods.
--@param _ (not used)
@@ -303,8 +320,21 @@ M['textDocument/typeDefinition'] = location_handler
--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation
M['textDocument/implementation'] = location_handler
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
-M['textDocument/signatureHelp'] = function(_, method, result, _, bufnr)
+--- |lsp-handler| for the method "textDocument/signatureHelp"
+--- <pre>
+--- vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(
+--- vim.lsp.handlers.signature_help, {
+--- -- Use a sharp border with `FloatBorder` highlights
+--- border = "single"
+--- }
+--- )
+--- </pre>
+---@param config table Configuration table.
+--- - border: (default=nil)
+--- - Add borders to the floating window
+--- - See |vim.api.nvim_open_win()|
+function M.signature_help(_, method, result, _, bufnr, config)
+ config = config or {}
-- When use `autocmd CompleteDone <silent><buffer> lua vim.lsp.buf.signature_help()` to call signatureHelp handler
-- If the completion item doesn't have signatures It will make noise. Change to use `print` that can use `<silent>` to ignore
if not (result and result.signatures and result.signatures[1]) then
@@ -319,11 +349,14 @@ M['textDocument/signatureHelp'] = function(_, method, result, _, bufnr)
end
local syntax = api.nvim_buf_get_option(bufnr, 'syntax')
local p_bufnr, _ = util.focusable_preview(method, function()
- return lines, util.try_trim_markdown_code_blocks(lines)
+ return lines, util.try_trim_markdown_code_blocks(lines), config
end)
api.nvim_buf_set_option(p_bufnr, 'syntax', syntax)
end
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
+M['textDocument/signatureHelp'] = M.signature_help
+
--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight
M['textDocument/documentHighlight'] = function(_, _, result, _, bufnr, _)
if not result then return end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index ec1131ae1f..325dc044be 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -18,6 +18,40 @@ end
local M = {}
+local default_border = {
+ {"", "NormalFloat"},
+ {"", "NormalFloat"},
+ {"", "NormalFloat"},
+ {" ", "NormalFloat"},
+ {"", "NormalFloat"},
+ {"", "NormalFloat"},
+ {"", "NormalFloat"},
+ {" ", "NormalFloat"},
+}
+
+--@private
+-- Check the border given by opts or the default border for the additional
+-- size it adds to a float.
+--@returns size of border in height and width
+local function get_border_size(opts)
+ local border = opts and opts.border or default_border
+ local height = 0
+ local width = 0
+
+ if type(border) == 'string' then
+ -- 'single', 'double', etc.
+ height = 2
+ width = 2
+ else
+ height = height + vim.fn.strdisplaywidth(border[2][1]) -- top
+ height = height + vim.fn.strdisplaywidth(border[6][1]) -- bottom
+ width = width + vim.fn.strdisplaywidth(border[4][1]) -- right
+ width = width + vim.fn.strdisplaywidth(border[8][1]) -- left
+ end
+
+ return { height = height, width = width }
+end
+
--@private
local function split_lines(value)
return split(value, '\n', true)
@@ -856,7 +890,7 @@ function M.make_floating_popup_options(width, height, opts)
else
anchor = anchor..'S'
height = math.min(lines_above, height)
- row = 0
+ row = -get_border_size(opts).height
end
if vim.fn.wincol() + width <= api.nvim_get_option('columns') then
@@ -875,6 +909,7 @@ function M.make_floating_popup_options(width, height, opts)
row = row + (opts.offset_y or 0),
style = 'minimal',
width = width,
+ border = opts.border or default_border,
}
end
@@ -981,27 +1016,20 @@ function M.focusable_preview(unique_name, fn)
end)
end
---- Trims empty lines from input and pad left and right with spaces
+--- Trims empty lines from input and pad top and bottom with empty lines
---
---@param contents table of lines to trim and pad
---@param opts dictionary with optional fields
---- - pad_left number of columns to pad contents at left (default 1)
---- - pad_right number of columns to pad contents at right (default 1)
--- - pad_top number of lines to pad contents at top (default 0)
--- - pad_bottom number of lines to pad contents at bottom (default 0)
---@return contents table of trimmed and padded lines
-function M._trim_and_pad(contents, opts)
+function M._trim(contents, opts)
validate {
contents = { contents, 't' };
opts = { opts, 't', true };
}
opts = opts or {}
- local left_padding = (" "):rep(opts.pad_left or 1)
- local right_padding = (" "):rep(opts.pad_right or 1)
contents = M.trim_empty_lines(contents)
- for i, line in ipairs(contents) do
- contents[i] = string.format('%s%s%s', left_padding, line:gsub("\r", ""), right_padding)
- end
if opts.pad_top then
for _ = 1, opts.pad_top do
table.insert(contents, 1, "")
@@ -1078,8 +1106,8 @@ function M.fancy_floating_markdown(contents, opts)
end
end
end
- -- Clean up and add padding
- stripped = M._trim_and_pad(stripped, opts)
+ -- Clean up
+ stripped = M._trim(stripped, opts)
-- 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))
@@ -1182,6 +1210,20 @@ function M._make_floating_popup_size(contents, opts)
width = math.max(line_widths[i], width)
end
end
+
+ local border_width = get_border_size(opts).width
+ local screen_width = api.nvim_win_get_width(0)
+ width = math.min(width, screen_width)
+
+ -- make sure borders are always inside the screen
+ if width + border_width > screen_width then
+ width = width - (width + border_width - screen_width)
+ end
+
+ if wrap_at > width then
+ wrap_at = width
+ end
+
if max_width then
width = math.min(width, max_width)
wrap_at = math.min(wrap_at or max_width, max_width)
@@ -1235,7 +1277,7 @@ function M.open_floating_preview(contents, syntax, opts)
opts = opts or {}
-- Clean up input: trim empty lines from the end, pad
- contents = M._trim_and_pad(contents, opts)
+ contents = M._trim(contents, opts)
-- 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))
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index cac0ab864b..f223c7b8c8 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -17,6 +17,9 @@ setmetatable(M, {
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]
end
end
})
diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua
new file mode 100644
index 0000000000..dd0b11a6c7
--- /dev/null
+++ b/runtime/lua/vim/treesitter/health.lua
@@ -0,0 +1,34 @@
+local M = {}
+local ts = vim.treesitter
+
+function M.list_parsers()
+ return vim.api.nvim_get_runtime_file('parser/*', true)
+end
+
+function M.check_health()
+ local report_info = vim.fn['health#report_info']
+ local report_ok = vim.fn['health#report_ok']
+ local report_error = vim.fn['health#report_error']
+ local parsers = M.list_parsers()
+
+ 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 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))
+ 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))
+ else
+ report_error(string.format("Unable to load parser for %s", parsername))
+ end
+ end
+end
+
+return M
+
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 79a88c5dbb..ed5146be44 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -22,6 +22,16 @@ local function dedupe_files(files)
return result
end
+local function safe_read(filename, read_quantifier)
+ local file, err = io.open(filename, 'r')
+ if not file then
+ error(err)
+ end
+ local content = file:read(read_quantifier)
+ io.close(file)
+ return content
+end
+
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))
@@ -38,7 +48,7 @@ function M.get_query_files(lang, query_name, is_included)
local MODELINE_FORMAT = "^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$"
for _, file in ipairs(lang_files) do
- local modeline = io.open(file, 'r'):read('*l')
+ local modeline = safe_read(file, '*l')
if modeline then
local langlist = modeline:match(MODELINE_FORMAT)
@@ -73,7 +83,7 @@ local function read_query_files(filenames)
local contents = {}
for _,filename in ipairs(filenames) do
- table.insert(contents, io.open(filename, 'r'):read('*a'))
+ table.insert(contents, safe_read(filename, '*a'))
end
return table.concat(contents, '')
diff --git a/runtime/menu.vim b/runtime/menu.vim
index cd56eb5583..78306a57b8 100644
--- a/runtime/menu.vim
+++ b/runtime/menu.vim
@@ -2,7 +2,7 @@
" You can also use this as a start for your own set of menus.
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2019 Jan 27
+" Last Change: 2019 Dec 10
" Note that ":an" (short for ":anoremenu") is often used to make a menu work
" in all modes and avoid side effects from mappings defined by the user.
@@ -690,11 +690,11 @@ func! s:BMShow(...)
let g:bmenu_priority = a:1
endif
- " remove old menu, if exists; keep one entry to avoid a torn off menu to
- " disappear.
- silent! unmenu &Buffers
+ " Remove old menu, if exists; keep one entry to avoid a torn off menu to
+ " disappear. Use try/catch to avoid setting v:errmsg
+ try | unmenu &Buffers | catch | endtry
exe 'noremenu ' . g:bmenu_priority . ".1 &Buffers.Dummy l"
- silent! unmenu! &Buffers
+ try | unmenu! &Buffers | catch | endtry
" create new menu; set 'cpo' to include the <CR>
let cpo_save = &cpo