mirror of
https://github.com/neovim/neovim
synced 2025-07-22 14:21:58 +00:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
5b839ced69 | |||
844872cc0a | |||
0e96f7d04c | |||
1cc63abf4a | |||
9f51da3442 | |||
857678c2ec | |||
03bd9147f0 | |||
ee9e3420fd | |||
7b60ec79ea | |||
14357c83c5 | |||
571609fb89 | |||
37a00be7c0 | |||
09306f07c4 | |||
ec101b9fd9 | |||
222d1414dc | |||
7f4fa077cd | |||
00889948dd | |||
1bb861c7a1 | |||
d547d874af | |||
060eeaa14c | |||
9dae939b1f | |||
8c6a4fab66 | |||
1b54344c11 | |||
8f68548384 | |||
25da2430f9 | |||
93f1ec0a59 | |||
5c8e5432c0 | |||
e86997a812 | |||
a0ebba7052 | |||
ae249d81fb | |||
785baceaee | |||
aa0ddc6690 | |||
2cd272decb | |||
08ddfa9851 | |||
beac24d6f3 | |||
5dcf2c77a9 | |||
ce4c8010cc | |||
270f71b571 | |||
3c0f239c3e | |||
1d32521135 | |||
bd057d4b40 | |||
096f8418c5 | |||
84784a8391 | |||
fb11ef0aad | |||
faf3159ab0 | |||
a4699892af |
4
.github/workflows/api-docs.yml
vendored
4
.github/workflows/api-docs.yml
vendored
@ -26,7 +26,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y doxygen python3 python3-msgpack luajit
|
||||
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y python3 luajit
|
||||
conda install -c conda-forge doxygen=1.9.2 msgpack-python
|
||||
echo "$CONDA/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Setup git config
|
||||
run: |
|
||||
|
@ -137,7 +137,7 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
||||
# version string, else they are combined with the result of `git describe`.
|
||||
set(NVIM_VERSION_MAJOR 0)
|
||||
set(NVIM_VERSION_MINOR 6)
|
||||
set(NVIM_VERSION_PATCH 0)
|
||||
set(NVIM_VERSION_PATCH 1)
|
||||
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
|
||||
|
||||
# API level
|
||||
|
@ -46,6 +46,10 @@ if(DEFINED ENV{TEST_FILTER} AND NOT "$ENV{TEST_FILTER}" STREQUAL "")
|
||||
list(APPEND BUSTED_ARGS --filter $ENV{TEST_FILTER})
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{TEST_FILTER_OUT} AND NOT "$ENV{TEST_FILTER_OUT}" STREQUAL "")
|
||||
list(APPEND BUSTED_ARGS --filter-out $ENV{TEST_FILTER_OUT})
|
||||
endif()
|
||||
|
||||
# TMPDIR: use relative test path (for parallel test runs / isolation).
|
||||
set(ENV{TMPDIR} "${BUILD_DIR}/Xtest_tmpdir/${TEST_PATH}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{TMPDIR})
|
||||
|
@ -1,27 +1,3 @@
|
||||
function! s:enhance_syntax() abort
|
||||
syntax case match
|
||||
|
||||
syntax keyword healthError ERROR[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default link healthError Error
|
||||
|
||||
syntax keyword healthWarning WARNING[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default link healthWarning WarningMsg
|
||||
|
||||
syntax keyword healthSuccess OK[:]
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
highlight default healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
||||
|
||||
syntax match healthHelp "|.\{-}|" contains=healthBar
|
||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||
syntax match healthBar "|" contained conceal
|
||||
highlight default link healthHelp Identifier
|
||||
|
||||
" We do not care about markdown syntax errors in :checkhealth output.
|
||||
highlight! link markdownError Normal
|
||||
endfunction
|
||||
|
||||
" Runs the specified healthchecks.
|
||||
" Runs all discovered healthchecks if a:plugin_names is empty.
|
||||
function! health#check(plugin_names) abort
|
||||
@ -29,13 +5,9 @@ function! health#check(plugin_names) abort
|
||||
\ ? s:discover_healthchecks()
|
||||
\ : s:get_healthcheck(a:plugin_names)
|
||||
|
||||
tabnew
|
||||
setlocal wrap breakindent linebreak
|
||||
setlocal filetype=markdown
|
||||
setlocal conceallevel=2 concealcursor=nc
|
||||
setlocal keywordprg=:help
|
||||
let &l:iskeyword='!-~,^*,^|,^",192-255'
|
||||
call s:enhance_syntax()
|
||||
" create scratch-buffer
|
||||
execute 'tab sbuffer' nvim_create_buf(v:true, v:true)
|
||||
setfiletype checkhealth
|
||||
|
||||
if empty(healthchecks)
|
||||
call setline(1, 'ERROR: No healthchecks found.')
|
||||
@ -70,8 +42,6 @@ function! health#check(plugin_names) abort
|
||||
|
||||
" needed for plasticboy/vim-markdown, because it uses fdm=expr
|
||||
normal! zR
|
||||
setlocal nomodified
|
||||
setlocal bufhidden=hide
|
||||
redraw|echo ''
|
||||
endfunction
|
||||
|
||||
|
@ -523,7 +523,7 @@ function! s:check_virtualenv() abort
|
||||
let hint = '$PATH ambiguities in subshells typically are '
|
||||
\.'caused by your shell config overriding the $PATH previously set by the '
|
||||
\.'virtualenv. Either prevent them from doing so, or use this workaround: '
|
||||
\.'https://vi.stackexchange.com/a/7654'
|
||||
\.'https://vi.stackexchange.com/a/34996'
|
||||
let hints[hint] = v:true
|
||||
endif
|
||||
endfor
|
||||
|
@ -361,7 +361,7 @@ UTF-32 and UTF-16 sizes of the deleted region is also passed as additional
|
||||
arguments {old_utf32_size} and {old_utf16_size}.
|
||||
|
||||
"on_changedtick" is invoked when |b:changedtick| was incremented but no text
|
||||
was changed. The parameters recieved are ("changedtick", {buf}, {changedtick}).
|
||||
was changed. The parameters received are ("changedtick", {buf}, {changedtick}).
|
||||
|
||||
*api-lua-detach*
|
||||
In-process Lua callbacks can detach by returning `true`. This will detach all
|
||||
@ -634,7 +634,7 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
|
||||
atomically, i.e. without interleaving redraws, RPC requests
|
||||
from other clients, or user interactions (however API
|
||||
methods may trigger autocommands or event processing which
|
||||
have such side-effects, e.g. |:sleep| may wake timers).
|
||||
have such side effects, e.g. |:sleep| may wake timers).
|
||||
2. To minimize RPC overhead (roundtrips) of a sequence of many
|
||||
requests.
|
||||
|
||||
@ -698,7 +698,7 @@ nvim_del_keymap({mode}, {lhs}) *nvim_del_keymap()*
|
||||
|nvim_set_keymap()|
|
||||
|
||||
nvim_del_mark({name}) *nvim_del_mark()*
|
||||
Deletes a uppercase/file named mark. See |mark-motions|.
|
||||
Deletes an uppercase/file named mark. See |mark-motions|.
|
||||
|
||||
Note:
|
||||
fails with error if a lowercase or buffer local named mark
|
||||
@ -2353,7 +2353,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
|
||||
|api-indexing|
|
||||
{opts} Optional parameters.
|
||||
• id : id of the extmark to edit.
|
||||
• end_line : ending line of the mark, 0-based
|
||||
• end_row : ending line of the mark, 0-based
|
||||
inclusive.
|
||||
• end_col : ending col of the mark, 0-based
|
||||
exclusive.
|
||||
@ -2655,7 +2655,7 @@ nvim_win_is_valid({window}) *nvim_win_is_valid()*
|
||||
true if the window is valid, false otherwise
|
||||
|
||||
nvim_win_set_buf({window}, {buffer}) *nvim_win_set_buf()*
|
||||
Sets the current buffer in a window, without side-effects
|
||||
Sets the current buffer in a window, without side effects
|
||||
|
||||
Attributes: ~
|
||||
not allowed when |textlock| is active
|
||||
|
@ -130,7 +130,7 @@ with |vim.notify()|: >
|
||||
In this example, there is nothing to do when diagnostics are hidden, so we
|
||||
omit the "hide" function.
|
||||
|
||||
Existing handlers can be overriden. For example, use the following to only
|
||||
Existing handlers can be overridden. For example, use the following to only
|
||||
show a sign for the highest severity diagnostic on a given line: >
|
||||
|
||||
-- Create a custom namespace. This will aggregate signs from all other
|
||||
@ -175,8 +175,9 @@ All highlights defined for diagnostics begin with `Diagnostic` followed by
|
||||
the type of highlight (e.g., `Sign`, `Underline`, etc.) and the severity (e.g.
|
||||
`Error`, `Warn`, etc.)
|
||||
|
||||
Sign, underline and virtual text highlights (by default) are linked to their
|
||||
corresponding default highlight.
|
||||
By default, highlights for signs, floating windows, and virtual text are linked to the
|
||||
corresponding default highlight. Underline highlights are not linked and use their
|
||||
own default highlight groups.
|
||||
|
||||
For example, the default highlighting for |hl-DiagnosticSignError| is linked
|
||||
to |hl-DiagnosticError|. To change the default (and therefore the linked
|
||||
@ -296,7 +297,6 @@ Example: >
|
||||
autocmd DiagnosticChanged * lua vim.diagnostic.setqflist({open = false })
|
||||
<
|
||||
==============================================================================
|
||||
==============================================================================
|
||||
Lua module: vim.diagnostic *diagnostic-api*
|
||||
|
||||
config({opts}, {namespace}) *vim.diagnostic.config()*
|
||||
@ -341,13 +341,24 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
|
||||
|diagnostic-severity|
|
||||
|
||||
• virtual_text: (default true) Use virtual
|
||||
text for diagnostics. Options:
|
||||
text for diagnostics. If multiple
|
||||
diagnostics are set for a namespace, one
|
||||
prefix per diagnostic + the last diagnostic
|
||||
message are shown. Options:
|
||||
• severity: Only show virtual text for
|
||||
diagnostics matching the given severity
|
||||
|diagnostic-severity|
|
||||
• source: (string) Include the diagnostic
|
||||
source in virtual text. One of "always"
|
||||
or "if_many".
|
||||
• source: (boolean or string) Include the
|
||||
diagnostic source in virtual text. Use
|
||||
"if_many" to only show sources if there
|
||||
is more than one diagnostic source in the
|
||||
buffer. Otherwise, any truthy value means
|
||||
to always show the diagnostic source.
|
||||
• spacing: (number) Amount of empty spaces
|
||||
inserted at the beginning of the virtual
|
||||
text.
|
||||
• prefix: (string) Prepend diagnostic
|
||||
message with prefix.
|
||||
• format: (function) A function that takes
|
||||
a diagnostic as input and returns a
|
||||
string. The return value is the text used
|
||||
@ -574,21 +585,24 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
|
||||
diagnostic |diagnostic-structure| or `nil` if {pat} fails
|
||||
to match {str}.
|
||||
|
||||
open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
|
||||
open_float({opts}, {...}) *vim.diagnostic.open_float()*
|
||||
Show diagnostics in a floating window.
|
||||
|
||||
Parameters: ~
|
||||
{bufnr} number|nil Buffer number. Defaults to the current
|
||||
buffer.
|
||||
{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
|
||||
diagnostics from. Defaults to the current
|
||||
buffer.
|
||||
• namespace: (number) Limit diagnostics to the
|
||||
given namespace
|
||||
• scope: (string, default "line") Show
|
||||
diagnostics from the whole buffer ("buffer"),
|
||||
the current cursor line ("line"), or the
|
||||
current cursor position ("cursor").
|
||||
• scope: (string, default "line") Show diagnostics
|
||||
from the whole buffer ("buffer"), the current
|
||||
cursor line ("line"), or the current cursor
|
||||
position ("cursor"). Shorthand versions are also
|
||||
accepted ("c" for "cursor", "l" for "line", "b"
|
||||
for "buffer").
|
||||
• pos: (number or table) If {scope} is "line" or
|
||||
"cursor", use this position rather than the
|
||||
cursor position. If a number, interpreted as a
|
||||
@ -603,17 +617,20 @@ open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
|
||||
is interpreted as a [text, hl_group] tuple.
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• source: (string) Include the diagnostic source
|
||||
in the message. One of "always" or "if_many".
|
||||
Overrides the setting from
|
||||
• source: (boolean or string) Include the
|
||||
diagnostic source in the message. Use "if_many"
|
||||
to only show sources if there is more than one
|
||||
source of diagnostics in the buffer. Otherwise,
|
||||
any truthy value means to always show the
|
||||
diagnostic source. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• format: (function) A function that takes a
|
||||
diagnostic as input and returns a string. The
|
||||
return value is the text used to display the
|
||||
diagnostic. Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
• prefix: (function, string, or table) Prefix
|
||||
each diagnostic in the floating window. If a
|
||||
• prefix: (function, string, or table) Prefix each
|
||||
diagnostic in the floating window. If a
|
||||
function, it must have the signature
|
||||
(diagnostic, i, total) -> (string, string),
|
||||
where {i} is the index of the diagnostic being
|
||||
@ -621,13 +638,13 @@ open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
|
||||
diagnostics displayed in the window. The
|
||||
function should return a string which is
|
||||
prepended to each diagnostic in the window as
|
||||
well as an (optional) highlight group which
|
||||
will be used to highlight the prefix. If
|
||||
{prefix} is a table, it is interpreted as a
|
||||
[text, hl_group] tuple as in |nvim_echo()|;
|
||||
otherwise, if {prefix} is a string, it is
|
||||
prepended to each diagnostic in the window with
|
||||
no highlight. Overrides the setting from
|
||||
well as an (optional) highlight group which will
|
||||
be used to highlight the prefix. If {prefix} is
|
||||
a table, it is interpreted as a [text, hl_group]
|
||||
tuple as in |nvim_echo()|; otherwise, if
|
||||
{prefix} is a string, it is prepended to each
|
||||
diagnostic in the window with no highlight.
|
||||
Overrides the setting from
|
||||
|vim.diagnostic.config()|.
|
||||
|
||||
Return: ~
|
||||
|
@ -93,6 +93,7 @@ REFERENCE MANUAL: These files explain every detail of Vim. *reference_toc*
|
||||
|
||||
General subjects ~
|
||||
|intro.txt| general introduction to Vim; notation used in help files
|
||||
|nvim.txt| Transitioning from Vim
|
||||
|help.txt| overview and quick reference (this file)
|
||||
|helphelp.txt| about using the help files
|
||||
|index.txt| alphabetical index of all commands
|
||||
@ -135,15 +136,17 @@ Advanced editing ~
|
||||
Special issues ~
|
||||
|testing.txt| testing Vim and Vim scripts
|
||||
|print.txt| printing
|
||||
|remote.txt| using Vim as a server or client
|
||||
|remote_plugin.txt| Nvim support for remote plugins
|
||||
|
||||
Programming language support ~
|
||||
|indent.txt| automatic indenting for C and other languages
|
||||
|lsp.txt| Language Server Protocol (LSP)
|
||||
|treesitter.txt| tree-sitter library for incremental parsing of buffers
|
||||
|diagnostic.txt| Diagnostic framework
|
||||
|syntax.txt| syntax highlighting
|
||||
|filetype.txt| settings done specifically for a type of file
|
||||
|quickfix.txt| commands for a quick edit-compile-fix cycle
|
||||
|provider.txt| Built-in remote plugin hosts
|
||||
|ft_ada.txt| Ada (the programming language) support
|
||||
|ft_ps1.txt| Filetype plugin for Windows PowerShell
|
||||
|ft_raku.txt| Filetype plugin for Raku
|
||||
@ -164,6 +167,7 @@ GUI ~
|
||||
|
||||
Interfaces ~
|
||||
|if_cscop.txt| using Cscope with Vim
|
||||
|if_perl.txt| Perl interface
|
||||
|if_pyth.txt| Python interface
|
||||
|if_ruby.txt| Ruby interface
|
||||
|sign.txt| debugging signs
|
||||
@ -171,6 +175,16 @@ Interfaces ~
|
||||
Versions ~
|
||||
|vim_diff.txt| Main differences between Nvim and Vim
|
||||
|vi_diff.txt| Main differences between Vim and Vi
|
||||
|deprecated.txt| Deprecated items that have been or will be removed
|
||||
|
||||
Other ~
|
||||
|terminal_emulator.txt| Terminal buffers
|
||||
|term.txt| Terminal UI
|
||||
|ui.txt| Nvim UI protocol
|
||||
|channel.txt| Nvim asynchronous IO
|
||||
|dev_style.txt| Nvim style guide
|
||||
|job_control.txt| Spawn and control multiple processes
|
||||
|
||||
*standard-plugin-list*
|
||||
Standard plugins ~
|
||||
|matchit.txt| Extended |%| matching
|
||||
|
@ -214,7 +214,7 @@ For |lsp-request|, each |lsp-handler| has this signature: >
|
||||
request, a table with information about the error
|
||||
is sent. Otherwise, it is `nil`. See |lsp-response|.
|
||||
{result} (Result | Params | nil)
|
||||
When the language server is able to succesfully
|
||||
When the language server is able to successfully
|
||||
complete a request, this contains the `result` key
|
||||
of the response. See |lsp-response|.
|
||||
{ctx} (table)
|
||||
@ -236,7 +236,7 @@ For |lsp-request|, each |lsp-handler| has this signature: >
|
||||
{config} (table)
|
||||
Configuration for the handler.
|
||||
|
||||
Each handler can define it's own configuration
|
||||
Each handler can define its own configuration
|
||||
table that allows users to customize the behavior
|
||||
of a particular handler.
|
||||
|
||||
@ -274,7 +274,7 @@ For |lsp-notification|, each |lsp-handler| has this signature: >
|
||||
{config} (table)
|
||||
Configuration for the handler.
|
||||
|
||||
Each handler can define it's own configuration
|
||||
Each handler can define its own configuration
|
||||
table that allows users to customize the behavior
|
||||
of a particular handler.
|
||||
|
||||
@ -369,7 +369,7 @@ Handlers can be set by:
|
||||
For example: >
|
||||
|
||||
vim.lsp.start_client {
|
||||
..., -- Other configuration ommitted.
|
||||
..., -- Other configuration omitted.
|
||||
handlers = {
|
||||
["textDocument/definition"] = my_custom_server_definition
|
||||
},
|
||||
@ -394,6 +394,9 @@ in the following order:
|
||||
2. Handler defined in |vim.lsp.start_client()|, if any.
|
||||
3. Handler defined in |vim.lsp.handlers|, if any.
|
||||
|
||||
*vim.lsp.log_levels*
|
||||
Log levels are defined in |vim.log.levels|
|
||||
|
||||
|
||||
VIM.LSP.PROTOCOL *vim.lsp.protocol*
|
||||
|
||||
@ -444,7 +447,7 @@ LspCodeLens
|
||||
|nvim_buf_set_extmark()|.
|
||||
|
||||
LspCodeLensSeparator *hl-LspCodeLensSeparator*
|
||||
Used to color the seperator between two or more code lens.
|
||||
Used to color the separator between two or more code lens.
|
||||
|
||||
*lsp-highlight-signature*
|
||||
|
||||
@ -819,10 +822,10 @@ start_client({config}) *vim.lsp.start_client()*
|
||||
throws an error. `code` is a number
|
||||
describing the error. Other arguments
|
||||
may be passed depending on the error
|
||||
kind. See |vim.lsp.client_errors| for
|
||||
possible errors. Use
|
||||
`vim.lsp.client_errors[code]` to get
|
||||
human-friendly name.
|
||||
kind. See |vim.lsp.rpc.client_errors|
|
||||
for possible errors. Use
|
||||
`vim.lsp.rpc.client_errors[code]` to
|
||||
get human-friendly name.
|
||||
{before_init} Callback with parameters
|
||||
(initialize_params, config) invoked
|
||||
before the LSP "initialize" phase,
|
||||
@ -1285,7 +1288,7 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
|
||||
{config} table Configuration table.
|
||||
• border: (default=nil)
|
||||
• Add borders to the floating window
|
||||
• See |vim.api.nvim_open_win()|
|
||||
• See |nvim_open_win()|
|
||||
|
||||
*vim.lsp.handlers.signature_help()*
|
||||
signature_help({_}, {result}, {ctx}, {config})
|
||||
@ -1377,18 +1380,6 @@ character_offset({bufnr}, {row}, {col})
|
||||
(number, number) UTF-32 and UTF-16 index of the character
|
||||
in line {row} column {col} in buffer {buf}
|
||||
|
||||
*vim.lsp.util.close_preview_autocmd()*
|
||||
close_preview_autocmd({events}, {winnr})
|
||||
Creates autocommands to close a preview window when events
|
||||
happen.
|
||||
|
||||
Parameters: ~
|
||||
{events} (table) list of events
|
||||
{winnr} (number) window id of preview window
|
||||
|
||||
See also: ~
|
||||
|autocmd-events|
|
||||
|
||||
*vim.lsp.util.convert_input_to_markdown_lines()*
|
||||
convert_input_to_markdown_lines({input}, {contents})
|
||||
Converts any of `MarkedString` | `MarkedString[]` |
|
||||
@ -1909,14 +1900,14 @@ make_client_capabilities()
|
||||
|
||||
*vim.lsp.protocol.resolve_capabilities()*
|
||||
resolve_capabilities({server_capabilities})
|
||||
`*` to match one or more characters in a path segment `?` to
|
||||
match on one character in a path segment `**` to match any
|
||||
number of path segments, including none `{}` to group
|
||||
conditions (e.g. `**/*.{ts,js}` matches all TypeScript and
|
||||
JavaScript files) `[]` to declare a range of characters to
|
||||
match in a path segment (e.g., `example.[0-9]` to match on
|
||||
`example.0` , `example.1` , …) `[!...]` to negate a range of
|
||||
characters to match in a path segment (e.g., `example.[!0-9]`
|
||||
to match on `example.a` , `example.b` , but not `example.0` )
|
||||
Creates a normalized object describing LSP server
|
||||
capabilities.
|
||||
|
||||
Parameters: ~
|
||||
{server_capabilities} table Table of capabilities
|
||||
supported by the server
|
||||
|
||||
Return: ~
|
||||
table Normalized table of capabilities
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -759,9 +759,9 @@ vim.stricmp({a}, {b}) *vim.stricmp()*
|
||||
respectively.
|
||||
|
||||
vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
|
||||
Convert byte index to UTF-32 and UTF-16 indicies. If {index} is not
|
||||
supplied, the length of the string is used. All indicies are zero-based.
|
||||
Returns two values: the UTF-32 and UTF-16 indicies respectively.
|
||||
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.
|
||||
|
||||
Embedded NUL bytes are treated as terminating the string. Invalid
|
||||
UTF-8 bytes, and embedded surrogates are counted as one code
|
||||
@ -881,6 +881,15 @@ vim.types *vim.types*
|
||||
`vim.types.dictionary` will not change or that `vim.types` table will
|
||||
only contain values for these three types.
|
||||
|
||||
*log_levels* *vim.log.levels*
|
||||
Log levels are one of the values defined in `vim.log.levels`:
|
||||
|
||||
vim.log.levels.DEBUG
|
||||
vim.log.levels.ERROR
|
||||
vim.log.levels.INFO
|
||||
vim.log.levels.TRACE
|
||||
vim.log.levels.WARN
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LUA-VIMSCRIPT BRIDGE *lua-vimscript*
|
||||
|
||||
|
@ -90,7 +90,7 @@ Mouse input has the following behavior:
|
||||
- If another window is clicked, terminal focus will be lost and nvim will jump
|
||||
to the clicked window
|
||||
- If the mouse wheel is used while the mouse is positioned in another window,
|
||||
the terminal wont lose focus and the hovered window will be scrolled.
|
||||
the terminal won't lose focus and the hovered window will be scrolled.
|
||||
|
||||
==============================================================================
|
||||
Configuration *terminal-config*
|
||||
@ -426,7 +426,7 @@ When 'background' is "dark":
|
||||
hi debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||
|
||||
|
||||
Shorcuts *termdebug_shortcuts*
|
||||
Shortcuts *termdebug_shortcuts*
|
||||
|
||||
You can define your own shortcuts (mappings) to control gdb, that can work in
|
||||
any window, using the TermDebugSendCommand() function. Example: >
|
||||
|
@ -3226,10 +3226,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'inccommand' 'icm' string (default "nosplit")
|
||||
global
|
||||
|
||||
"nosplit": Shows the effects of a command incrementally, as you type.
|
||||
"split" : Also shows partial off-screen results in a preview window.
|
||||
When nonempty, shows the effects of |:substitute|, |:smagic|, and
|
||||
|:snomagic| as you type.
|
||||
|
||||
Works for |:substitute|, |:smagic|, |:snomagic|. |hl-Substitute|
|
||||
Possible values:
|
||||
nosplit Shows the effects of a command incrementally in the
|
||||
buffer.
|
||||
split Like "nosplit", but also shows partial off-screen
|
||||
results in a preview window.
|
||||
|
||||
If the preview is too slow (exceeds 'redrawtime') then 'inccommand' is
|
||||
automatically disabled until |Command-line-mode| is done.
|
||||
|
@ -100,7 +100,7 @@ tsnode:prev_named_sibling() *tsnode:prev_named_sibling()*
|
||||
|
||||
tsnode:iter_children() *tsnode:iter_children()*
|
||||
Iterates over all the direct children of {tsnode}, regardless of
|
||||
wether they are named or not.
|
||||
whether they are named or not.
|
||||
Returns the child node plus the eventual field name corresponding to
|
||||
this child node.
|
||||
|
||||
@ -155,9 +155,9 @@ tsnode:sexpr() *tsnode:sexpr()*
|
||||
Get an S-expression representing the node as a string.
|
||||
|
||||
tsnode:id() *tsnode:id()*
|
||||
Get an unique identier for the node inside its own tree.
|
||||
Get an unique identifier for the node inside its own tree.
|
||||
|
||||
No guarantees are made about this identifer's internal representation,
|
||||
No guarantees are made about this identifier's internal representation,
|
||||
except for being a primitive lua type with value equality (so not a table).
|
||||
Presently it is a (non-printable) string.
|
||||
|
||||
@ -195,7 +195,7 @@ to a match.
|
||||
Treesitter Query Predicates *lua-treesitter-predicates*
|
||||
|
||||
When writing queries for treesitter, one might use `predicates`, that is,
|
||||
special scheme nodes that are evaluted to verify things on a captured node for
|
||||
special scheme nodes that are evaluated to verify things on a captured node for
|
||||
example, the |eq?| predicate : >
|
||||
((identifier) @foo (#eq? @foo "foo"))
|
||||
|
||||
@ -203,7 +203,7 @@ This will only match identifier corresponding to the `"foo"` text.
|
||||
Here is a list of built-in predicates :
|
||||
|
||||
`eq?` *ts-predicate-eq?*
|
||||
This predicate will check text correspondance between nodes or
|
||||
This predicate will check text correspondence between nodes or
|
||||
strings : >
|
||||
((identifier) @foo (#eq? @foo "foo"))
|
||||
((node1) @left (node2) @right (#eq? @left @right))
|
||||
@ -212,7 +212,7 @@ Here is a list of built-in predicates :
|
||||
`vim-match?` *ts-predicate-vim-match?*
|
||||
This will match if the provived vim regex matches the text
|
||||
corresponding to a node : >
|
||||
((idenfitier) @constant (#match? @constant "^[A-Z_]+$"))
|
||||
((identifier) @constant (#match? @constant "^[A-Z_]+$"))
|
||||
< Note: the `^` and `$` anchors will respectively match the
|
||||
start and end of the node's text.
|
||||
|
||||
@ -267,7 +267,7 @@ Here is a list of built-in directives:
|
||||
`offset!` *ts-predicate-offset!*
|
||||
Takes the range of the captured node and applies the offsets
|
||||
to it's range : >
|
||||
((idenfitier) @constant (#offset! @constant 0 1 0 -1))
|
||||
((identifier) @constant (#offset! @constant 0 1 0 -1))
|
||||
< This will generate a range object for the captured node with the
|
||||
offsets applied. The arguments are
|
||||
`({capture_id}, {start_row}, {start_col}, {end_row}, {end_col}, {key?})`
|
||||
|
20
runtime/ftplugin/checkhealth.vim
Normal file
20
runtime/ftplugin/checkhealth.vim
Normal file
@ -0,0 +1,20 @@
|
||||
" Vim filetype plugin
|
||||
" Language: Neovim checkhealth buffer
|
||||
" Last Change: 2021 Dec 15
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim
|
||||
|
||||
setlocal wrap breakindent linebreak
|
||||
setlocal conceallevel=2 concealcursor=nc
|
||||
setlocal keywordprg=:help
|
||||
let &l:iskeyword='!-~,^*,^|,^",192-255'
|
||||
|
||||
if exists("b:undo_ftplugin")
|
||||
let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<"
|
||||
else
|
||||
let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<"
|
||||
endif
|
@ -91,23 +91,22 @@ local function filter_by_severity(severity, diagnostics)
|
||||
end
|
||||
|
||||
---@private
|
||||
local function prefix_source(source, diagnostics)
|
||||
vim.validate { source = {source, function(v)
|
||||
return v == "always" or v == "if_many"
|
||||
end, "'always' or 'if_many'" } }
|
||||
|
||||
if source == "if_many" then
|
||||
local sources = {}
|
||||
for _, d in pairs(diagnostics) do
|
||||
if d.source then
|
||||
sources[d.source] = true
|
||||
local function count_sources(bufnr)
|
||||
local seen = {}
|
||||
local count = 0
|
||||
for _, namespace_diagnostics in pairs(diagnostic_cache[bufnr]) do
|
||||
for _, diagnostic in ipairs(namespace_diagnostics) do
|
||||
if diagnostic.source and not seen[diagnostic.source] then
|
||||
seen[diagnostic.source] = true
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if #vim.tbl_keys(sources) <= 1 then
|
||||
return diagnostics
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
---@private
|
||||
local function prefix_source(diagnostics)
|
||||
return vim.tbl_map(function(d)
|
||||
if not d.source then
|
||||
return d
|
||||
@ -272,6 +271,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")
|
||||
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
|
||||
@ -297,11 +298,6 @@ local function restore_extmarks(bufnr, last)
|
||||
if not found[extmark[1]] then
|
||||
local opts = extmark[4]
|
||||
opts.id = extmark[1]
|
||||
-- HACK: end_row should be end_line
|
||||
if opts.end_row then
|
||||
opts.end_line = opts.end_row
|
||||
opts.end_row = nil
|
||||
end
|
||||
pcall(vim.api.nvim_buf_set_extmark, bufnr, ns, extmark[2], extmark[3], opts)
|
||||
end
|
||||
end
|
||||
@ -386,7 +382,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) 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)
|
||||
@ -508,17 +504,20 @@ local function diagnostic_move_pos(opts, pos)
|
||||
return
|
||||
end
|
||||
|
||||
vim.api.nvim_win_call(win_id, function()
|
||||
-- Save position in the window's jumplist
|
||||
vim.api.nvim_win_call(win_id, function() vim.cmd("normal! m'") end)
|
||||
|
||||
vim.cmd("normal! m'")
|
||||
vim.api.nvim_win_set_cursor(win_id, {pos[1] + 1, pos[2]})
|
||||
-- Open folds under the cursor
|
||||
vim.cmd("normal! zv")
|
||||
end)
|
||||
|
||||
if float then
|
||||
local float_opts = type(float) == "table" and float or {}
|
||||
vim.schedule(function()
|
||||
M.open_float(
|
||||
vim.api.nvim_win_get_buf(win_id),
|
||||
vim.tbl_extend("keep", float_opts, {
|
||||
bufnr = vim.api.nvim_win_get_buf(win_id),
|
||||
scope = "cursor",
|
||||
focus = false,
|
||||
})
|
||||
@ -557,11 +556,19 @@ end
|
||||
--- - underline: (default true) Use underline for diagnostics. Options:
|
||||
--- * severity: Only underline diagnostics matching the given severity
|
||||
--- |diagnostic-severity|
|
||||
--- - virtual_text: (default true) Use virtual text for diagnostics. Options:
|
||||
--- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics
|
||||
--- are set for a namespace, one prefix per diagnostic + the last diagnostic
|
||||
--- message are shown.
|
||||
--- Options:
|
||||
--- * severity: Only show virtual text for diagnostics matching the given
|
||||
--- severity |diagnostic-severity|
|
||||
--- * source: (string) Include the diagnostic source in virtual
|
||||
--- text. One of "always" or "if_many".
|
||||
--- * source: (boolean or string) Include the diagnostic source in virtual
|
||||
--- text. Use "if_many" to only show sources if there is more than
|
||||
--- one diagnostic source in the buffer. Otherwise, any truthy value
|
||||
--- means to always show the diagnostic source.
|
||||
--- * spacing: (number) Amount of empty spaces inserted at the beginning
|
||||
--- of the virtual text.
|
||||
--- * prefix: (string) Prepend diagnostic message with prefix.
|
||||
--- * format: (function) A function that takes a diagnostic as input and
|
||||
--- returns a string. The return value is the text used to display
|
||||
--- the diagnostic. Example:
|
||||
@ -653,9 +660,14 @@ function M.set(namespace, bufnr, diagnostics, opts)
|
||||
M.show(namespace, bufnr, nil, opts)
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_call(bufnr, function()
|
||||
vim.api.nvim_command(
|
||||
string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
|
||||
string.format(
|
||||
"doautocmd <nomodeline> DiagnosticChanged %s",
|
||||
vim.fn.fnameescape(vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Get namespace metadata.
|
||||
@ -920,8 +932,11 @@ M.handlers.virtual_text = {
|
||||
if opts.virtual_text.format then
|
||||
diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
|
||||
end
|
||||
if opts.virtual_text.source then
|
||||
diagnostics = prefix_source(opts.virtual_text.source, diagnostics)
|
||||
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
|
||||
severity = opts.virtual_text.severity
|
||||
@ -1127,12 +1142,15 @@ end
|
||||
|
||||
--- Show diagnostics in a floating window.
|
||||
---
|
||||
---@param bufnr number|nil Buffer number. Defaults to the current buffer.
|
||||
---@param 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 diagnostics from.
|
||||
--- Defaults to the current buffer.
|
||||
--- - namespace: (number) Limit diagnostics to the given namespace
|
||||
--- - scope: (string, default "line") Show diagnostics from the whole buffer ("buffer"),
|
||||
--- the current cursor line ("line"), or the current cursor position ("cursor").
|
||||
--- Shorthand versions are also accepted ("c" for "cursor", "l" for "line", "b"
|
||||
--- for "buffer").
|
||||
--- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather
|
||||
--- than the cursor position. If a number, interpreted as a line number;
|
||||
--- otherwise, a (row, col) tuple.
|
||||
@ -1143,8 +1161,11 @@ end
|
||||
--- - header: (string or table) String to use as the header for the floating window. If a
|
||||
--- table, it is interpreted as a [text, hl_group] tuple. Overrides the setting
|
||||
--- from |vim.diagnostic.config()|.
|
||||
--- - source: (string) Include the diagnostic source in the message. One of "always" or
|
||||
--- "if_many". Overrides the setting from |vim.diagnostic.config()|.
|
||||
--- - source: (boolean or string) Include the diagnostic source in the message.
|
||||
--- Use "if_many" to only show sources if there is more than one source of
|
||||
--- diagnostics in the buffer. Otherwise, any truthy value means to always show
|
||||
--- the diagnostic source. Overrides the setting from
|
||||
--- |vim.diagnostic.config()|.
|
||||
--- - format: (function) A function that takes a diagnostic as input and returns a
|
||||
--- string. The return value is the text used to display the diagnostic.
|
||||
--- Overrides the setting from |vim.diagnostic.config()|.
|
||||
@ -1161,15 +1182,21 @@ end
|
||||
--- highlight.
|
||||
--- Overrides the setting from |vim.diagnostic.config()|.
|
||||
---@return tuple ({float_bufnr}, {win_id})
|
||||
function M.open_float(bufnr, opts)
|
||||
function M.open_float(opts, ...)
|
||||
-- Support old (bufnr, opts) signature
|
||||
local bufnr
|
||||
if opts == nil or type(opts) == "number" then
|
||||
bufnr = opts
|
||||
opts = ...
|
||||
else
|
||||
vim.validate {
|
||||
bufnr = { bufnr, 'n', true },
|
||||
opts = { opts, 't', true },
|
||||
}
|
||||
end
|
||||
|
||||
opts = opts or {}
|
||||
bufnr = get_bufnr(bufnr)
|
||||
local scope = opts.scope or "line"
|
||||
bufnr = get_bufnr(bufnr or opts.bufnr)
|
||||
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 not opts.pos then
|
||||
@ -1250,8 +1277,8 @@ function M.open_float(bufnr, opts)
|
||||
diagnostics = reformat_diagnostics(opts.format, diagnostics)
|
||||
end
|
||||
|
||||
if opts.source then
|
||||
diagnostics = prefix_source(opts.source, diagnostics)
|
||||
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)
|
||||
@ -1327,9 +1354,14 @@ function M.reset(namespace, bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_call(bufnr, function()
|
||||
vim.api.nvim_command(
|
||||
string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
|
||||
string.format(
|
||||
"doautocmd <nomodeline> DiagnosticChanged %s",
|
||||
vim.fn.fnameescape(vim.api.nvim_buf_get_name(bufnr))
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Add all diagnostics to the quickfix list.
|
||||
|
@ -290,7 +290,7 @@ end
|
||||
--- Memoizes a function. On first run, the function return value is saved and
|
||||
--- immediately returned on subsequent runs. If the function returns a multival,
|
||||
--- only the first returned value will be memoized and returned. The function will only be run once,
|
||||
--- even if it has side-effects.
|
||||
--- even if it has side effects.
|
||||
---
|
||||
---@param fn (function) Function to run
|
||||
---@returns (function) Memoized function
|
||||
@ -489,7 +489,8 @@ local function text_document_did_open_handler(bufnr, client)
|
||||
-- Protect against a race where the buffer disappears
|
||||
-- between `did_open_handler` and the scheduled function firing.
|
||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.lsp.diagnostic.redraw(bufnr, client.id)
|
||||
local namespace = vim.lsp.diagnostic.get_namespace(client.id)
|
||||
vim.diagnostic.show(namespace, bufnr)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@ -559,6 +560,12 @@ end
|
||||
---
|
||||
--- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
|
||||
---
|
||||
--- - {requests} (table): The current pending requests in flight
|
||||
--- to the server. Entries are key-value pairs with the key
|
||||
--- being the request ID while the value is a table with `type`,
|
||||
--- `bufnr`, and `method` key-value pairs. `type` is either "pending"
|
||||
--- for an active request, or "cancel" for a cancel request.
|
||||
---
|
||||
--- - {config} (table): copy of the table that was passed by the user
|
||||
--- to |vim.lsp.start_client()|.
|
||||
---
|
||||
@ -638,8 +645,8 @@ end
|
||||
---@param on_error Callback with parameters (code, ...), invoked
|
||||
--- when the client operation throws an error. `code` is a number describing
|
||||
--- the error. Other arguments may be passed depending on the error kind. See
|
||||
--- |vim.lsp.client_errors| for possible errors.
|
||||
--- Use `vim.lsp.client_errors[code]` to get human-friendly name.
|
||||
--- |vim.lsp.rpc.client_errors| for possible errors.
|
||||
--- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
|
||||
---
|
||||
---@param before_init Callback with parameters (initialize_params, config)
|
||||
--- invoked before the LSP "initialize" phase, where `params` contains the
|
||||
@ -750,8 +757,8 @@ function lsp.start_client(config)
|
||||
---
|
||||
---@param code (number) Error code
|
||||
---@param err (...) Other arguments may be passed depending on the error kind
|
||||
---@see |vim.lsp.client_errors| for possible errors. Use
|
||||
---`vim.lsp.client_errors[code]` to get a human-friendly name.
|
||||
---@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 })
|
||||
err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err))
|
||||
@ -770,6 +777,10 @@ function lsp.start_client(config)
|
||||
---@param code (number) exit code of the process
|
||||
---@param signal (number) the signal used to terminate (if any)
|
||||
function dispatch.on_exit(code, signal)
|
||||
if config.on_exit then
|
||||
pcall(config.on_exit, code, signal, client_id)
|
||||
end
|
||||
|
||||
active_clients[client_id] = nil
|
||||
uninitialized_clients[client_id] = nil
|
||||
|
||||
@ -785,10 +796,6 @@ function lsp.start_client(config)
|
||||
vim.notify(msg, vim.log.levels.WARN)
|
||||
end)
|
||||
end
|
||||
|
||||
if config.on_exit then
|
||||
pcall(config.on_exit, code, signal, client_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Start the RPC client.
|
||||
@ -1105,9 +1112,9 @@ local text_document_did_change_handler
|
||||
do
|
||||
text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline)
|
||||
|
||||
-- Don't do anything if there are no clients attached.
|
||||
-- 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
|
||||
return true
|
||||
end
|
||||
util.buf_versions[bufnr] = changedtick
|
||||
local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline)
|
||||
@ -1149,6 +1156,12 @@ function lsp.buf_attach_client(bufnr, client_id)
|
||||
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)
|
||||
)
|
||||
return false
|
||||
end
|
||||
local buffer_client_ids = all_buffer_active_clients[bufnr]
|
||||
-- This is our first time attaching to this buffer.
|
||||
if not buffer_client_ids then
|
||||
@ -1207,6 +1220,50 @@ function lsp.buf_attach_client(bufnr, client_id)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Detaches client from the specified buffer.
|
||||
--- Note: While the server is notified that the text document (buffer)
|
||||
--- was closed, it is still able to send notifications should it ignore this notification.
|
||||
---
|
||||
---@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'};
|
||||
}
|
||||
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)
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
changetracking.reset_buf(client, bufnr)
|
||||
|
||||
if client.resolved_capabilities.text_document_open_close then
|
||||
local uri = vim.uri_from_bufnr(bufnr)
|
||||
local params = { textDocument = { uri = uri; } }
|
||||
client.notify('textDocument/didClose', params)
|
||||
end
|
||||
|
||||
client.attached_buffers[bufnr] = nil
|
||||
util.buf_versions[bufnr] = nil
|
||||
|
||||
all_buffer_active_clients[bufnr][client_id] = nil
|
||||
if #vim.tbl_keys(all_buffer_active_clients[bufnr]) == 0 then
|
||||
all_buffer_active_clients[bufnr] = nil
|
||||
end
|
||||
|
||||
local namespace = vim.lsp.diagnostic.get_namespace(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.
|
||||
---
|
||||
---@param bufnr (number) Buffer handle, or 0 for current
|
||||
@ -1486,11 +1543,7 @@ local function adjust_start_col(lnum, line, items, encoding)
|
||||
end
|
||||
end
|
||||
if min_start_char then
|
||||
if encoding == 'utf-8' then
|
||||
return min_start_char
|
||||
else
|
||||
return vim.str_byteindex(line, min_start_char, encoding == 'utf-16')
|
||||
end
|
||||
return util._str_byteindex_enc(line, min_start_char, encoding)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
@ -1655,14 +1708,14 @@ end
|
||||
--
|
||||
-- Can be used to lookup the number from the name or the
|
||||
-- name from the number.
|
||||
-- Levels by name: "trace", "debug", "info", "warn", "error"
|
||||
-- Level numbers begin with "trace" at 0
|
||||
-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
-- Level numbers begin with "TRACE" at 0
|
||||
lsp.log_levels = log.levels
|
||||
|
||||
--- Sets the global log level for LSP logging.
|
||||
---
|
||||
--- Levels by name: "trace", "debug", "info", "warn", "error"
|
||||
--- Level numbers begin with "trace" at 0
|
||||
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
--- Level numbers begin with "TRACE" at 0
|
||||
---
|
||||
--- Use `lsp.log_levels` for reverse lookup.
|
||||
---
|
||||
|
@ -116,31 +116,30 @@ end
|
||||
--- asks the user to select one.
|
||||
--
|
||||
---@returns The client that the user selected or nil
|
||||
local function select_client(method)
|
||||
local clients = vim.tbl_values(vim.lsp.buf_get_clients());
|
||||
local function select_client(method, on_choice)
|
||||
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)
|
||||
end, clients)
|
||||
-- better UX when choices are always in the same order (between restarts)
|
||||
table.sort(clients, function (a, b) return a.name < b.name end)
|
||||
table.sort(clients, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
if #clients > 1 then
|
||||
local choices = {}
|
||||
for k,v in pairs(clients) do
|
||||
table.insert(choices, string.format("%d %s", k, v.name))
|
||||
end
|
||||
local user_choice = vim.fn.confirm(
|
||||
"Select a language server:",
|
||||
table.concat(choices, "\n"),
|
||||
0,
|
||||
"Question"
|
||||
)
|
||||
if user_choice == 0 then return nil end
|
||||
return clients[user_choice]
|
||||
vim.ui.select(clients, {
|
||||
prompt = 'Select a language server:',
|
||||
format_item = function(client)
|
||||
return client.name
|
||||
end,
|
||||
}, on_choice)
|
||||
elseif #clients < 1 then
|
||||
return nil
|
||||
on_choice(nil)
|
||||
else
|
||||
return clients[1]
|
||||
on_choice(clients[1])
|
||||
end
|
||||
end
|
||||
|
||||
@ -152,11 +151,15 @@ end
|
||||
--
|
||||
---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
|
||||
function M.formatting(options)
|
||||
local client = select_client("textDocument/formatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_formatting_params(options)
|
||||
return client.request("textDocument/formatting", params, nil, vim.api.nvim_get_current_buf())
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
select_client('textDocument/formatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
return client.request('textDocument/formatting', params, nil, bufnr)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Performs |vim.lsp.buf.formatting()| synchronously.
|
||||
@ -172,17 +175,20 @@ end
|
||||
---@param timeout_ms (number) Request timeout
|
||||
---@see |vim.lsp.buf.formatting_seq_sync|
|
||||
function M.formatting_sync(options, timeout_ms)
|
||||
local client = select_client("textDocument/formatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_formatting_params(options)
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr)
|
||||
select_client('textDocument/formatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
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)
|
||||
elseif err then
|
||||
vim.notify("vim.lsp.buf.formatting_sync: " .. err, vim.log.levels.WARN)
|
||||
vim.notify('vim.lsp.buf.formatting_sync: ' .. err, vim.log.levels.WARN)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Formats the current buffer by sequentially requesting formatting from attached clients.
|
||||
@ -238,12 +244,15 @@ end
|
||||
---@param end_pos ({number, number}, optional) mark-indexed position.
|
||||
---Defaults to the end of the last visual selection.
|
||||
function M.range_formatting(options, start_pos, end_pos)
|
||||
local client = select_client("textDocument/rangeFormatting")
|
||||
if client == nil then return end
|
||||
|
||||
local params = util.make_given_range_params(start_pos, end_pos)
|
||||
params.options = util.make_formatting_params(options).options
|
||||
return client.request("textDocument/rangeFormatting", params)
|
||||
select_client('textDocument/rangeFormatting', function(client)
|
||||
if client == nil then
|
||||
return
|
||||
end
|
||||
|
||||
return client.request('textDocument/rangeFormatting', params)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Renames all references to the symbol under the cursor.
|
||||
|
@ -153,19 +153,6 @@ function M.get_namespace(client_id)
|
||||
return _client_namespaces[client_id]
|
||||
end
|
||||
|
||||
--- Save diagnostics to the current buffer.
|
||||
---
|
||||
--- Handles saving diagnostics from multiple clients in the same buffer.
|
||||
---@param diagnostics Diagnostic[]
|
||||
---@param bufnr number
|
||||
---@param client_id number
|
||||
---@private
|
||||
function M.save(diagnostics, bufnr, client_id)
|
||||
local namespace = M.get_namespace(client_id)
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
|
||||
end
|
||||
-- }}}
|
||||
|
||||
--- |lsp-handler| for the method "textDocument/publishDiagnostics"
|
||||
---
|
||||
--- See |vim.diagnostic.config()| for configuration options. Handler-specific
|
||||
@ -245,6 +232,23 @@ end
|
||||
|
||||
-- Deprecated Functions {{{
|
||||
|
||||
|
||||
--- Save diagnostics to the current buffer.
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.set()|
|
||||
---
|
||||
--- Handles saving diagnostics from multiple clients in the same buffer.
|
||||
---@param diagnostics Diagnostic[]
|
||||
---@param bufnr number
|
||||
---@param client_id number
|
||||
---@private
|
||||
function M.save(diagnostics, bufnr, client_id)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.save is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
local namespace = M.get_namespace(client_id)
|
||||
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
|
||||
end
|
||||
-- }}}
|
||||
|
||||
--- Get all diagnostics for clients
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.get()|
|
||||
@ -253,6 +257,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
local result = {}
|
||||
local namespace
|
||||
if client_id then
|
||||
@ -274,6 +279,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.get is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
predicate = predicate or function() return true end
|
||||
if client_id == nil then
|
||||
local all_diagnostics = {}
|
||||
@ -335,6 +341,7 @@ end
|
||||
---@param severity DiagnosticSeverity
|
||||
---@param client_id number the client id
|
||||
function M.get_count(bufnr, severity, client_id)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
severity = severity_lsp_to_vim(severity)
|
||||
local opts = { severity = severity }
|
||||
if client_id ~= nil then
|
||||
@ -351,6 +358,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Previous diagnostic
|
||||
function M.get_prev(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -368,6 +376,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Previous diagnostic position
|
||||
function M.get_prev_pos(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -384,6 +393,7 @@ end
|
||||
---
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
function M.goto_prev(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -401,6 +411,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Next diagnostic
|
||||
function M.get_next(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -418,6 +429,7 @@ end
|
||||
---@param opts table See |vim.lsp.diagnostic.goto_next()|
|
||||
---@return table Next diagnostic position
|
||||
function M.get_next_pos(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -432,6 +444,7 @@ end
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.goto_next()|
|
||||
function M.goto_next(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if opts then
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -455,6 +468,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
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)}
|
||||
@ -475,6 +489,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
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)}
|
||||
@ -496,6 +511,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
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)}
|
||||
@ -514,6 +530,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.api.nvim_echo({{'vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
|
||||
end
|
||||
|
||||
@ -531,6 +548,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
opts = opts or {}
|
||||
opts.scope = "cursor"
|
||||
opts.pos = position
|
||||
@ -554,6 +572,7 @@ 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.api.nvim_echo({{'vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
opts = opts or {}
|
||||
opts.scope = "line"
|
||||
opts.pos = line_nr
|
||||
@ -565,7 +584,7 @@ end
|
||||
|
||||
--- Redraw diagnostics for the given buffer and client
|
||||
---
|
||||
---@deprecated Prefer |vim.diagnostic.redraw()|
|
||||
---@deprecated Prefer |vim.diagnostic.show()|
|
||||
---
|
||||
--- This calls the "textDocument/publishDiagnostics" handler manually using
|
||||
--- the cached diagnostics already received from the server. This can be useful
|
||||
@ -577,6 +596,7 @@ end
|
||||
--- client. The default is to redraw diagnostics for all attached
|
||||
--- clients.
|
||||
function M.redraw(bufnr, client_id)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
bufnr = get_bufnr(bufnr)
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
@ -604,6 +624,7 @@ end
|
||||
--- - {workspace}: (boolean, default true)
|
||||
--- - Set the list with workspace diagnostics
|
||||
function M.set_qflist(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
opts = opts or {}
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -635,6 +656,7 @@ end
|
||||
--- - {workspace}: (boolean, default false)
|
||||
--- - Set the list with workspace diagnostics
|
||||
function M.set_loclist(opts)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
opts = opts or {}
|
||||
if opts.severity then
|
||||
opts.severity = severity_lsp_to_vim(opts.severity)
|
||||
@ -662,6 +684,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.api.nvim_echo({{'vim.lsp.diagnostic.disable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
M.disable(bufnr, client.id)
|
||||
@ -682,6 +705,7 @@ end
|
||||
--- client. The default is to enable diagnostics for all attached
|
||||
--- clients.
|
||||
function M.enable(bufnr, client_id)
|
||||
vim.api.nvim_echo({{'vim.lsp.diagnostic.enable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
|
||||
if not client_id then
|
||||
return vim.lsp.for_each_buffer_client(bufnr, function(client)
|
||||
M.enable(bufnr, client.id)
|
||||
|
@ -28,7 +28,7 @@ local function progress_handler(_, result, ctx, _)
|
||||
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 the message")
|
||||
return
|
||||
return vim.NIL
|
||||
end
|
||||
local val = result.value -- unspecified yet
|
||||
local token = result.token -- string or number
|
||||
@ -70,7 +70,7 @@ M['window/workDoneProgress/create'] = function(_, result, ctx)
|
||||
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 the message")
|
||||
return
|
||||
return vim.NIL
|
||||
end
|
||||
client.messages.progress[token] = {}
|
||||
return vim.NIL
|
||||
@ -246,7 +246,7 @@ end
|
||||
---@param config table Configuration table.
|
||||
--- - border: (default=nil)
|
||||
--- - Add borders to the floating window
|
||||
--- - See |vim.api.nvim_open_win()|
|
||||
--- - See |nvim_open_win()|
|
||||
function M.hover(_, result, ctx, config)
|
||||
config = config or {}
|
||||
config.focus_id = ctx.method
|
||||
@ -285,7 +285,7 @@ local function location_handler(_, result, ctx, _)
|
||||
util.jump_to_location(result[1])
|
||||
|
||||
if #result > 1 then
|
||||
util.set_qflist(util.locations_to_items(result))
|
||||
vim.fn.setqflist({}, ' ', {title = 'LSP locations', items = util.locations_to_items(result)})
|
||||
api.nvim_command("copen")
|
||||
end
|
||||
else
|
||||
@ -379,7 +379,7 @@ local make_call_hierarchy_handler = function(direction)
|
||||
})
|
||||
end
|
||||
end
|
||||
util.set_qflist(items)
|
||||
vim.fn.setqflist({}, ' ', {title = 'LSP call hierarchy', items = items})
|
||||
api.nvim_command("copen")
|
||||
end
|
||||
end
|
||||
|
@ -8,8 +8,8 @@ local log = {}
|
||||
-- Log level dictionary with reverse lookup as well.
|
||||
--
|
||||
-- Can be used to lookup the number from the name or the name from the number.
|
||||
-- Levels by name: 'trace', 'debug', 'info', 'warn', 'error'
|
||||
-- Level numbers begin with 'trace' at 0
|
||||
-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
|
||||
-- Level numbers begin with "TRACE" at 0
|
||||
log.levels = vim.deepcopy(vim.log.levels)
|
||||
|
||||
-- Default log level is warn.
|
||||
|
@ -776,149 +776,9 @@ function protocol.make_client_capabilities()
|
||||
}
|
||||
end
|
||||
|
||||
--[=[
|
||||
export interface DocumentFilter {
|
||||
--A language id, like `typescript`.
|
||||
language?: string;
|
||||
--A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
|
||||
scheme?: string;
|
||||
--A glob pattern, like `*.{ts,js}`.
|
||||
--
|
||||
--Glob patterns can have the following syntax:
|
||||
--- `*` to match one or more characters in a path segment
|
||||
--- `?` to match on one character in a path segment
|
||||
--- `**` to match any number of path segments, including none
|
||||
--- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
|
||||
--- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
|
||||
--- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
|
||||
pattern?: string;
|
||||
}
|
||||
--]=]
|
||||
|
||||
--[[
|
||||
--Static registration options to be returned in the initialize request.
|
||||
interface StaticRegistrationOptions {
|
||||
--The id used to register the request. The id can be used to deregister
|
||||
--the request again. See also Registration#id.
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface DocumentFilter {
|
||||
--A language id, like `typescript`.
|
||||
language?: string;
|
||||
--A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
|
||||
scheme?: string;
|
||||
--A glob pattern, like `*.{ts,js}`.
|
||||
--
|
||||
--Glob patterns can have the following syntax:
|
||||
--- `*` to match one or more characters in a path segment
|
||||
--- `?` to match on one character in a path segment
|
||||
--- `**` to match any number of path segments, including none
|
||||
--- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
|
||||
--- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
|
||||
--- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
|
||||
pattern?: string;
|
||||
}
|
||||
export type DocumentSelector = DocumentFilter[];
|
||||
export interface TextDocumentRegistrationOptions {
|
||||
--A document selector to identify the scope of the registration. If set to null
|
||||
--the document selector provided on the client side will be used.
|
||||
documentSelector: DocumentSelector | null;
|
||||
}
|
||||
|
||||
--Code Action options.
|
||||
export interface CodeActionOptions {
|
||||
--CodeActionKinds that this server may return.
|
||||
--
|
||||
--The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
|
||||
--may list out every specific kind they provide.
|
||||
codeActionKinds?: CodeActionKind[];
|
||||
}
|
||||
|
||||
interface ServerCapabilities {
|
||||
--Defines how text documents are synced. Is either a detailed structure defining each notification or
|
||||
--for backwards compatibility the TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`.
|
||||
textDocumentSync?: TextDocumentSyncOptions | number;
|
||||
--The server provides hover support.
|
||||
hoverProvider?: boolean;
|
||||
--The server provides completion support.
|
||||
completionProvider?: CompletionOptions;
|
||||
--The server provides signature help support.
|
||||
signatureHelpProvider?: SignatureHelpOptions;
|
||||
--The server provides goto definition support.
|
||||
definitionProvider?: boolean;
|
||||
--The server provides Goto Type Definition support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
typeDefinitionProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides Goto Implementation support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
implementationProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides find references support.
|
||||
referencesProvider?: boolean;
|
||||
--The server provides document highlight support.
|
||||
documentHighlightProvider?: boolean;
|
||||
--The server provides document symbol support.
|
||||
documentSymbolProvider?: boolean;
|
||||
--The server provides workspace symbol support.
|
||||
workspaceSymbolProvider?: boolean;
|
||||
--The server provides code actions. The `CodeActionOptions` return type is only
|
||||
--valid if the client signals code action literal support via the property
|
||||
--`textDocument.codeAction.codeActionLiteralSupport`.
|
||||
codeActionProvider?: boolean | CodeActionOptions;
|
||||
--The server provides code lens.
|
||||
codeLensProvider?: CodeLensOptions;
|
||||
--The server provides document formatting.
|
||||
documentFormattingProvider?: boolean;
|
||||
--The server provides document range formatting.
|
||||
documentRangeFormattingProvider?: boolean;
|
||||
--The server provides document formatting on typing.
|
||||
documentOnTypeFormattingProvider?: DocumentOnTypeFormattingOptions;
|
||||
--The server provides rename support. RenameOptions may only be
|
||||
--specified if the client states that it supports
|
||||
--`prepareSupport` in its initial `initialize` request.
|
||||
renameProvider?: boolean | RenameOptions;
|
||||
--The server provides document link support.
|
||||
documentLinkProvider?: DocumentLinkOptions;
|
||||
--The server provides color provider support.
|
||||
--
|
||||
--Since 3.6.0
|
||||
colorProvider?: boolean | ColorProviderOptions | (ColorProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides folding provider support.
|
||||
--
|
||||
--Since 3.10.0
|
||||
foldingRangeProvider?: boolean | FoldingRangeProviderOptions | (FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides go to declaration support.
|
||||
--
|
||||
--Since 3.14.0
|
||||
declarationProvider?: boolean | (TextDocumentRegistrationOptions & StaticRegistrationOptions);
|
||||
--The server provides execute command support.
|
||||
executeCommandProvider?: ExecuteCommandOptions;
|
||||
--Workspace specific server capabilities
|
||||
workspace?: {
|
||||
--The server supports workspace folder.
|
||||
--
|
||||
--Since 3.6.0
|
||||
workspaceFolders?: {
|
||||
* The server has support for workspace folders
|
||||
supported?: boolean;
|
||||
* Whether the server wants to receive workspace folder
|
||||
* change notifications.
|
||||
*
|
||||
* If a strings is provided the string is treated as a ID
|
||||
* under which the notification is registered on the client
|
||||
* side. The ID can be used to unregister for these events
|
||||
* using the `client/unregisterCapability` request.
|
||||
changeNotifications?: string | boolean;
|
||||
}
|
||||
}
|
||||
--Experimental server capabilities.
|
||||
experimental?: any;
|
||||
}
|
||||
--]]
|
||||
|
||||
--- Creates a normalized object describing LSP server capabilities.
|
||||
---@param server_capabilities table Table of capabilities supported by the server
|
||||
---@return table Normalized table of capabilities
|
||||
function protocol.resolve_capabilities(server_capabilities)
|
||||
local general_properties = {}
|
||||
local text_document_sync_properties
|
||||
|
@ -133,7 +133,8 @@ local function request_parser_loop()
|
||||
end
|
||||
end
|
||||
|
||||
local client_errors = vim.tbl_add_reverse_lookup {
|
||||
--- Mapping of error codes used by the client
|
||||
local client_errors = {
|
||||
INVALID_SERVER_MESSAGE = 1;
|
||||
INVALID_SERVER_JSON = 2;
|
||||
NO_RESULT_CALLBACK_FOUND = 3;
|
||||
@ -143,6 +144,8 @@ local client_errors = vim.tbl_add_reverse_lookup {
|
||||
SERVER_RESULT_CALLBACK_ERROR = 7;
|
||||
}
|
||||
|
||||
client_errors = vim.tbl_add_reverse_lookup(client_errors)
|
||||
|
||||
--- Constructs an error message from an LSP error object.
|
||||
---
|
||||
---@param err (table) The error object
|
||||
|
@ -105,15 +105,16 @@ local function align_end_position(line, byte, offset_encoding)
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
else
|
||||
-- Modifying line, find the nearest utf codepoint
|
||||
local offset = str_utf_end(line, byte)
|
||||
local offset = str_utf_start(line, byte)
|
||||
-- If the byte does not fall on the start of the character, then
|
||||
-- align to the start of the next character.
|
||||
if offset > 0 then
|
||||
char = byte_to_utf(line, byte, offset_encoding) + 1
|
||||
byte = byte + offset
|
||||
else
|
||||
if offset < 0 then
|
||||
byte = byte + str_utf_end(line, byte) + 1
|
||||
end
|
||||
if byte <= #line then
|
||||
char = byte_to_utf(line, byte, offset_encoding)
|
||||
byte = byte + offset
|
||||
else
|
||||
char = compute_line_length(line, offset_encoding) + 1
|
||||
end
|
||||
-- Extending line, find the nearest utf codepoint for the last valid character
|
||||
end
|
||||
@ -167,7 +168,7 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline,
|
||||
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, start_byte_idx, offset_encoding)
|
||||
char_idx = byte_to_utf(prev_line, byte_idx, offset_encoding)
|
||||
end
|
||||
|
||||
-- Return the start difference (shared for new and prev lines)
|
||||
|
@ -90,6 +90,49 @@ local function split_lines(value)
|
||||
return split(value, '\n', true)
|
||||
end
|
||||
|
||||
--- Convert byte index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_utfindex
|
||||
---@param line string line to be indexed
|
||||
---@param index number byte index (utf-8), or `nil` for length
|
||||
---@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 encoding == 'utf-8' then
|
||||
if index then return index else return #line end
|
||||
elseif encoding == 'utf-16' then
|
||||
local _, col16 = vim.str_utfindex(line, index)
|
||||
return col16
|
||||
elseif encoding == 'utf-32' then
|
||||
local col32, _ = vim.str_utfindex(line, index)
|
||||
return col32
|
||||
else
|
||||
error("Invalid encoding: " .. vim.inspect(encoding))
|
||||
end
|
||||
end
|
||||
|
||||
--- Convert UTF index to `encoding` index.
|
||||
--- Convenience wrapper around vim.str_byteindex
|
||||
---Alternative to vim.str_byteindex that takes an encoding.
|
||||
---@param line string line to be indexed
|
||||
---@param index number UTF index
|
||||
---@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 encoding == 'utf-8' then
|
||||
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))
|
||||
end
|
||||
end
|
||||
|
||||
local _str_utfindex_enc = M._str_utfindex_enc
|
||||
local _str_byteindex_enc = M._str_byteindex_enc
|
||||
--- Replaces text in a range with new text.
|
||||
---
|
||||
--- CAUTION: Changes in-place!
|
||||
@ -237,6 +280,7 @@ 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
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
--- 1-indexed
|
||||
local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
-- LSP's line and characters are 0-indexed
|
||||
@ -247,13 +291,7 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
|
||||
if col > 0 then
|
||||
local line = get_line(bufnr, position.line)
|
||||
local ok, result
|
||||
|
||||
if offset_encoding == "utf-16" or not offset_encoding then
|
||||
ok, result = pcall(vim.str_byteindex, line, col, true)
|
||||
elseif offset_encoding == "utf-32" then
|
||||
ok, result = pcall(vim.str_byteindex, line, col, false)
|
||||
end
|
||||
|
||||
ok, result = pcall(_str_byteindex_enc, line, col, offset_encoding)
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
@ -325,12 +363,15 @@ end
|
||||
--- Applies a list of text edits to a buffer.
|
||||
---@param text_edits table list of `TextEdit` objects
|
||||
---@param bufnr number Buffer id
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to encoding of first client of `bufnr`
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
|
||||
function M.apply_text_edits(text_edits, bufnr)
|
||||
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', true };
|
||||
}
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
if not next(text_edits) then return end
|
||||
if not api.nvim_buf_is_loaded(bufnr) then
|
||||
vim.fn.bufload(bufnr)
|
||||
@ -367,8 +408,7 @@ function M.apply_text_edits(text_edits, bufnr)
|
||||
-- Some LSP servers may return +1 range of the buffer content but nvim_buf_set_text can't accept it so we should fix it here.
|
||||
local has_eol_text_edit = false
|
||||
local max = vim.api.nvim_buf_line_count(bufnr)
|
||||
-- TODO handle offset_encoding
|
||||
local _, len = vim.str_utfindex(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '')
|
||||
local len = _str_utfindex_enc(vim.api.nvim_buf_get_lines(bufnr, -2, -1, false)[1] or '', nil, offset_encoding)
|
||||
text_edits = vim.tbl_map(function(text_edit)
|
||||
if max <= text_edit.range.start.line then
|
||||
text_edit.range.start.line = max - 1
|
||||
@ -965,6 +1005,8 @@ function M.jump_to_location(location)
|
||||
local row = range.start.line
|
||||
local col = get_line_byte_from_position(0, range.start)
|
||||
api.nvim_win_set_cursor(0, {row + 1, col})
|
||||
-- Open folds under the cursor
|
||||
vim.cmd("normal! zv")
|
||||
return true
|
||||
end
|
||||
|
||||
@ -1218,17 +1260,57 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
return stripped
|
||||
end
|
||||
|
||||
---@private
|
||||
--- Creates autocommands to close a preview window when events happen.
|
||||
---
|
||||
---@param events (table) list of events
|
||||
---@param winnr (number) window id of preview window
|
||||
---@param events table list of events
|
||||
---@param winnr number window id of preview window
|
||||
---@param bufnrs table list of buffers where the preview window will remain visible
|
||||
---@see |autocmd-events|
|
||||
function M.close_preview_autocmd(events, winnr)
|
||||
local function close_preview_autocmd(events, winnr, bufnrs)
|
||||
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([[
|
||||
augroup %s
|
||||
autocmd!
|
||||
autocmd BufEnter * lua vim.lsp.util._close_preview_window(%d, {%s})
|
||||
augroup end
|
||||
]], augroup, winnr, table.concat(bufnrs, ',')))
|
||||
|
||||
if #events > 0 then
|
||||
api.nvim_command("autocmd "..table.concat(events, ',').." <buffer> ++once lua pcall(vim.api.nvim_win_close, "..winnr..", true)")
|
||||
vim.cmd(string.format([[
|
||||
augroup %s
|
||||
autocmd %s <buffer> lua vim.lsp.util._close_preview_window(%d)
|
||||
augroup end
|
||||
]], augroup, table.concat(events, ','), winnr))
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
--- Closes the preview window
|
||||
---
|
||||
---@param winnr number window id of preview window
|
||||
---@param bufnrs table|nil optional list of ignored buffers
|
||||
function M._close_preview_window(winnr, bufnrs)
|
||||
vim.schedule(function()
|
||||
-- exit if we are in one of ignored buffers
|
||||
if bufnrs and vim.tbl_contains(bufnrs, api.nvim_get_current_buf()) then
|
||||
return
|
||||
end
|
||||
|
||||
local augroup = 'preview_window_'..winnr
|
||||
vim.cmd(string.format([[
|
||||
augroup %s
|
||||
autocmd!
|
||||
augroup end
|
||||
augroup! %s
|
||||
]], augroup, augroup))
|
||||
pcall(vim.api.nvim_win_close, winnr, true)
|
||||
end)
|
||||
end
|
||||
|
||||
---@internal
|
||||
--- Computes size of float needed to show contents (with optional wrapping)
|
||||
---
|
||||
@ -1335,7 +1417,7 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
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", "BufHidden", "InsertCharPre"}
|
||||
opts.close_events = opts.close_events or {"CursorMoved", "CursorMovedI", "InsertCharPre"}
|
||||
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
@ -1404,7 +1486,7 @@ 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})
|
||||
M.close_preview_autocmd(opts.close_events, floating_winnr)
|
||||
close_preview_autocmd(opts.close_events, floating_winnr, {floating_bufnr, bufnr})
|
||||
|
||||
-- save focus_id
|
||||
if opts.focus_id then
|
||||
@ -1430,11 +1512,11 @@ do --[[ References ]]
|
||||
---
|
||||
---@param bufnr number Buffer id
|
||||
---@param references table List of `DocumentHighlight` objects to highlight
|
||||
---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to utf-16
|
||||
---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to `offset_encoding` of first client of `bufnr`
|
||||
---@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 or 'utf-16'
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
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"]
|
||||
@ -1529,6 +1611,7 @@ 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.fn.setloclist(win_id or 0, {}, ' ', {
|
||||
title = 'Language Server';
|
||||
items = items;
|
||||
@ -1542,6 +1625,7 @@ 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.fn.setqflist({}, ' ', {
|
||||
title = 'Language Server';
|
||||
items = items;
|
||||
@ -1645,43 +1729,78 @@ function M.try_trim_markdown_code_blocks(lines)
|
||||
return 'markdown'
|
||||
end
|
||||
|
||||
local str_utfindex = vim.str_utfindex
|
||||
---@private
|
||||
local function make_position_param()
|
||||
local row, col = unpack(api.nvim_win_get_cursor(0))
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
local function make_position_param(window, offset_encoding)
|
||||
window = window or 0
|
||||
local buf = vim.api.nvim_win_get_buf(window)
|
||||
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(0, 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; }
|
||||
end
|
||||
-- TODO handle offset_encoding
|
||||
local _
|
||||
_, col = str_utfindex(line, col)
|
||||
|
||||
col = _str_utfindex_enc(line, col, offset_encoding)
|
||||
|
||||
return { line = row; character = col; }
|
||||
end
|
||||
|
||||
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
|
||||
---
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
---@returns `TextDocumentPositionParams` object
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
|
||||
function M.make_position_params()
|
||||
function M.make_position_params(window, offset_encoding)
|
||||
window = window or 0
|
||||
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();
|
||||
position = make_position_param()
|
||||
textDocument = M.make_text_document_params(buf);
|
||||
position = make_position_param(window, offset_encoding)
|
||||
}
|
||||
end
|
||||
|
||||
--- Utility function for getting the encoding of the first LSP client on the given buffer.
|
||||
---@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};
|
||||
}
|
||||
|
||||
local offset_encoding
|
||||
|
||||
for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do
|
||||
local this_offset_encoding = client.offset_encoding or "utf-16"
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
return offset_encoding
|
||||
end
|
||||
|
||||
--- Using the current position in the current buffer, creates an object that
|
||||
--- can be used as a building block for several LSP requests, such as
|
||||
--- `textDocument/codeAction`, `textDocument/colorPresentation`,
|
||||
--- `textDocument/rangeFormatting`.
|
||||
---
|
||||
---@param window (optional, number): window handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window`
|
||||
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
|
||||
---`current_position`, end = `current_position` } }
|
||||
function M.make_range_params()
|
||||
local position = make_position_param()
|
||||
function M.make_range_params(window, offset_encoding)
|
||||
local buf = vim.api.nvim_win_get_buf(window)
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
local position = make_position_param(window, offset_encoding)
|
||||
return {
|
||||
textDocument = M.make_text_document_params(),
|
||||
textDocument = M.make_text_document_params(buf),
|
||||
range = { start = position; ["end"] = position; }
|
||||
}
|
||||
end
|
||||
@ -1693,27 +1812,29 @@ end
|
||||
---Defaults to the start of the last visual selection.
|
||||
---@param end_pos ({number, number}, optional) mark-indexed position.
|
||||
---Defaults to the end of the last visual selection.
|
||||
---@param bufnr (optional, number): buffer handle or 0 for current, defaults to current
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `bufnr`
|
||||
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
|
||||
---`start_position`, end = `end_position` } }
|
||||
function M.make_given_range_params(start_pos, end_pos)
|
||||
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};
|
||||
}
|
||||
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(0, '<'))
|
||||
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(0, '>'))
|
||||
bufnr = bufnr or 0
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
|
||||
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<'))
|
||||
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>'))
|
||||
-- convert to 0-index
|
||||
A[1] = A[1] - 1
|
||||
B[1] = B[1] - 1
|
||||
-- account for encoding.
|
||||
-- TODO handle offset_encoding
|
||||
-- account for offset_encoding.
|
||||
if A[2] > 0 then
|
||||
local _, char = M.character_offset(0, A[1], A[2])
|
||||
A = {A[1], char}
|
||||
A = {A[1], M.character_offset(bufnr, A[1], A[2], offset_encoding)}
|
||||
end
|
||||
if B[2] > 0 then
|
||||
local _, char = M.character_offset(0, B[1], B[2])
|
||||
B = {B[1], char}
|
||||
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
|
||||
@ -1722,7 +1843,7 @@ function M.make_given_range_params(start_pos, end_pos)
|
||||
B[2] = B[2] + 1
|
||||
end
|
||||
return {
|
||||
textDocument = M.make_text_document_params(),
|
||||
textDocument = M.make_text_document_params(bufnr),
|
||||
range = {
|
||||
start = {line = A[1], character = A[2]},
|
||||
['end'] = {line = B[1], character = B[2]}
|
||||
@ -1732,10 +1853,11 @@ end
|
||||
|
||||
--- Creates a `TextDocumentIdentifier` object for the current buffer.
|
||||
---
|
||||
---@param bufnr (optional, number): Buffer handle, defaults to current
|
||||
---@returns `TextDocumentIdentifier`
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
|
||||
function M.make_text_document_params()
|
||||
return { uri = vim.uri_from_bufnr(0) }
|
||||
function M.make_text_document_params(bufnr)
|
||||
return { uri = vim.uri_from_bufnr(bufnr or 0) }
|
||||
end
|
||||
|
||||
--- Create the workspace params
|
||||
@ -1778,14 +1900,16 @@ end
|
||||
---@param buf buffer id (0 for current)
|
||||
---@param row 0-indexed line
|
||||
---@param col 0-indexed byte offset in line
|
||||
---@returns (number, number) UTF-32 and UTF-16 index of the character in line {row} column {col} in buffer {buf}
|
||||
function M.character_offset(bufnr, row, col)
|
||||
local line = get_line(bufnr, row)
|
||||
---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf`
|
||||
---@returns (number, number) `offset_encoding` index of the character in line {row} column {col} in buffer {buf}
|
||||
function M.character_offset(buf, row, col, offset_encoding)
|
||||
local line = get_line(buf, row)
|
||||
offset_encoding = offset_encoding or M._get_offset_encoding(buf)
|
||||
-- If the col is past the EOL, use the line length.
|
||||
if col > #line then
|
||||
return str_utfindex(line)
|
||||
return _str_utfindex_enc(line, nil, offset_encoding)
|
||||
end
|
||||
return str_utfindex(line, col)
|
||||
return _str_utfindex_enc(line, col, offset_encoding)
|
||||
end
|
||||
|
||||
--- Helper function to return nested values in language server settings
|
||||
|
@ -74,8 +74,8 @@ local function uri_from_fname(path)
|
||||
return table.concat(uri_parts)
|
||||
end
|
||||
|
||||
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*'
|
||||
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):[a-zA-Z]:.*'
|
||||
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*'
|
||||
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
|
||||
|
||||
--- Get a URI from a bufnr
|
||||
---@param bufnr number
|
||||
|
@ -26,7 +26,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release date="2021-12-31" version="0.6.1"/>
|
||||
<release date="2021-11-30" version="0.6.0"/>
|
||||
<release date="2021-09-26" version="0.5.1"/>
|
||||
<release date="2021-07-02" version="0.5.0"/>
|
||||
<release date="2020-08-04" version="0.4.4"/>
|
||||
<release date="2019-11-06" version="0.4.3"/>
|
||||
|
28
runtime/syntax/checkhealth.vim
Normal file
28
runtime/syntax/checkhealth.vim
Normal file
@ -0,0 +1,28 @@
|
||||
" Vim syntax file
|
||||
" Language: Neovim checkhealth buffer
|
||||
" Last Change: 2021 Dec 15
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! syntax/markdown.vim
|
||||
unlet! b:current_syntax
|
||||
|
||||
syn case match
|
||||
|
||||
" We do not care about markdown syntax errors
|
||||
syn clear markdownError
|
||||
|
||||
syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine
|
||||
syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar
|
||||
syn match healthBar "|" contained conceal
|
||||
|
||||
hi def link healthError Error
|
||||
hi def link healthWarning WarningMsg
|
||||
hi def healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
||||
hi def link healthHelp Identifier
|
||||
|
||||
let b:current_syntax = "checkhealth"
|
@ -339,7 +339,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
||||
/// @param col Column where to place the mark, 0-based. |api-indexing|
|
||||
/// @param opts Optional parameters.
|
||||
/// - id : id of the extmark to edit.
|
||||
/// - end_line : ending line of the mark, 0-based inclusive.
|
||||
/// - end_row : ending line of the mark, 0-based inclusive.
|
||||
/// - end_col : ending col of the mark, 0-based exclusive.
|
||||
/// - hl_group : name of the highlight group used to highlight
|
||||
/// this mark.
|
||||
@ -431,16 +431,26 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
|
||||
int line2 = -1;
|
||||
if (opts->end_line.type == kObjectTypeInteger) {
|
||||
Integer val = opts->end_line.data.integer;
|
||||
|
||||
// For backward compatibility we support "end_line" as an alias for "end_row"
|
||||
if (HAS_KEY(opts->end_line)) {
|
||||
if (HAS_KEY(opts->end_row)) {
|
||||
api_set_error(err, kErrorTypeValidation, "cannot use both end_row and end_line");
|
||||
goto error;
|
||||
}
|
||||
opts->end_row = opts->end_line;
|
||||
}
|
||||
|
||||
if (opts->end_row.type == kObjectTypeInteger) {
|
||||
Integer val = opts->end_row.data.integer;
|
||||
if (val < 0 || val > buf->b_ml.ml_line_count) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_line value outside range");
|
||||
api_set_error(err, kErrorTypeValidation, "end_row value outside range");
|
||||
goto error;
|
||||
} else {
|
||||
line2 = (int)val;
|
||||
}
|
||||
} else if (HAS_KEY(opts->end_line)) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_line is not an integer");
|
||||
} else if (HAS_KEY(opts->end_row)) {
|
||||
api_set_error(err, kErrorTypeValidation, "end_row is not an integer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -571,10 +581,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
OPTION_TO_BOOL(right_gravity, right_gravity, true);
|
||||
|
||||
// Only error out if they try to set end_right_gravity without
|
||||
// setting end_col or end_line
|
||||
// setting end_col or end_row
|
||||
if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"cannot set end_right_gravity without setting end_line or end_col");
|
||||
"cannot set end_right_gravity without setting end_row or end_col");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ return {
|
||||
set_extmark = {
|
||||
"id";
|
||||
"end_line";
|
||||
"end_row";
|
||||
"end_col";
|
||||
"hl_group";
|
||||
"virt_text";
|
||||
|
@ -231,8 +231,8 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
if (offset < 0 || offset > (intptr_t)s1_len) {
|
||||
return luaL_error(lstate, "index out of range");
|
||||
}
|
||||
int tail_offset = mb_head_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1);
|
||||
lua_pushinteger(lstate, tail_offset);
|
||||
int head_offset = mb_head_off((char_u *)s1, (char_u *)s1 + offset - 1);
|
||||
lua_pushinteger(lstate, head_offset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
if (offset < 0 || offset > (intptr_t)s1_len) {
|
||||
return luaL_error(lstate, "index out of range");
|
||||
}
|
||||
int tail_offset = mb_tail_off((char_u *)s1, (char_u *)s1 + (char_u)offset - 1);
|
||||
int tail_offset = mb_tail_off((char_u *)s1, (char_u *)s1 + offset - 1);
|
||||
lua_pushinteger(lstate, tail_offset);
|
||||
return 1;
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ end
|
||||
--- Without a runtime, writes to :Messages
|
||||
---@see :help nvim_notify
|
||||
---@param msg string Content of the notification to show to the user
|
||||
---@param log_level number|nil enum from vim.log.levels
|
||||
---@param log_level number|nil enum from |vim.log.levels|
|
||||
---@param opts table|nil additional options (timeout, etc)
|
||||
function vim.notify(msg, log_level, opts) -- luacheck: no unused
|
||||
if log_level == vim.log.levels.ERROR then
|
||||
|
@ -1011,7 +1011,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
|
||||
col -= wp->w_leftcol;
|
||||
|
||||
if (col >= 0 && col < wp->w_width) {
|
||||
coloff = col - scol + (local ? 0 : wp->w_wincol) + 1;
|
||||
coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_border_adj[3]) + 1;
|
||||
} else {
|
||||
scol = ccol = ecol = 0;
|
||||
// character is left or right of the window
|
||||
@ -1022,7 +1022,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
|
||||
}
|
||||
}
|
||||
}
|
||||
*rowp = (local ? 0 : wp->w_winrow) + row + rowoff;
|
||||
*rowp = (local ? 0 : wp->w_winrow + wp->w_border_adj[0]) + row + rowoff;
|
||||
*scolp = scol + coloff;
|
||||
*ccolp = ccol + coloff;
|
||||
*ecolp = ecol + coloff;
|
||||
|
@ -2953,7 +2953,7 @@ ambw_end:
|
||||
}
|
||||
} else if (varp == &curwin->w_p_fdc || varp == &curwin->w_allbuf_opt.wo_fdc) {
|
||||
// 'foldcolumn'
|
||||
if (check_opt_strings(*varp, p_fdc_values, false) != OK) {
|
||||
if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
} else if (varp == &p_pt) {
|
||||
@ -3332,6 +3332,9 @@ static int int_cmp(const void *a, const void *b)
|
||||
/// @return OK when the value is valid, FAIL otherwise
|
||||
int check_signcolumn(char_u *val)
|
||||
{
|
||||
if (*val == NUL) {
|
||||
return FAIL;
|
||||
}
|
||||
// check for basic match
|
||||
if (check_opt_strings(val, p_scl_values, false) == OK) {
|
||||
return OK;
|
||||
|
@ -658,7 +658,8 @@ static int qf_get_next_str_line(qfstate_T *state)
|
||||
state->linebuf = IObuff;
|
||||
state->linelen = len;
|
||||
}
|
||||
STRLCPY(state->linebuf, p_str, state->linelen + 1);
|
||||
memcpy(state->linebuf, p_str, state->linelen);
|
||||
state->linebuf[state->linelen] = '\0';
|
||||
|
||||
// Increment using len in order to discard the rest of the line if it
|
||||
// exceeds LINE_MAXLEN.
|
||||
|
@ -5248,6 +5248,9 @@ search_line:
|
||||
if (depth == -1) {
|
||||
// match in current file
|
||||
if (l_g_do_tagpreview != 0) {
|
||||
if (!win_valid(curwin_save)) {
|
||||
break;
|
||||
}
|
||||
if (!GETFILE_SUCCESS(getfile(curwin_save->w_buffer->b_fnum, NULL,
|
||||
NULL, true, lnum, false))) {
|
||||
break; // failed to jump to file
|
||||
|
@ -1466,6 +1466,17 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
|
||||
int width, height;
|
||||
vterm_get_size(term->vt, &height, &width);
|
||||
|
||||
// May still have pending scrollback after increase in terminal height if the
|
||||
// scrollback wasn't refreshed in time; append these to the top of the buffer.
|
||||
int row_offset = term->sb_pending;
|
||||
while (term->sb_pending > 0 && buf->b_ml.ml_line_count < height) {
|
||||
fetch_row(term, term->sb_pending - row_offset - 1, width);
|
||||
ml_append(0, (uint8_t *)term->textbuf, 0, false);
|
||||
appended_lines(0, 1);
|
||||
term->sb_pending--;
|
||||
}
|
||||
|
||||
row_offset -= term->sb_pending;
|
||||
while (term->sb_pending > 0) {
|
||||
// This means that either the window height has decreased or the screen
|
||||
// became full and libvterm had to push all rows up. Convert the first
|
||||
@ -1476,7 +1487,7 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
|
||||
ml_delete(1, false);
|
||||
deleted_lines(1, 1);
|
||||
}
|
||||
fetch_row(term, -term->sb_pending, width);
|
||||
fetch_row(term, -term->sb_pending - row_offset, width);
|
||||
int buf_index = (int)buf->b_ml.ml_line_count - height;
|
||||
ml_append(buf_index, (uint8_t *)term->textbuf, 0, false);
|
||||
appended_lines(buf_index, 1);
|
||||
|
@ -33,7 +33,7 @@ if has('timers')
|
||||
let g:triggered = 0
|
||||
au CursorHoldI * let g:triggered += 1
|
||||
set updatetime=20
|
||||
call timer_start(LoadAdjust(100), 'ExitInsertMode')
|
||||
call timer_start(LoadAdjust(200), 'ExitInsertMode')
|
||||
call feedkeys('a', 'x!')
|
||||
call assert_equal(1, g:triggered)
|
||||
unlet g:triggered
|
||||
@ -1897,6 +1897,26 @@ func Test_autocmd_CmdWinEnter()
|
||||
call delete(filename)
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_was_using_freed_memory()
|
||||
pedit xx
|
||||
n x
|
||||
augroup winenter
|
||||
au WinEnter * if winnr('$') > 2 | quit | endif
|
||||
augroup END
|
||||
" Nvim needs large 'winwidth' and 'nowinfixwidth' to crash
|
||||
set winwidth=99999 nowinfixwidth
|
||||
split
|
||||
|
||||
augroup winenter
|
||||
au! WinEnter
|
||||
augroup END
|
||||
|
||||
set winwidth& winfixwidth&
|
||||
bwipe xx
|
||||
bwipe x
|
||||
pclose
|
||||
endfunc
|
||||
|
||||
func Test_FileChangedShell_reload()
|
||||
if !has('unix')
|
||||
return
|
||||
@ -2125,6 +2145,19 @@ func Test_autocmd_closes_window()
|
||||
au! BufWinLeave
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_quit_psearch()
|
||||
sn aa bb
|
||||
augroup aucmd_win_test
|
||||
au!
|
||||
au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif
|
||||
augroup END
|
||||
ps /
|
||||
|
||||
augroup aucmd_win_test
|
||||
au!
|
||||
augroup END
|
||||
endfunc
|
||||
|
||||
func Test_autocmd_closing_cmdwin()
|
||||
au BufWinLeave * nested q
|
||||
call assert_fails("norm 7q?\n", 'E855:')
|
||||
|
@ -4525,6 +4525,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
||||
|
||||
fix_current_dir();
|
||||
|
||||
// Careful: autocommands may close the window and make "wp" invalid
|
||||
if (flags & WEE_TRIGGER_NEW_AUTOCMDS) {
|
||||
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
|
||||
}
|
||||
@ -4558,7 +4559,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
||||
}
|
||||
|
||||
// set window width to desired minimal value
|
||||
if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !wp->w_floating) {
|
||||
if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !curwin->w_floating) {
|
||||
win_setwidth((int)p_wiw);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ Filtering Tests
|
||||
|
||||
### Filter by name
|
||||
|
||||
Another filter method is by setting a pattern of test name to `TEST_FILTER`.
|
||||
Another filter method is by setting a pattern of test name to `TEST_FILTER` or `TEST_FILTER_OUT`.
|
||||
|
||||
``` lua
|
||||
it('foo api',function()
|
||||
@ -131,6 +131,10 @@ To run only test with filter name:
|
||||
|
||||
TEST_FILTER='foo.*api' make functionaltest
|
||||
|
||||
To run all tests except ones matching a filter:
|
||||
|
||||
TEST_FILTER_OUT='foo.*api' make functionaltest
|
||||
|
||||
### Filter by file
|
||||
|
||||
To run a *specific* unit test:
|
||||
|
@ -104,10 +104,10 @@ describe('API/extmarks', function()
|
||||
it("can end extranges past final newline using end_col = 0", function()
|
||||
set_extmark(ns, marks[1], 0, 0, {
|
||||
end_col = 0,
|
||||
end_line = 1
|
||||
end_row = 1
|
||||
})
|
||||
eq("end_col value outside range",
|
||||
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_line = 1 }))
|
||||
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
|
||||
end)
|
||||
|
||||
it('adds, updates and deletes marks', function()
|
||||
@ -1424,6 +1424,14 @@ describe('API/extmarks', function()
|
||||
eq({ {1, 0, 0}, {2, 0, 8} },
|
||||
meths.buf_get_extmarks(0, ns, 0, -1, {}))
|
||||
end)
|
||||
|
||||
it('can accept "end_row" or "end_line" #16548', function()
|
||||
set_extmark(ns, marks[1], 0, 0, {
|
||||
end_col = 0,
|
||||
end_line = 1
|
||||
})
|
||||
eq({ {1, 0, 0, { end_col = 0, end_row = 1 }} }, get_extmarks(ns, 0, -1, {details=true}))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Extmarks buffer api with many marks', function()
|
||||
|
@ -83,4 +83,9 @@ describe('set', function()
|
||||
Press ENTER or type command to continue^ |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('foldcolumn and signcolumn to empty string is disallowed', function()
|
||||
matches('E474: Invalid argument: fdc=', exc_exec('set fdc='))
|
||||
matches('E474: Invalid argument: scl=', exc_exec('set scl='))
|
||||
end)
|
||||
end)
|
||||
|
@ -1343,7 +1343,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = "We're no strangers to love..."})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = "We're no strangers to love..."})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1355,7 +1355,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = {'You know the rules', 'Search'}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = {'You know the rules', 'Search'}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1370,7 +1370,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope="buffer"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope="buffer"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1387,7 +1387,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {2, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1402,7 +1402,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, pos=1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, pos=1})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1419,7 +1419,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {2, 2})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1434,7 +1434,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor", pos={1,3}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor", pos={1,3}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1449,7 +1449,7 @@ describe('vim.diagnostic', function()
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
vim.api.nvim_win_set_cursor(0, {1, 1})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor", pos={0,first_line_len}})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor", pos={0,first_line_len}})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1665,7 +1665,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer"})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope = "buffer"})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1678,7 +1678,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer", prefix = ""})
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({header = false, scope = "buffer", prefix = ""})
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
@ -1691,7 +1691,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({
|
||||
header = false,
|
||||
prefix = function(_, i, total)
|
||||
-- Only show a number if there is more than one diagnostic
|
||||
@ -1712,7 +1712,7 @@ describe('vim.diagnostic', function()
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, {
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float({
|
||||
header = false,
|
||||
prefix = function(_, i, total)
|
||||
-- Only show a number if there is more than one diagnostic
|
||||
@ -1728,7 +1728,21 @@ describe('vim.diagnostic', function()
|
||||
]])
|
||||
|
||||
eq("Error executing lua: .../diagnostic.lua:0: prefix: expected 'string' or 'table' or 'function', got 42",
|
||||
pcall_err(exec_lua, [[ vim.diagnostic.open_float(0, { prefix = 42 }) ]]))
|
||||
pcall_err(exec_lua, [[ vim.diagnostic.open_float({ prefix = 42 }) ]]))
|
||||
end)
|
||||
|
||||
it('works with the old signature', function()
|
||||
eq({'1. Syntax error'}, exec_lua [[
|
||||
local diagnostics = {
|
||||
make_error("Syntax error", 0, 1, 0, 3),
|
||||
}
|
||||
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
|
||||
local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
|
||||
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
|
||||
vim.api.nvim_win_close(winnr, true)
|
||||
return lines
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -1918,5 +1932,27 @@ describe('vim.diagnostic', function()
|
||||
return {show_called, hide_called}
|
||||
]])
|
||||
end)
|
||||
|
||||
it('triggers the autocommand when diagnostics are set', function()
|
||||
eq(1, exec_lua [[
|
||||
vim.g.diagnostic_autocmd_triggered = 0
|
||||
vim.cmd('autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = 1')
|
||||
vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test")
|
||||
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
|
||||
make_error('Diagnostic', 0, 0, 0, 0)
|
||||
})
|
||||
return vim.g.diagnostic_autocmd_triggered
|
||||
]])
|
||||
end)
|
||||
|
||||
it('triggers the autocommand when diagnostics are cleared', function()
|
||||
eq(1, exec_lua [[
|
||||
vim.g.diagnostic_autocmd_triggered = 0
|
||||
vim.cmd('autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = 1')
|
||||
vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test")
|
||||
vim.diagnostic.reset(diagnostic_ns, diagnostic_bufnr)
|
||||
return vim.g.diagnostic_autocmd_triggered
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -155,6 +155,12 @@ describe('URI methods', function()
|
||||
return pcall(vim.uri_to_fname, 'not_an_uri.txt')
|
||||
]])
|
||||
end)
|
||||
|
||||
it('uri_to_fname should not treat comma as a scheme character', function()
|
||||
eq(false, exec_lua [[
|
||||
return pcall(vim.uri_to_fname, 'foo,://bar')
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -156,7 +156,7 @@ describe('health.vim', function()
|
||||
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
|
||||
function health#check, line 24]])
|
||||
function health#check, line 20]])
|
||||
eq(expected, received)
|
||||
end)
|
||||
|
||||
@ -167,7 +167,7 @@ describe('health.vim', function()
|
||||
broken: health#broken#check
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
|
||||
function health#check[24]..health#broken#check, line 1
|
||||
function health#check[20]..health#broken#check, line 1
|
||||
caused an error
|
||||
]])
|
||||
end)
|
||||
@ -186,7 +186,7 @@ describe('health.vim', function()
|
||||
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
|
||||
========================================================================
|
||||
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
|
||||
function health#check, line 24]])
|
||||
function health#check, line 20]])
|
||||
eq(expected, received)
|
||||
end)
|
||||
|
||||
|
@ -164,6 +164,201 @@ describe('incremental synchronization', function()
|
||||
}
|
||||
test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting a line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 0
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 12,
|
||||
text = ''
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"dd"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting an empty line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = ''
|
||||
}
|
||||
}
|
||||
test_edit({"hello world", ""}, {"jdd"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('adding a line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = 'hello world\n'
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"yyp"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('adding an empty line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = '\n'
|
||||
}
|
||||
}
|
||||
test_edit({"hello world"}, {"o"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
end)
|
||||
describe('multi line edit', function()
|
||||
it('deletion and insertion', function()
|
||||
local expected_text_changes = {
|
||||
-- delete "_fsda" from end of line 1
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 5,
|
||||
text = ''
|
||||
},
|
||||
-- delete "hello world\n" from line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 12,
|
||||
text = ''
|
||||
},
|
||||
-- delete "1234" from beginning of line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 4,
|
||||
line = 2
|
||||
}
|
||||
},
|
||||
rangeLength = 4,
|
||||
text = ''
|
||||
},
|
||||
-- add " asdf" to end of line 1
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = ' asdf'
|
||||
},
|
||||
-- delete " asdf\n" from line 2
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 2
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 6,
|
||||
text = ''
|
||||
},
|
||||
-- undo entire deletion
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 5,
|
||||
text = "_fdsa\nhello world\n1234 asdf"
|
||||
},
|
||||
-- redo entire deletion
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 4,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 9,
|
||||
line = 3
|
||||
}
|
||||
},
|
||||
rangeLength = 27,
|
||||
text = ' asdf'
|
||||
},
|
||||
}
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"test_fdsa",
|
||||
"hello world",
|
||||
"1234 asdf",
|
||||
"\\end{document}"
|
||||
}
|
||||
test_edit(original_lines, {"jf_vejjbhhdu<C-R>"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('multi-operation edits', function()
|
||||
@ -297,6 +492,80 @@ describe('incremental synchronization', function()
|
||||
}
|
||||
test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('replacing a multibyte character with matching prefix', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 1,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = '⟩'
|
||||
}
|
||||
}
|
||||
-- ⟨ is e29fa8, ⟩ is e29fa9
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"⟨",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"jr⟩"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('replacing a multibyte character with matching suffix', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 1,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 1,
|
||||
text = 'ḟ'
|
||||
}
|
||||
}
|
||||
-- ฟ is e0b89f, ḟ is e1b89f
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"ฟ",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"jrḟ"}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('inserting before a multibyte character', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
range = {
|
||||
['start'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
},
|
||||
['end'] = {
|
||||
character = 0,
|
||||
line = 1
|
||||
}
|
||||
},
|
||||
rangeLength = 0,
|
||||
text = ' '
|
||||
}
|
||||
}
|
||||
local original_lines = {
|
||||
"\\begin{document}",
|
||||
"→",
|
||||
"\\end{document}",
|
||||
}
|
||||
test_edit(original_lines, {"ji "}, expected_text_changes, 'utf-16', '\n')
|
||||
end)
|
||||
it('deleting a multibyte character from a long line', function()
|
||||
local expected_text_changes = {
|
||||
{
|
||||
|
@ -301,6 +301,43 @@ describe('LSP', function()
|
||||
}
|
||||
end)
|
||||
|
||||
it('should detach buffer in response to nvim_buf_detach', function()
|
||||
local expected_handlers = {
|
||||
{NIL, {}, {method="shutdown", client_id=1}};
|
||||
{NIL, {}, {method="finish", client_id=1}};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_finish";
|
||||
on_setup = function()
|
||||
exec_lua [[
|
||||
BUFFER = vim.api.nvim_create_buf(false, true)
|
||||
]]
|
||||
eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
exec_lua [[
|
||||
vim.api.nvim_command(BUFFER.."bwipeout")
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
client.notify('finish')
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code", fake_lsp_logfile)
|
||||
eq(0, signal, "exit signal", fake_lsp_logfile)
|
||||
end;
|
||||
on_handler = function(err, result, ctx)
|
||||
eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
|
||||
if ctx.method == 'finish' then
|
||||
exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
|
||||
eq(false, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('client should return settings via workspace/configuration handler', function()
|
||||
local expected_handlers = {
|
||||
{NIL, {}, {method="shutdown", client_id=1}};
|
||||
|
@ -12,6 +12,8 @@ local curbufmeths = helpers.curbufmeths
|
||||
local nvim = helpers.nvim
|
||||
local feed_data = thelpers.feed_data
|
||||
local pcall_err = helpers.pcall_err
|
||||
local exec_lua = helpers.exec_lua
|
||||
local assert_alive = helpers.assert_alive
|
||||
|
||||
describe(':terminal scrollback', function()
|
||||
local screen
|
||||
@ -527,3 +529,71 @@ describe("'scrollback' option", function()
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
describe("pending scrollback line handling", function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(30, 7)
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids {
|
||||
[1] = {foreground = Screen.colors.Brown},
|
||||
[2] = {reverse = true},
|
||||
[3] = {bold = true},
|
||||
}
|
||||
end)
|
||||
|
||||
it("does not crash after setting 'number' #14891", function()
|
||||
exec_lua [[
|
||||
local a = vim.api
|
||||
local buf = a.nvim_create_buf(true, true)
|
||||
local chan = a.nvim_open_term(buf, {})
|
||||
a.nvim_win_set_option(0, "number", true)
|
||||
a.nvim_chan_send(chan, ("a\n"):rep(11) .. "a")
|
||||
a.nvim_win_set_buf(0, buf)
|
||||
]]
|
||||
screen:expect [[
|
||||
{1: 1 }^a |
|
||||
{1: 2 } a |
|
||||
{1: 3 } a |
|
||||
{1: 4 } a |
|
||||
{1: 5 } a |
|
||||
{1: 6 } a |
|
||||
|
|
||||
]]
|
||||
feed('G')
|
||||
screen:expect [[
|
||||
{1: 7 } a |
|
||||
{1: 8 } a |
|
||||
{1: 9 } a |
|
||||
{1: 10 } a |
|
||||
{1: 11 } a |
|
||||
{1: 12 } ^a |
|
||||
|
|
||||
]]
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it("does not crash after nvim_buf_call #14891", function()
|
||||
exec_lua [[
|
||||
local a = vim.api
|
||||
local bufnr = a.nvim_create_buf(false, true)
|
||||
a.nvim_buf_call(bufnr, function()
|
||||
vim.fn.termopen({"echo", ("hi\n"):rep(11)})
|
||||
end)
|
||||
a.nvim_win_set_buf(0, bufnr)
|
||||
vim.cmd("startinsert")
|
||||
]]
|
||||
screen:expect [[
|
||||
hi |
|
||||
hi |
|
||||
hi |
|
||||
|
|
||||
|
|
||||
[Process exited 0]{2: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]]
|
||||
assert_alive()
|
||||
end)
|
||||
end)
|
||||
|
51
test/functional/vimscript/screenpos_spec.lua
Normal file
51
test/functional/vimscript/screenpos_spec.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear, eq, meths = helpers.clear, helpers.eq, helpers.meths
|
||||
local command, funcs = helpers.command, helpers.funcs
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('screenpos() function', function()
|
||||
it('works in floating window with border', function()
|
||||
local bufnr = meths.create_buf(false, true)
|
||||
local opts = {
|
||||
relative='editor',
|
||||
height=8,
|
||||
width=12,
|
||||
row=6,
|
||||
col=8,
|
||||
anchor='NW',
|
||||
style='minimal',
|
||||
border='none',
|
||||
focusable=1
|
||||
}
|
||||
local float = meths.open_win(bufnr, false, opts)
|
||||
command('redraw')
|
||||
local pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(7, pos.row)
|
||||
eq(9, pos.col)
|
||||
|
||||
-- only left border
|
||||
opts.border = {'', '', '', '', '', '', '', '|'}
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(7, pos.row)
|
||||
eq(10, pos.col)
|
||||
|
||||
-- only top border
|
||||
opts.border = {'', '_', '', '', '', '', '', ''}
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(8, pos.row)
|
||||
eq(9, pos.col)
|
||||
|
||||
-- both left and top border
|
||||
opts.border = 'single'
|
||||
meths.win_set_config(float, opts)
|
||||
command('redraw')
|
||||
pos = funcs.screenpos(bufnr, 1, 1)
|
||||
eq(8, pos.row)
|
||||
eq(10, pos.col)
|
||||
end)
|
||||
end)
|
Reference in New Issue
Block a user