mirror of https://github.com/neovim/neovim.git
Compare commits
18 Commits
4aa437d95a
...
8a78915089
Author | SHA1 | Date |
---|---|---|
James | 8a78915089 | |
zeertzjq | 435dee74bb | |
zeertzjq | 694756252b | |
zeertzjq | e81eb34aa1 | |
zeertzjq | a1568f5df0 | |
zeertzjq | f1f5fb911b | |
Mathias Fußenegger | 9b8a075539 | |
Gregory Anders | 73034611c2 | |
Brian Cao | 3a7c30dc93 | |
Gregory Anders | 6888607415 | |
Justin M. Keyes | 9b028bd64f | |
Lewis Russell | b2c26a875b | |
Lewis Russell | b8273c9a33 | |
TheLeoP | c5b9fb2f25 | |
Gregory Anders | 37d8e50459 | |
Yi Ming | 567f8a300b | |
Mathias Fußenegger | 47dbda97d2 | |
James Tirta Halim | 77c10671ed |
|
@ -49,6 +49,8 @@ endif()
|
|||
check_function_exists(fseeko HAVE_FSEEKO)
|
||||
check_function_exists(readv HAVE_READV)
|
||||
check_function_exists(readlink HAVE_READLINK)
|
||||
check_function_exists(stpcpy HAVE_STPCPY)
|
||||
check_function_exists(stpncpy HAVE_STPNCPY)
|
||||
check_function_exists(strnlen HAVE_STRNLEN)
|
||||
check_function_exists(strcasecmp HAVE_STRCASECMP)
|
||||
check_function_exists(strncasecmp HAVE_STRNCASECMP)
|
||||
|
|
|
@ -8208,6 +8208,10 @@ synconcealed({lnum}, {col}) *synconcealed()*
|
|||
synconcealed(lnum, 5) [1, 'X', 2]
|
||||
synconcealed(lnum, 6) [0, '', 0]
|
||||
|
||||
Note: Doesn't consider |matchadd()| highlighting items,
|
||||
since syntax and matching highlighting are two different
|
||||
mechanisms |syntax-vs-match|.
|
||||
|
||||
synstack({lnum}, {col}) *synstack()*
|
||||
Return a |List|, which is the stack of syntax items at the
|
||||
position {lnum} and {col} in the current window. {lnum} is
|
||||
|
|
|
@ -281,6 +281,10 @@ gr{char} Replace the virtual characters under the cursor with
|
|||
that have a special meaning in Insert mode, such as
|
||||
most CTRL-keys, cannot be used.
|
||||
|
||||
*gr-default*
|
||||
Mapped to |vim.lsp.buf.references()| by default.
|
||||
|default-mappings|
|
||||
|
||||
*digraph-arg*
|
||||
The argument for Normal mode commands like |r| and |t| is a single character.
|
||||
When 'cpo' doesn't contain the 'D' flag, this character can also be entered
|
||||
|
|
|
@ -61,47 +61,41 @@ options are not restored when the LSP client is stopped or detached.
|
|||
- |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or
|
||||
a custom keymap for `K` exists.
|
||||
|
||||
*crr* *v_crr* *crn* *i_CTRL-S*
|
||||
Some keymaps are created unconditionally when Nvim starts:
|
||||
- "crn" is mapped in Normal mode to |vim.lsp.buf.rename()|
|
||||
- "crr" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
|
||||
- "gr" is mapped in Normal mode to |vim.lsp.buf.references()| |gr-default|
|
||||
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
|
||||
|
||||
If not wanted, these keymaps can be removed at any time using
|
||||
|vim.keymap.del()| or |:unmap|.
|
||||
|
||||
*lsp-defaults-disable*
|
||||
To override the above defaults, set or unset the options on |LspAttach|: >lua
|
||||
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(ev)
|
||||
vim.bo[ev.buf].formatexpr = nil
|
||||
vim.bo[ev.buf].omnifunc = nil
|
||||
vim.keymap.del("n", "K", { buffer = ev.buf })
|
||||
vim.keymap.del('n', 'K', { buffer = ev.buf })
|
||||
end,
|
||||
})
|
||||
|
||||
To use other LSP features like hover, rename, etc. you can set other keymaps
|
||||
on |LspAttach|. Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf })
|
||||
end,
|
||||
})
|
||||
To use other LSP features, set keymaps on |LspAttach|. Not all language
|
||||
servers provide the same capabilities. To ensure you only set keymaps if the
|
||||
language server supports a feature, guard keymaps behind capability checks.
|
||||
Example: >lua
|
||||
|
||||
The most common functions are:
|
||||
|
||||
- |vim.lsp.buf.hover()|
|
||||
- |vim.lsp.buf.format()|
|
||||
- |vim.lsp.buf.references()|
|
||||
- |vim.lsp.buf.implementation()|
|
||||
- |vim.lsp.buf.code_action()|
|
||||
|
||||
|
||||
Not all language servers provide the same capabilities. To ensure you only set
|
||||
keymaps if the language server supports a feature, you can guard the keymap
|
||||
calls behind capability checks:
|
||||
>lua
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
if client.server_capabilities.hoverProvider then
|
||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf })
|
||||
if client.supports_method('textDocument/implementation') then
|
||||
vim.keymap.set('n', 'g<C-I>', vim.lsp.buf.implementation, { buffer = args.buf })
|
||||
end
|
||||
end,
|
||||
})
|
||||
<
|
||||
|
||||
To learn what capabilities are available you can run the following command in
|
||||
a buffer with a started LSP client: >vim
|
||||
|
||||
|
@ -869,12 +863,14 @@ start({config}, {opts}) *vim.lsp.start()*
|
|||
|vim.lsp.ClientConfig|.
|
||||
• {opts} (`table?`) Optional keyword arguments
|
||||
• {reuse_client}
|
||||
(`fun(client: vim.lsp.Client, config: table): boolean`)
|
||||
(`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`)
|
||||
Predicate used to decide if a client should be re-used.
|
||||
Used on all running clients. The default implementation
|
||||
re-uses a client if name and root_dir matches.
|
||||
• {bufnr} (`integer`) Buffer handle to attach to if starting
|
||||
or re-using a client (0 for current).
|
||||
• {silent}? (`boolean`) Suppress error reporting if the LSP
|
||||
server fails to start (default false).
|
||||
|
||||
Return: ~
|
||||
(`integer?`) client_id
|
||||
|
@ -886,10 +882,11 @@ start_client({config}) *vim.lsp.start_client()*
|
|||
• {config} (`vim.lsp.ClientConfig`) Configuration for the server. See
|
||||
|vim.lsp.ClientConfig|.
|
||||
|
||||
Return: ~
|
||||
Return (multiple): ~
|
||||
(`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may
|
||||
not be fully initialized. Use `on_init` to do any actions once the
|
||||
client has been initialized.
|
||||
(`string?`) Error message, if any
|
||||
|
||||
status() *vim.lsp.status()*
|
||||
Consumes the latest progress messages from all clients and formats them as
|
||||
|
@ -1073,7 +1070,7 @@ Lua module: vim.lsp.client *lsp-client*
|
|||
*vim.lsp.ClientConfig*
|
||||
|
||||
Fields: ~
|
||||
• {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?`)
|
||||
• {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
||||
command string[] that launches the language
|
||||
server (treated as in |jobstart()|, must be
|
||||
absolute or on `$PATH`, shell constructs like
|
||||
|
@ -2340,7 +2337,7 @@ start({cmd}, {dispatchers}, {extra_spawn_params}) *vim.lsp.rpc.start()*
|
|||
See |vim.system()|
|
||||
|
||||
Return: ~
|
||||
(`vim.lsp.rpc.PublicClient?`) Client RPC object, with these methods:
|
||||
(`vim.lsp.rpc.PublicClient`) Client RPC object, with these methods:
|
||||
• `notify()` |vim.lsp.rpc.notify()|
|
||||
• `request()` |vim.lsp.rpc.request()|
|
||||
• `is_closing()` returns a boolean indicating if the RPC is closing.
|
||||
|
|
|
@ -678,44 +678,47 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
|
|||
Parameters: ~
|
||||
• {a} (`string`) First string to compare
|
||||
• {b} (`string`) Second string to compare
|
||||
• {opts} (`table<string,any>`) Optional parameters:
|
||||
• `on_hunk` (callback): Invoked for each hunk in the diff.
|
||||
Return a negative number to cancel the callback for any
|
||||
remaining hunks. Args:
|
||||
• `start_a` (integer): Start line of hunk in {a}.
|
||||
• `count_a` (integer): Hunk size in {a}.
|
||||
• `start_b` (integer): Start line of hunk in {b}.
|
||||
• `count_b` (integer): Hunk size in {b}.
|
||||
• `result_type` (string): Form of the returned diff:
|
||||
• "unified": (default) String in unified format.
|
||||
• "indices": Array of hunk locations. Note: This option is
|
||||
• {opts} (`table`) Optional parameters:
|
||||
• {on_hunk}
|
||||
(`fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer`)
|
||||
Invoked for each hunk in the diff. Return a negative number
|
||||
to cancel the callback for any remaining hunks. Arguments:
|
||||
• `start_a` (`integer`): Start line of hunk in {a}.
|
||||
• `count_a` (`integer`): Hunk size in {a}.
|
||||
• `start_b` (`integer`): Start line of hunk in {b}.
|
||||
• `count_b` (`integer`): Hunk size in {b}.
|
||||
• {result_type} (`'unified'|'indices'`, default: `'unified'`)
|
||||
Form of the returned diff:
|
||||
• `unified`: String in unified format.
|
||||
• `indices`: Array of hunk locations. Note: This option is
|
||||
ignored if `on_hunk` is used.
|
||||
• `linematch` (boolean|integer): Run linematch on the
|
||||
• {linematch} (`boolean|integer`) Run linematch on the
|
||||
resulting hunks from xdiff. When integer, only hunks upto
|
||||
this size in lines are run through linematch. Requires
|
||||
`result_type = indices`, ignored otherwise.
|
||||
• `algorithm` (string): Diff algorithm to use. Values:
|
||||
• "myers" the default algorithm
|
||||
• "minimal" spend extra time to generate the smallest
|
||||
• {algorithm} (`'myers'|'minimal'|'patience'|'histogram'`,
|
||||
default: `'myers'`) Diff algorithm to use. Values:
|
||||
• `myers`: the default algorithm
|
||||
• `minimal`: spend extra time to generate the smallest
|
||||
possible diff
|
||||
• "patience" patience diff algorithm
|
||||
• "histogram" histogram diff algorithm
|
||||
• `ctxlen` (integer): Context length
|
||||
• `interhunkctxlen` (integer): Inter hunk context length
|
||||
• `ignore_whitespace` (boolean): Ignore whitespace
|
||||
• `ignore_whitespace_change` (boolean): Ignore whitespace
|
||||
• `patience`: patience diff algorithm
|
||||
• `histogram`: histogram diff algorithm
|
||||
• {ctxlen} (`integer`) Context length
|
||||
• {interhunkctxlen} (`integer`) Inter hunk context length
|
||||
• {ignore_whitespace} (`boolean`) Ignore whitespace
|
||||
• {ignore_whitespace_change} (`boolean`) Ignore whitespace
|
||||
change
|
||||
• `ignore_whitespace_change_at_eol` (boolean) Ignore
|
||||
• {ignore_whitespace_change_at_eol} (`boolean`) Ignore
|
||||
whitespace change at end-of-line.
|
||||
• `ignore_cr_at_eol` (boolean) Ignore carriage return at
|
||||
• {ignore_cr_at_eol} (`boolean`) Ignore carriage return at
|
||||
end-of-line
|
||||
• `ignore_blank_lines` (boolean) Ignore blank lines
|
||||
• `indent_heuristic` (boolean): Use the indent heuristic for
|
||||
• {ignore_blank_lines} (`boolean`) Ignore blank lines
|
||||
• {indent_heuristic} (`boolean`) Use the indent heuristic for
|
||||
the internal diff library.
|
||||
|
||||
Return: ~
|
||||
(`string|table?`) See {opts.result_type}. `nil` if {opts.on_hunk} is
|
||||
given.
|
||||
(`string|integer[]`) See {opts.result_type}. `nil` if {opts.on_hunk}
|
||||
is given.
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
@ -829,8 +832,8 @@ vim.spell.check({str}) *vim.spell.check()*
|
|||
• {str} (`string`)
|
||||
|
||||
Return: ~
|
||||
(`{[1]: string, [2]: string, [3]: string}[]`) List of tuples with
|
||||
three items:
|
||||
(`{[1]: string, [2]: 'bad'|'rare'|'local'|'caps', [3]: integer}[]`)
|
||||
List of tuples with three items:
|
||||
• The badly spelled word.
|
||||
• The type of the spelling error: "bad" spelling mistake "rare" rare
|
||||
word "local" word only valid in another region "caps" word should
|
||||
|
@ -911,7 +914,7 @@ vim.empty_dict() *vim.empty_dict()*
|
|||
Return: ~
|
||||
(`table`)
|
||||
|
||||
vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()*
|
||||
vim.iconv({str}, {from}, {to}) *vim.iconv()*
|
||||
The result is a String, which is the text {str} converted from encoding
|
||||
{from} to encoding {to}. When the conversion fails `nil` is returned. When
|
||||
some characters could not be converted they are replaced with "?". The
|
||||
|
@ -920,9 +923,8 @@ vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()*
|
|||
|
||||
Parameters: ~
|
||||
• {str} (`string`) Text to convert
|
||||
• {from} (`number`) Encoding of {str}
|
||||
• {to} (`number`) Target encoding
|
||||
• {opts} (`table<string,any>?`)
|
||||
• {from} (`string`) Encoding of {str}
|
||||
• {to} (`string`) Target encoding
|
||||
|
||||
Return: ~
|
||||
(`string?`) Converted string if conversion succeeds, `nil` otherwise.
|
||||
|
@ -962,7 +964,7 @@ vim.schedule({fn}) *vim.schedule()*
|
|||
|textlock| or other temporary restrictions.
|
||||
|
||||
Parameters: ~
|
||||
• {fn} (`function`)
|
||||
• {fn} (`fun()`)
|
||||
|
||||
vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()*
|
||||
Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not
|
||||
|
@ -974,8 +976,8 @@ vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()*
|
|||
|
||||
Parameters: ~
|
||||
• {str} (`string`)
|
||||
• {index} (`number`)
|
||||
• {use_utf16} (`any?`)
|
||||
• {index} (`integer`)
|
||||
• {use_utf16} (`boolean?`)
|
||||
|
||||
vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
|
||||
Gets the distance (in bytes) from the last byte of the codepoint
|
||||
|
@ -993,10 +995,10 @@ vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
|
|||
|
||||
Parameters: ~
|
||||
• {str} (`string`)
|
||||
• {index} (`number`)
|
||||
• {index} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`number`)
|
||||
(`integer`)
|
||||
|
||||
vim.str_utf_pos({str}) *vim.str_utf_pos()*
|
||||
Gets a list of the starting byte positions of each UTF-8 codepoint in the
|
||||
|
@ -1008,7 +1010,7 @@ vim.str_utf_pos({str}) *vim.str_utf_pos()*
|
|||
• {str} (`string`)
|
||||
|
||||
Return: ~
|
||||
(`table`)
|
||||
(`integer[]`)
|
||||
|
||||
vim.str_utf_start({str}, {index}) *vim.str_utf_start()*
|
||||
Gets the distance (in bytes) from the starting byte of the codepoint
|
||||
|
@ -1029,10 +1031,10 @@ vim.str_utf_start({str}, {index}) *vim.str_utf_start()*
|
|||
|
||||
Parameters: ~
|
||||
• {str} (`string`)
|
||||
• {index} (`number`)
|
||||
• {index} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`number`)
|
||||
(`integer`)
|
||||
|
||||
vim.str_utfindex({str}, {index}) *vim.str_utfindex()*
|
||||
Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
|
||||
|
@ -1045,7 +1047,7 @@ vim.str_utfindex({str}, {index}) *vim.str_utfindex()*
|
|||
|
||||
Parameters: ~
|
||||
• {str} (`string`)
|
||||
• {index} (`number?`)
|
||||
• {index} (`integer?`)
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`) UTF-32 index
|
||||
|
@ -4051,6 +4053,9 @@ Iter:last() *Iter:last()*
|
|||
Return: ~
|
||||
(`any`)
|
||||
|
||||
See also: ~
|
||||
• Iter.rpeek
|
||||
|
||||
Iter:map({f}) *Iter:map()*
|
||||
Maps the items of an iterator pipeline to the values returned by `f`.
|
||||
|
||||
|
@ -4092,53 +4097,28 @@ Iter:next() *Iter:next()*
|
|||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:nextback() *Iter:nextback()*
|
||||
"Pops" a value from a |list-iterator| (gets the last value and decrements
|
||||
the tail).
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({1, 2, 3, 4})
|
||||
it:nextback()
|
||||
-- 4
|
||||
it:nextback()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:nth({n}) *Iter:nth()*
|
||||
Gets the nth value of an iterator (and advances to it).
|
||||
|
||||
Example: >lua
|
||||
If `n` is negative, offsets from the end of a |list-iterator|.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({ 3, 6, 9, 12 })
|
||||
it:nth(2)
|
||||
-- 6
|
||||
it:nth(2)
|
||||
-- 12
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) The index of the value to return.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:nthback({n}) *Iter:nthback()*
|
||||
Gets the nth value from the end of a |list-iterator| (and advances to it).
|
||||
|
||||
Example: >lua
|
||||
|
||||
local it = vim.iter({ 3, 6, 9, 12 })
|
||||
it:nthback(2)
|
||||
local it2 = vim.iter({ 3, 6, 9, 12 })
|
||||
it2:nth(-2)
|
||||
-- 9
|
||||
it:nthback(2)
|
||||
it2:nth(-2)
|
||||
-- 3
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) The index of the value to return.
|
||||
• {n} (`number`) Index of the value to return. May be negative if the
|
||||
source is a |list-iterator|.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
@ -4160,19 +4140,16 @@ Iter:peek() *Iter:peek()*
|
|||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:peekback() *Iter:peekback()*
|
||||
Gets the last value of a |list-iterator| without consuming it.
|
||||
|
||||
See also |Iter:last()|.
|
||||
Iter:pop() *Iter:pop()*
|
||||
"Pops" a value from a |list-iterator| (gets the last value and decrements
|
||||
the tail).
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({1, 2, 3, 4})
|
||||
it:peekback()
|
||||
-- 4
|
||||
it:peekback()
|
||||
-- 4
|
||||
it:nextback()
|
||||
it:pop()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Return: ~
|
||||
|
@ -4192,8 +4169,8 @@ Iter:rev() *Iter:rev()*
|
|||
(`Iter`)
|
||||
|
||||
Iter:rfind({f}) *Iter:rfind()*
|
||||
Gets the first value in a |list-iterator| that satisfies a predicate,
|
||||
starting from the end.
|
||||
Gets the first value satisfying a predicate, from the end of a
|
||||
|list-iterator|.
|
||||
|
||||
Advances the iterator. Returns nil and drains the iterator if no value is
|
||||
found.
|
||||
|
@ -4216,6 +4193,42 @@ Iter:rfind({f}) *Iter:rfind()*
|
|||
See also: ~
|
||||
• Iter.find
|
||||
|
||||
Iter:rpeek() *Iter:rpeek()*
|
||||
Gets the last value of a |list-iterator| without consuming it.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({1, 2, 3, 4})
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 4
|
||||
<
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
See also: ~
|
||||
• Iter.last
|
||||
|
||||
Iter:rskip({n}) *Iter:rskip()*
|
||||
Discards `n` values from the end of a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
|
||||
it:next()
|
||||
-- 1
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) Number of values to skip.
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
|
||||
Iter:skip({n}) *Iter:skip()*
|
||||
Skips `n` values of an iterator pipeline.
|
||||
|
||||
|
@ -4232,27 +4245,10 @@ Iter:skip({n}) *Iter:skip()*
|
|||
Return: ~
|
||||
(`Iter`)
|
||||
|
||||
Iter:skipback({n}) *Iter:skipback()*
|
||||
Skips `n` values backwards from the end of a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({ 1, 2, 3, 4, 5 }):skipback(2)
|
||||
it:next()
|
||||
-- 1
|
||||
it:nextback()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) Number of values to skip.
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
|
||||
Iter:slice({first}, {last}) *Iter:slice()*
|
||||
Sets the start and end of a |list-iterator| pipeline.
|
||||
|
||||
Equivalent to `:skip(first - 1):skipback(len - last + 1)`.
|
||||
Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
|
||||
|
||||
Parameters: ~
|
||||
• {first} (`number`)
|
||||
|
|
|
@ -159,6 +159,14 @@ unreleased features on Nvim HEAD.
|
|||
|
||||
• Changed |vim.ui.open()| return-signature to match pcall() convention.
|
||||
|
||||
• Renamed Iter:nextback() to Iter:pop()
|
||||
|
||||
• Renamed Iter:peekback() to Iter:rpeek()
|
||||
|
||||
• Renamed Iter:skipback() to Iter:rskip()
|
||||
|
||||
• Removed Iter:nthback(), use Iter:nth() with negative index instead.
|
||||
|
||||
==============================================================================
|
||||
NEW FEATURES *news-features*
|
||||
|
||||
|
@ -243,6 +251,8 @@ The following new APIs and features were added.
|
|||
(e.g. `commitCharacters`). Note that this might affect plugins and
|
||||
language servers that don't support the feature, and in such cases the
|
||||
respective capability can be unset.
|
||||
• |vim.lsp.start()| accepts a "silent" option for suppressing messages
|
||||
if an LSP server failed to start.
|
||||
|
||||
• Treesitter
|
||||
• Bundled parsers and queries (highlight, folds) for Markdown, Python, and
|
||||
|
@ -398,6 +408,14 @@ The following changes to existing APIs or features add new behavior.
|
|||
• 'comments' includes "fb:•".
|
||||
• 'shortmess' includes the "C" flag.
|
||||
• 'grepprg' defaults to using ripgrep if available.
|
||||
• |crn| in Normal mode maps to |vim.lsp.buf.rename()|.
|
||||
• |crr| in Normal and Visual mode maps to |vim.lsp.buf.code_action()|.
|
||||
• "gr" in Normal mode maps to |vim.lsp.buf.references()| |gr-default|
|
||||
• |i_CTRL-S| in Insert mode maps to |vim.lsp.buf.signature_help()|
|
||||
• "]d" and "[d" in Normal mode map to |vim.diagnostic.goto_next()| and
|
||||
|vim.diagnostic.goto_prev()|, respectively. |]d-default| |[d-default|
|
||||
• <C-W>d (and <C-W><C-D>) map to |vim.diagnostic.open_float()|
|
||||
|CTRL-W_d-default|
|
||||
• Automatic linting of treesitter query files (see |ft-query-plugin|).
|
||||
Can be disabled via: >lua
|
||||
vim.g.query_lint_on = {}
|
||||
|
@ -428,9 +446,10 @@ The following changes to existing APIs or features add new behavior.
|
|||
|
||||
:call netrw#BrowseX(expand(exists("g:netrw_gx")? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR>
|
||||
|
||||
• |vim.lsp.start()| now maps |K| to use |vim.lsp.buf.hover()| if the server
|
||||
supports it, unless |'keywordprg'| was customized before calling
|
||||
|vim.lsp.start()|.
|
||||
• |vim.lsp.start()| now creates the following default keymaps (assuming the
|
||||
server supports the feature):
|
||||
- |K| in Normal mode maps to |vim.lsp.buf.hover()|, unless |'keywordprg'|
|
||||
was customized before calling |vim.lsp.start()|.
|
||||
|
||||
• Terminal buffers started with no arguments (and use 'shell') close
|
||||
automatically if the job exited without error, eliminating the (often
|
||||
|
|
|
@ -1375,6 +1375,19 @@ Finally, these constructs are unique to Perl:
|
|||
==============================================================================
|
||||
10. Highlighting matches *match-highlight*
|
||||
|
||||
*syntax-vs-match*
|
||||
Note that the match highlight mechanism is independent
|
||||
of |syntax-highlighting|, which is (usually) a buffer-local
|
||||
highlighting, while matching is window-local, both methods
|
||||
can be freely mixed. Match highlighting functions give you
|
||||
a bit more flexibility in when and how to apply, but are
|
||||
typically only used for temporary highlighting, without strict
|
||||
rules. Both methods can be used to conceal text.
|
||||
|
||||
Thus the matching functions like |matchadd()| won't consider
|
||||
syntax rules and functions like |synconcealed()| and the
|
||||
other way around.
|
||||
|
||||
*:mat* *:match*
|
||||
:mat[ch] {group} /{pattern}/
|
||||
Define a pattern to highlight in the current window. It will
|
||||
|
|
|
@ -3825,7 +3825,9 @@ Whether or not it is actually concealed depends on the value of the
|
|||
'conceallevel' option. The 'concealcursor' option is used to decide whether
|
||||
concealable items in the current line are displayed unconcealed to be able to
|
||||
edit the line.
|
||||
Another way to conceal text is with |matchadd()|.
|
||||
|
||||
Another way to conceal text is with |matchadd()|, but internally this works a
|
||||
bit differently |syntax-vs-match|.
|
||||
|
||||
concealends *:syn-concealends*
|
||||
|
||||
|
@ -3833,7 +3835,9 @@ When the "concealends" argument is given, the start and end matches of
|
|||
the region, but not the contents of the region, are marked as concealable.
|
||||
Whether or not they are actually concealed depends on the setting on the
|
||||
'conceallevel' option. The ends of a region can only be concealed separately
|
||||
in this way when they have their own highlighting via "matchgroup"
|
||||
in this way when they have their own highlighting via "matchgroup". The
|
||||
|synconcealed()| function can be used to retrieve information about conealed
|
||||
items.
|
||||
|
||||
cchar *:syn-cchar*
|
||||
*E844*
|
||||
|
|
|
@ -780,9 +780,17 @@ CTRL-W i Open a new window, with the cursor on the first line
|
|||
beginning of the file. If a count is given, the
|
||||
count'th matching line is displayed.
|
||||
|
||||
*[d-default*
|
||||
Mapped to |vim.diagnostic.goto_prev()| by default.
|
||||
|default-mappings|
|
||||
|
||||
*]d*
|
||||
]d like "[d", but start at the current cursor position.
|
||||
|
||||
*]d-default*
|
||||
Mapped to |vim.diagnostic.goto_next()| by default.
|
||||
|default-mappings|
|
||||
|
||||
*:ds* *:dsearch*
|
||||
:[range]ds[earch][!] [count] [/]string[/]
|
||||
Like "[d" and "]d", but search in [range] lines
|
||||
|
@ -829,6 +837,10 @@ CTRL-W d Open a new window, with the cursor on the first
|
|||
beginning of the file. If a count is given, the
|
||||
count'th matching line is jumped to.
|
||||
|
||||
*CTRL-W_d-default*
|
||||
Mapped to |vim.diagnostic.open_float()| by default.
|
||||
|default-mappings|
|
||||
|
||||
*:dsp* *:dsplit*
|
||||
:[range]dsp[lit][!] [count] [/]string[/]
|
||||
Like "CTRL-W d", but search in [range] lines
|
||||
|
|
|
@ -731,8 +731,7 @@ get_captures_at_pos({bufnr}, {row}, {col})
|
|||
• {col} (`integer`) Position column
|
||||
|
||||
Return: ~
|
||||
(`table[]`) List of captures
|
||||
`{ capture = "name", metadata = { ... } }`
|
||||
(`{capture: string, lang: string, metadata: table}[]`)
|
||||
|
||||
get_node({opts}) *vim.treesitter.get_node()*
|
||||
Returns the smallest named node at the given position
|
||||
|
|
|
@ -948,7 +948,7 @@ Syntax and highlighting: *syntax-functions* *highlighting-functions*
|
|||
synIDattr() get a specific attribute of a syntax ID
|
||||
synIDtrans() get translated syntax ID
|
||||
synstack() get list of syntax IDs at a specific position
|
||||
synconcealed() get info about concealing
|
||||
synconcealed() get info about (syntax) concealing
|
||||
diff_hlID() get highlight ID for diff mode at a position
|
||||
matchadd() define a pattern to highlight (a "match")
|
||||
matchaddpos() define a list of positions to highlight
|
||||
|
|
|
@ -137,6 +137,13 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y".
|
|||
- * |v_star-default|
|
||||
- gc |gc-default| |v_gc-default| |o_gc-default|
|
||||
- gcc |gcc-default|
|
||||
- |crn|
|
||||
- |crr|
|
||||
- gr |gr-default|
|
||||
- <C-S> |i_CTRL-S|
|
||||
- ]d |]d-default|
|
||||
- [d |[d-default|
|
||||
- <C-W>d |CTRL-W_d-default|
|
||||
- Nvim LSP client defaults |lsp-defaults|
|
||||
- K |K-lsp-default|
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
|
|||
nnoremap <silent> <buffer> k gk
|
||||
nnoremap <silent> <buffer> gO :lua require'man'.show_toc()<CR>
|
||||
nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR>
|
||||
if get(b:, 'pager')
|
||||
if get(g:, 'pager')
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>q
|
||||
else
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
|
||||
|
|
|
@ -411,15 +411,13 @@ local function find_man()
|
|||
return false
|
||||
end
|
||||
|
||||
---@param pager boolean
|
||||
local function set_options(pager)
|
||||
local function set_options()
|
||||
vim.bo.swapfile = false
|
||||
vim.bo.buftype = 'nofile'
|
||||
vim.bo.bufhidden = 'unload'
|
||||
vim.bo.modified = false
|
||||
vim.bo.readonly = true
|
||||
vim.bo.modifiable = false
|
||||
vim.b.pager = pager
|
||||
vim.bo.filetype = 'man'
|
||||
end
|
||||
|
||||
|
@ -475,7 +473,7 @@ local function put_page(page)
|
|||
vim.cmd([[silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g]])
|
||||
vim.cmd('1') -- Move cursor to first line
|
||||
highlight_man_page()
|
||||
set_options(false)
|
||||
set_options()
|
||||
end
|
||||
|
||||
local function format_candidate(path, psect)
|
||||
|
@ -662,7 +660,8 @@ function M.init_pager()
|
|||
vim.cmd.file({ 'man://' .. fn.fnameescape(ref):lower(), mods = { silent = true } })
|
||||
end
|
||||
|
||||
set_options(true)
|
||||
vim.g.pager = true
|
||||
set_options()
|
||||
end
|
||||
|
||||
---@param count integer
|
||||
|
@ -730,7 +729,7 @@ function M.open_page(count, smods, args)
|
|||
if not ok then
|
||||
error(ret)
|
||||
else
|
||||
set_options(false)
|
||||
set_options()
|
||||
end
|
||||
|
||||
vim.b.man_sect = sect
|
||||
|
|
|
@ -127,7 +127,9 @@ do
|
|||
end, { desc = gx_desc })
|
||||
end
|
||||
|
||||
--- Default maps for built-in commenting
|
||||
--- Default maps for built-in commenting.
|
||||
---
|
||||
--- See |gc-default| and |gcc-default|.
|
||||
do
|
||||
local operator_rhs = function()
|
||||
return require('vim._comment').operator()
|
||||
|
@ -144,6 +146,60 @@ do
|
|||
end
|
||||
vim.keymap.set({ 'o' }, 'gc', textobject_rhs, { desc = 'Comment textobject' })
|
||||
end
|
||||
|
||||
--- Default maps for LSP functions.
|
||||
---
|
||||
--- These are mapped unconditionally to avoid confusion. If no server is attached, or if a server
|
||||
--- does not support a capability, an error message is displayed rather than exhibiting different
|
||||
--- behavior.
|
||||
---
|
||||
--- See |gr-default|, |crn|, |crr|, |i_CTRL-S|.
|
||||
do
|
||||
vim.keymap.set('n', 'crn', function()
|
||||
vim.lsp.buf.rename()
|
||||
end, { desc = 'vim.lsp.buf.rename()' })
|
||||
|
||||
vim.keymap.set({ 'n', 'v' }, 'crr', function()
|
||||
vim.lsp.buf.code_action()
|
||||
end, { desc = 'vim.lsp.buf.code_action()' })
|
||||
|
||||
vim.keymap.set('n', 'gr', function()
|
||||
vim.lsp.buf.references()
|
||||
end, { desc = 'vim.lsp.buf.references()' })
|
||||
|
||||
vim.keymap.set('i', '<C-S>', function()
|
||||
vim.lsp.buf.signature_help()
|
||||
end, { desc = 'vim.lsp.buf.signature_help()' })
|
||||
end
|
||||
|
||||
--- Map [d and ]d to move to the previous/next diagnostic. Map <C-W>d to open a floating window
|
||||
--- for the diagnostic under the cursor.
|
||||
---
|
||||
--- See |[d-default|, |]d-default|, and |CTRL-W_d-default|.
|
||||
do
|
||||
vim.keymap.set('n', ']d', function()
|
||||
vim.diagnostic.goto_next({ float = false })
|
||||
end, {
|
||||
desc = 'Jump to the next diagnostic with the highest severity',
|
||||
})
|
||||
|
||||
vim.keymap.set('n', '[d', function()
|
||||
vim.diagnostic.goto_prev({ float = false })
|
||||
end, {
|
||||
desc = 'Jump to the previous diagnostic with the highest severity',
|
||||
})
|
||||
|
||||
vim.keymap.set('n', '<C-W>d', function()
|
||||
vim.diagnostic.open_float({ border = 'rounded' })
|
||||
end, {
|
||||
desc = 'Open a floating window showing diagnostics under the cursor',
|
||||
})
|
||||
|
||||
vim.keymap.set('n', '<C-W><C-D>', '<C-W>d', {
|
||||
remap = true,
|
||||
desc = 'Open a floating window showing diagnostics under the cursor',
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--- Default menus
|
||||
|
@ -196,6 +252,7 @@ do
|
|||
group = nvim_terminal_augroup,
|
||||
desc = 'Respond to OSC foreground/background color requests',
|
||||
callback = function(args)
|
||||
--- @type integer
|
||||
local channel = vim.bo[args.buf].channel
|
||||
if channel == 0 then
|
||||
return
|
||||
|
@ -242,229 +299,140 @@ do
|
|||
vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid))
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Only do the following when the TUI is attached
|
||||
local tty = nil
|
||||
for _, ui in ipairs(vim.api.nvim_list_uis()) do
|
||||
if ui.chan == 1 and ui.stdout_tty then
|
||||
tty = ui
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if tty then
|
||||
local group = vim.api.nvim_create_augroup('nvim_tty', {})
|
||||
|
||||
--- Set an option after startup (so that OptionSet is fired), but only if not
|
||||
--- already set by the user.
|
||||
---
|
||||
--- @param option string Option name
|
||||
--- @param value any Option value
|
||||
local function setoption(option, value)
|
||||
if vim.api.nvim_get_option_info2(option, {}).was_set then
|
||||
-- Don't do anything if option is already set
|
||||
return
|
||||
end
|
||||
|
||||
-- Wait until Nvim is finished starting to set the option to ensure the
|
||||
-- OptionSet event fires.
|
||||
if vim.v.vim_did_enter == 1 then
|
||||
vim.o[option] = value
|
||||
else
|
||||
vim.api.nvim_create_autocmd('VimEnter', {
|
||||
group = group,
|
||||
once = true,
|
||||
nested = true,
|
||||
callback = function()
|
||||
setoption(option, value)
|
||||
end,
|
||||
})
|
||||
-- Only do the following when the TUI is attached
|
||||
local tty = nil
|
||||
for _, ui in ipairs(vim.api.nvim_list_uis()) do
|
||||
if ui.chan == 1 and ui.stdout_tty then
|
||||
tty = ui
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--- Guess value of 'background' based on terminal color.
|
||||
---
|
||||
--- We write Operating System Command (OSC) 11 to the terminal to request the
|
||||
--- terminal's background color. We then wait for a response. If the response
|
||||
--- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
|
||||
--- compute the luminance[1] of the RGB color and classify it as light/dark
|
||||
--- accordingly. Note that the color components may have anywhere from one to
|
||||
--- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
|
||||
--- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
|
||||
--- ignored in the calculations.
|
||||
---
|
||||
--- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
|
||||
do
|
||||
--- Parse a string of hex characters as a color.
|
||||
if tty then
|
||||
local group = vim.api.nvim_create_augroup('nvim_tty', {})
|
||||
|
||||
--- Set an option after startup (so that OptionSet is fired), but only if not
|
||||
--- already set by the user.
|
||||
---
|
||||
--- The string can contain 1 to 4 hex characters. The returned value is
|
||||
--- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
|
||||
---
|
||||
--- For instance, if only a single hex char "a" is used, then this function
|
||||
--- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
|
||||
--- 256).
|
||||
---
|
||||
--- @param c string Color as a string of hex chars
|
||||
--- @return number? Intensity of the color
|
||||
local function parsecolor(c)
|
||||
if #c == 0 or #c > 4 then
|
||||
return nil
|
||||
--- @param option string Option name
|
||||
--- @param value any Option value
|
||||
local function setoption(option, value)
|
||||
if vim.api.nvim_get_option_info2(option, {}).was_set then
|
||||
-- Don't do anything if option is already set
|
||||
return
|
||||
end
|
||||
|
||||
local val = tonumber(c, 16)
|
||||
if not val then
|
||||
return nil
|
||||
-- Wait until Nvim is finished starting to set the option to ensure the
|
||||
-- OptionSet event fires.
|
||||
if vim.v.vim_did_enter == 1 then
|
||||
--- @diagnostic disable-next-line:no-unknown
|
||||
vim.o[option] = value
|
||||
else
|
||||
vim.api.nvim_create_autocmd('VimEnter', {
|
||||
group = group,
|
||||
once = true,
|
||||
nested = true,
|
||||
callback = function()
|
||||
setoption(option, value)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
local max = tonumber(string.rep('f', #c), 16)
|
||||
return val / max
|
||||
end
|
||||
|
||||
--- Parse an OSC 11 response
|
||||
--- Guess value of 'background' based on terminal color.
|
||||
---
|
||||
--- Either of the two formats below are accepted:
|
||||
--- We write Operating System Command (OSC) 11 to the terminal to request the
|
||||
--- terminal's background color. We then wait for a response. If the response
|
||||
--- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
|
||||
--- compute the luminance[1] of the RGB color and classify it as light/dark
|
||||
--- accordingly. Note that the color components may have anywhere from one to
|
||||
--- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
|
||||
--- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
|
||||
--- ignored in the calculations.
|
||||
---
|
||||
--- OSC 11 ; rgb:<red>/<green>/<blue>
|
||||
---
|
||||
--- or
|
||||
---
|
||||
--- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
|
||||
---
|
||||
--- where
|
||||
---
|
||||
--- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
|
||||
---
|
||||
--- The alpha component is ignored, if present.
|
||||
---
|
||||
--- @param resp string OSC 11 response
|
||||
--- @return string? Red component
|
||||
--- @return string? Green component
|
||||
--- @return string? Blue component
|
||||
local function parseosc11(resp)
|
||||
local r, g, b
|
||||
r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
|
||||
if not r and not g and not b then
|
||||
local a
|
||||
r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
|
||||
if not a or #a > 4 then
|
||||
return nil, nil, nil
|
||||
--- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
|
||||
do
|
||||
--- Parse a string of hex characters as a color.
|
||||
---
|
||||
--- The string can contain 1 to 4 hex characters. The returned value is
|
||||
--- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
|
||||
---
|
||||
--- For instance, if only a single hex char "a" is used, then this function
|
||||
--- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
|
||||
--- 256).
|
||||
---
|
||||
--- @param c string Color as a string of hex chars
|
||||
--- @return number? Intensity of the color
|
||||
local function parsecolor(c)
|
||||
if #c == 0 or #c > 4 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local val = tonumber(c, 16)
|
||||
if not val then
|
||||
return nil
|
||||
end
|
||||
|
||||
local max = tonumber(string.rep('f', #c), 16)
|
||||
return val / max
|
||||
end
|
||||
|
||||
if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
return nil, nil, nil
|
||||
end
|
||||
|
||||
local timer = assert(vim.uv.new_timer())
|
||||
|
||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||
group = group,
|
||||
nested = true,
|
||||
callback = function(args)
|
||||
local resp = args.data ---@type string
|
||||
local r, g, b = parseosc11(resp)
|
||||
if r and g and b then
|
||||
local rr = parsecolor(r)
|
||||
local gg = parsecolor(g)
|
||||
local bb = parsecolor(b)
|
||||
|
||||
if rr and gg and bb then
|
||||
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
|
||||
local bg = luminance < 0.5 and 'dark' or 'light'
|
||||
setoption('background', bg)
|
||||
--- Parse an OSC 11 response
|
||||
---
|
||||
--- Either of the two formats below are accepted:
|
||||
---
|
||||
--- OSC 11 ; rgb:<red>/<green>/<blue>
|
||||
---
|
||||
--- or
|
||||
---
|
||||
--- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
|
||||
---
|
||||
--- where
|
||||
---
|
||||
--- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
|
||||
---
|
||||
--- The alpha component is ignored, if present.
|
||||
---
|
||||
--- @param resp string OSC 11 response
|
||||
--- @return string? Red component
|
||||
--- @return string? Green component
|
||||
--- @return string? Blue component
|
||||
local function parseosc11(resp)
|
||||
local r, g, b
|
||||
r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
|
||||
if not r and not g and not b then
|
||||
local a
|
||||
r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
|
||||
if not a or #a > 4 then
|
||||
return nil, nil, nil
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
io.stdout:write('\027]11;?\007')
|
||||
if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
timer:start(1000, 0, function()
|
||||
-- Delete the autocommand if no response was received
|
||||
vim.schedule(function()
|
||||
-- Suppress error if autocommand has already been deleted
|
||||
pcall(vim.api.nvim_del_autocmd, id)
|
||||
end)
|
||||
|
||||
if not timer:is_closing() then
|
||||
timer:close()
|
||||
return nil, nil, nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- If the TUI (term_has_truecolor) was able to determine that the host
|
||||
--- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the
|
||||
--- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's
|
||||
--- response indicates that it does support truecolor enable 'termguicolors',
|
||||
--- but only if the user has not already disabled it.
|
||||
do
|
||||
if tty.rgb then
|
||||
-- The TUI was able to determine truecolor support
|
||||
setoption('termguicolors', true)
|
||||
else
|
||||
local caps = {} ---@type table<string, boolean>
|
||||
require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found)
|
||||
if not found then
|
||||
return
|
||||
end
|
||||
|
||||
caps[cap] = true
|
||||
if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then
|
||||
setoption('termguicolors', true)
|
||||
end
|
||||
end)
|
||||
|
||||
local timer = assert(vim.uv.new_timer())
|
||||
|
||||
-- Arbitrary colors to set in the SGR sequence
|
||||
local r = 1
|
||||
local g = 2
|
||||
local b = 3
|
||||
|
||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||
group = group,
|
||||
nested = true,
|
||||
callback = function(args)
|
||||
local resp = args.data ---@type string
|
||||
local decrqss = resp:match('^\027P1%$r([%d;:]+)m$')
|
||||
local r, g, b = parseosc11(resp)
|
||||
if r and g and b then
|
||||
local rr = parsecolor(r)
|
||||
local gg = parsecolor(g)
|
||||
local bb = parsecolor(b)
|
||||
|
||||
if decrqss then
|
||||
-- The DECRQSS SGR response first contains attributes separated by
|
||||
-- semicolons, followed by the SGR itself with parameters separated
|
||||
-- by colons. Some terminals include "0" in the attribute list
|
||||
-- unconditionally; others do not. Our SGR sequence did not set any
|
||||
-- attributes, so there should be no attributes in the list.
|
||||
local attrs = vim.split(decrqss, ';')
|
||||
if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then
|
||||
return false
|
||||
end
|
||||
|
||||
-- The returned SGR sequence should begin with 48:2
|
||||
local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$')
|
||||
if not sgr then
|
||||
return false
|
||||
end
|
||||
|
||||
-- The remaining elements of the SGR sequence should be the 3 colors
|
||||
-- we set. Some terminals also include an additional parameter
|
||||
-- (which can even be empty!), so handle those cases as well
|
||||
local params = vim.split(sgr, ':')
|
||||
if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then
|
||||
return true
|
||||
end
|
||||
|
||||
if
|
||||
tonumber(params[#params - 2]) == r
|
||||
and tonumber(params[#params - 1]) == g
|
||||
and tonumber(params[#params]) == b
|
||||
then
|
||||
setoption('termguicolors', true)
|
||||
if rr and gg and bb then
|
||||
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
|
||||
local bg = luminance < 0.5 and 'dark' or 'light'
|
||||
setoption('background', bg)
|
||||
end
|
||||
|
||||
return true
|
||||
|
@ -472,16 +440,7 @@ if tty then
|
|||
end,
|
||||
})
|
||||
|
||||
-- Write SGR followed by DECRQSS. This sets the background color then
|
||||
-- immediately asks the terminal what the background color is. If the
|
||||
-- terminal responds to the DECRQSS with the same SGR sequence that we
|
||||
-- sent then the terminal supports truecolor.
|
||||
local decrqss = '\027P$qm\027\\'
|
||||
if os.getenv('TMUX') then
|
||||
decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027'))
|
||||
end
|
||||
-- Reset attributes first, as other code may have set attributes.
|
||||
io.stdout:write(string.format('\027[0m\027[48;2;%d;%d;%dm%s', r, g, b, decrqss))
|
||||
io.stdout:write('\027]11;?\007')
|
||||
|
||||
timer:start(1000, 0, function()
|
||||
-- Delete the autocommand if no response was received
|
||||
|
@ -495,13 +454,115 @@ if tty then
|
|||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- If the TUI (term_has_truecolor) was able to determine that the host
|
||||
--- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the
|
||||
--- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's
|
||||
--- response indicates that it does support truecolor enable 'termguicolors',
|
||||
--- but only if the user has not already disabled it.
|
||||
do
|
||||
if tty.rgb then
|
||||
-- The TUI was able to determine truecolor support
|
||||
setoption('termguicolors', true)
|
||||
else
|
||||
local caps = {} ---@type table<string, boolean>
|
||||
require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found)
|
||||
if not found then
|
||||
return
|
||||
end
|
||||
|
||||
caps[cap] = true
|
||||
if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then
|
||||
setoption('termguicolors', true)
|
||||
end
|
||||
end)
|
||||
|
||||
local timer = assert(vim.uv.new_timer())
|
||||
|
||||
-- Arbitrary colors to set in the SGR sequence
|
||||
local r = 1
|
||||
local g = 2
|
||||
local b = 3
|
||||
|
||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||
group = group,
|
||||
nested = true,
|
||||
callback = function(args)
|
||||
local resp = args.data ---@type string
|
||||
local decrqss = resp:match('^\027P1%$r([%d;:]+)m$')
|
||||
|
||||
if decrqss then
|
||||
-- The DECRQSS SGR response first contains attributes separated by
|
||||
-- semicolons, followed by the SGR itself with parameters separated
|
||||
-- by colons. Some terminals include "0" in the attribute list
|
||||
-- unconditionally; others do not. Our SGR sequence did not set any
|
||||
-- attributes, so there should be no attributes in the list.
|
||||
local attrs = vim.split(decrqss, ';')
|
||||
if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then
|
||||
return false
|
||||
end
|
||||
|
||||
-- The returned SGR sequence should begin with 48:2
|
||||
local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$')
|
||||
if not sgr then
|
||||
return false
|
||||
end
|
||||
|
||||
-- The remaining elements of the SGR sequence should be the 3 colors
|
||||
-- we set. Some terminals also include an additional parameter
|
||||
-- (which can even be empty!), so handle those cases as well
|
||||
local params = vim.split(sgr, ':')
|
||||
if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then
|
||||
return true
|
||||
end
|
||||
|
||||
if
|
||||
tonumber(params[#params - 2]) == r
|
||||
and tonumber(params[#params - 1]) == g
|
||||
and tonumber(params[#params]) == b
|
||||
then
|
||||
setoption('termguicolors', true)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Write SGR followed by DECRQSS. This sets the background color then
|
||||
-- immediately asks the terminal what the background color is. If the
|
||||
-- terminal responds to the DECRQSS with the same SGR sequence that we
|
||||
-- sent then the terminal supports truecolor.
|
||||
local decrqss = '\027P$qm\027\\'
|
||||
if os.getenv('TMUX') then
|
||||
decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027'))
|
||||
end
|
||||
-- Reset attributes first, as other code may have set attributes.
|
||||
io.stdout:write(string.format('\027[0m\027[48;2;%d;%d;%dm%s', r, g, b, decrqss))
|
||||
|
||||
timer:start(1000, 0, function()
|
||||
-- Delete the autocommand if no response was received
|
||||
vim.schedule(function()
|
||||
-- Suppress error if autocommand has already been deleted
|
||||
pcall(vim.api.nvim_del_autocmd, id)
|
||||
end)
|
||||
|
||||
if not timer:is_closing() then
|
||||
timer:close()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Default 'grepprg' to ripgrep if available.
|
||||
if vim.fn.executable('rg') == 1 then
|
||||
-- Match :grep default, otherwise rg searches cwd by default
|
||||
-- Use -uuu to make ripgrep not do its default filtering
|
||||
vim.o.grepprg = 'rg --vimgrep -uuu $* ' .. (vim.fn.has('unix') == 1 and '/dev/null' or 'nul')
|
||||
vim.o.grepformat = '%f:%l:%c:%m'
|
||||
--- Default options
|
||||
do
|
||||
--- Default 'grepprg' to ripgrep if available.
|
||||
if vim.fn.executable('rg') == 1 then
|
||||
-- Match :grep default, otherwise rg searches cwd by default
|
||||
-- Use -uuu to make ripgrep not do its default filtering
|
||||
vim.o.grepprg = 'rg --vimgrep -uuu $* ' .. (vim.fn.has('unix') == 1 and '/dev/null' or 'nul')
|
||||
vim.o.grepformat = '%f:%l:%c:%m'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,8 +55,8 @@ function vim.inspect_pos(bufnr, row, col, filter)
|
|||
bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr
|
||||
|
||||
local results = {
|
||||
treesitter = {},
|
||||
syntax = {},
|
||||
treesitter = {}, --- @type table[]
|
||||
syntax = {}, --- @type table[]
|
||||
extmarks = {},
|
||||
semantic_tokens = {},
|
||||
buffer = bufnr,
|
||||
|
@ -93,7 +93,7 @@ function vim.inspect_pos(bufnr, row, col, filter)
|
|||
end
|
||||
|
||||
-- namespace id -> name map
|
||||
local nsmap = {}
|
||||
local nsmap = {} --- @type table<integer,string>
|
||||
for name, id in pairs(vim.api.nvim_get_namespaces()) do
|
||||
nsmap[id] = name
|
||||
end
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
--- Encode {str} using Base64.
|
||||
---
|
||||
--- @param str string String to encode
|
||||
--- @return string Encoded string
|
||||
--- @return string : Encoded string
|
||||
function vim.base64.encode(str) end
|
||||
|
||||
--- Decode a Base64 encoded string.
|
||||
---
|
||||
--- @param str string Base64 encoded string
|
||||
--- @return string Decoded string
|
||||
--- @return string : Decoded string
|
||||
function vim.base64.decode(str) end
|
||||
|
|
|
@ -119,15 +119,15 @@ function vim.stricmp(a, b) end
|
|||
--- An {index} in the middle of a UTF-16 sequence is rounded upwards to
|
||||
--- the end of that sequence.
|
||||
--- @param str string
|
||||
--- @param index number
|
||||
--- @param use_utf16? any
|
||||
--- @param index integer
|
||||
--- @param use_utf16? boolean
|
||||
function vim.str_byteindex(str, index, use_utf16) end
|
||||
|
||||
--- Gets a list of the starting byte positions of each UTF-8 codepoint in the given string.
|
||||
---
|
||||
--- Embedded NUL bytes are treated as terminating the string.
|
||||
--- @param str string
|
||||
--- @return table
|
||||
--- @return integer[]
|
||||
function vim.str_utf_pos(str) end
|
||||
|
||||
--- Gets the distance (in bytes) from the starting byte of the codepoint (character) that {index}
|
||||
|
@ -148,8 +148,8 @@ function vim.str_utf_pos(str) end
|
|||
--- ```
|
||||
---
|
||||
--- @param str string
|
||||
--- @param index number
|
||||
--- @return number
|
||||
--- @param index integer
|
||||
--- @return integer
|
||||
function vim.str_utf_start(str, index) end
|
||||
|
||||
--- Gets the distance (in bytes) from the last byte of the codepoint (character) that {index} points
|
||||
|
@ -168,8 +168,8 @@ function vim.str_utf_start(str, index) end
|
|||
--- ```
|
||||
---
|
||||
--- @param str string
|
||||
--- @param index number
|
||||
--- @return number
|
||||
--- @param index integer
|
||||
--- @return integer
|
||||
function vim.str_utf_end(str, index) end
|
||||
|
||||
--- Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
|
||||
|
@ -180,7 +180,7 @@ function vim.str_utf_end(str, index) end
|
|||
--- {index} in the middle of a UTF-8 sequence is rounded upwards to the end of
|
||||
--- that sequence.
|
||||
--- @param str string
|
||||
--- @param index? number
|
||||
--- @param index? integer
|
||||
--- @return integer UTF-32 index
|
||||
--- @return integer UTF-16 index
|
||||
function vim.str_utfindex(str, index) end
|
||||
|
@ -193,15 +193,14 @@ function vim.str_utfindex(str, index) end
|
|||
--- can accept, see ":Man 3 iconv".
|
||||
---
|
||||
--- @param str string Text to convert
|
||||
--- @param from number Encoding of {str}
|
||||
--- @param to number Target encoding
|
||||
--- @param opts? table<string,any>
|
||||
--- @return string|nil Converted string if conversion succeeds, `nil` otherwise.
|
||||
--- @param from string Encoding of {str}
|
||||
--- @param to string Target encoding
|
||||
--- @return string? : Converted string if conversion succeeds, `nil` otherwise.
|
||||
function vim.iconv(str, from, to, opts) end
|
||||
|
||||
--- Schedules {fn} to be invoked soon by the main event-loop. Useful
|
||||
--- to avoid |textlock| or other temporary restrictions.
|
||||
--- @param fn function
|
||||
--- @param fn fun()
|
||||
function vim.schedule(fn) end
|
||||
|
||||
--- Wait for {time} in milliseconds until {callback} returns `true`.
|
||||
|
|
|
@ -1,5 +1,46 @@
|
|||
---@meta
|
||||
|
||||
--- Optional parameters:
|
||||
--- @class vim.diff.Opts
|
||||
--- @inlinedoc
|
||||
---
|
||||
--- Invoked for each hunk in the diff. Return a negative number
|
||||
--- to cancel the callback for any remaining hunks.
|
||||
--- Arguments:
|
||||
--- - `start_a` (`integer`): Start line of hunk in {a}.
|
||||
--- - `count_a` (`integer`): Hunk size in {a}.
|
||||
--- - `start_b` (`integer`): Start line of hunk in {b}.
|
||||
--- - `count_b` (`integer`): Hunk size in {b}.
|
||||
--- @field on_hunk fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer
|
||||
---
|
||||
--- Form of the returned diff:
|
||||
--- - `unified`: String in unified format.
|
||||
--- - `indices`: Array of hunk locations.
|
||||
--- Note: This option is ignored if `on_hunk` is used.
|
||||
--- (default: `'unified'`)
|
||||
--- @field result_type 'unified'|'indices'
|
||||
---
|
||||
--- Run linematch on the resulting hunks from xdiff. When integer, only hunks
|
||||
--- upto this size in lines are run through linematch.
|
||||
--- Requires `result_type = indices`, ignored otherwise.
|
||||
--- @field linematch boolean|integer
|
||||
---
|
||||
--- Diff algorithm to use. Values:
|
||||
--- - `myers`: the default algorithm
|
||||
--- - `minimal`: spend extra time to generate the smallest possible diff
|
||||
--- - `patience`: patience diff algorithm
|
||||
--- - `histogram`: histogram diff algorithm
|
||||
--- (default: `'myers'`)
|
||||
--- @field algorithm 'myers'|'minimal'|'patience'|'histogram'
|
||||
--- @field ctxlen integer Context length
|
||||
--- @field interhunkctxlen integer Inter hunk context length
|
||||
--- @field ignore_whitespace boolean Ignore whitespace
|
||||
--- @field ignore_whitespace_change boolean Ignore whitespace change
|
||||
--- @field ignore_whitespace_change_at_eol boolean Ignore whitespace change at end-of-line.
|
||||
--- @field ignore_cr_at_eol boolean Ignore carriage return at end-of-line
|
||||
--- @field ignore_blank_lines boolean Ignore blank lines
|
||||
--- @field indent_heuristic boolean Use the indent heuristic for the internal diff library.
|
||||
|
||||
-- luacheck: no unused args
|
||||
|
||||
--- Run diff on strings {a} and {b}. Any indices returned by this function,
|
||||
|
@ -24,47 +65,7 @@
|
|||
---
|
||||
---@param a string First string to compare
|
||||
---@param b string Second string to compare
|
||||
---@param opts table<string,any> Optional parameters:
|
||||
--- - `on_hunk` (callback):
|
||||
--- Invoked for each hunk in the diff. Return a negative number
|
||||
--- to cancel the callback for any remaining hunks.
|
||||
--- Args:
|
||||
--- - `start_a` (integer): Start line of hunk in {a}.
|
||||
--- - `count_a` (integer): Hunk size in {a}.
|
||||
--- - `start_b` (integer): Start line of hunk in {b}.
|
||||
--- - `count_b` (integer): Hunk size in {b}.
|
||||
--- - `result_type` (string): Form of the returned diff:
|
||||
--- - "unified": (default) String in unified format.
|
||||
--- - "indices": Array of hunk locations.
|
||||
--- Note: This option is ignored if `on_hunk` is used.
|
||||
--- - `linematch` (boolean|integer): Run linematch on the resulting hunks
|
||||
--- from xdiff. When integer, only hunks upto this size in
|
||||
--- lines are run through linematch. Requires `result_type = indices`,
|
||||
--- ignored otherwise.
|
||||
--- - `algorithm` (string):
|
||||
--- Diff algorithm to use. Values:
|
||||
--- - "myers" the default algorithm
|
||||
--- - "minimal" spend extra time to generate the
|
||||
--- smallest possible diff
|
||||
--- - "patience" patience diff algorithm
|
||||
--- - "histogram" histogram diff algorithm
|
||||
--- - `ctxlen` (integer): Context length
|
||||
--- - `interhunkctxlen` (integer):
|
||||
--- Inter hunk context length
|
||||
--- - `ignore_whitespace` (boolean):
|
||||
--- Ignore whitespace
|
||||
--- - `ignore_whitespace_change` (boolean):
|
||||
--- Ignore whitespace change
|
||||
--- - `ignore_whitespace_change_at_eol` (boolean)
|
||||
--- Ignore whitespace change at end-of-line.
|
||||
--- - `ignore_cr_at_eol` (boolean)
|
||||
--- Ignore carriage return at end-of-line
|
||||
--- - `ignore_blank_lines` (boolean)
|
||||
--- Ignore blank lines
|
||||
--- - `indent_heuristic` (boolean):
|
||||
--- Use the indent heuristic for the internal
|
||||
--- diff library.
|
||||
---
|
||||
---@return string|table|nil
|
||||
---@param opts vim.diff.Opts
|
||||
---@return string|integer[][]?
|
||||
--- See {opts.result_type}. `nil` if {opts.on_hunk} is given.
|
||||
function vim.diff(a, b, opts) end
|
||||
|
|
|
@ -30,8 +30,8 @@ function vim.re.compile(string, defs) end
|
|||
--- @param subject string
|
||||
--- @param pattern vim.lpeg.Pattern|string
|
||||
--- @param init? integer
|
||||
--- @return integer|nil the index where the occurrence starts, nil if no match
|
||||
--- @return integer|nil the index where the occurrence ends, nil if no match
|
||||
--- @return integer|nil : the index where the occurrence starts, nil if no match
|
||||
--- @return integer|nil : the index where the occurrence ends, nil if no match
|
||||
function vim.re.find(subject, pattern, init) end
|
||||
|
||||
--- Does a global substitution, replacing all occurrences of {pattern} in the given {subject} by
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
-- luacheck: no unused args
|
||||
|
||||
--- Check {str} for spelling errors. Similar to the Vimscript function
|
||||
--- |spellbadword()|.
|
||||
--- [spellbadword()].
|
||||
---
|
||||
--- Note: The behaviour of this function is dependent on: 'spelllang',
|
||||
--- 'spellfile', 'spellcapcheck' and 'spelloptions' which can all be local to
|
||||
--- the buffer. Consider calling this with |nvim_buf_call()|.
|
||||
--- the buffer. Consider calling this with [nvim_buf_call()].
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
|
@ -20,7 +20,7 @@
|
|||
--- ```
|
||||
---
|
||||
--- @param str string
|
||||
--- @return {[1]: string, [2]: string, [3]: string}[]
|
||||
--- @return {[1]: string, [2]: 'bad'|'rare'|'local'|'caps', [3]: integer}[]
|
||||
--- List of tuples with three items:
|
||||
--- - The badly spelled word.
|
||||
--- - The type of the spelling error:
|
||||
|
|
|
@ -9752,6 +9752,10 @@ function vim.fn.synIDtrans(synID) end
|
|||
--- synconcealed(lnum, 5) [1, 'X', 2]
|
||||
--- synconcealed(lnum, 6) [0, '', 0]
|
||||
---
|
||||
--- Note: Doesn't consider |matchadd()| highlighting items,
|
||||
--- since syntax and matching highlighting are two different
|
||||
--- mechanisms |syntax-vs-match|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param col integer
|
||||
--- @return {[1]: integer, [2]: string, [3]: integer}
|
||||
|
|
|
@ -630,7 +630,7 @@ function Iter:find(f)
|
|||
return unpack(result)
|
||||
end
|
||||
|
||||
--- Gets the first value in a |list-iterator| that satisfies a predicate, starting from the end.
|
||||
--- Gets the first value satisfying a predicate, from the end of a |list-iterator|.
|
||||
---
|
||||
--- Advances the iterator. Returns nil and drains the iterator if no value is found.
|
||||
---
|
||||
|
@ -717,19 +717,19 @@ end
|
|||
---
|
||||
--- ```lua
|
||||
--- local it = vim.iter({1, 2, 3, 4})
|
||||
--- it:nextback()
|
||||
--- it:pop()
|
||||
--- -- 4
|
||||
--- it:nextback()
|
||||
--- it:pop()
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@return any
|
||||
function Iter:nextback()
|
||||
error('nextback() requires a list-like table')
|
||||
function Iter:pop()
|
||||
error('pop() requires a list-like table')
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
function ListIter:nextback()
|
||||
function ListIter:pop()
|
||||
if self._head ~= self._tail then
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
self._tail = self._tail - inc
|
||||
|
@ -739,27 +739,27 @@ end
|
|||
|
||||
--- Gets the last value of a |list-iterator| without consuming it.
|
||||
---
|
||||
--- See also |Iter:last()|.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- local it = vim.iter({1, 2, 3, 4})
|
||||
--- it:peekback()
|
||||
--- it:rpeek()
|
||||
--- -- 4
|
||||
--- it:peekback()
|
||||
--- it:rpeek()
|
||||
--- -- 4
|
||||
--- it:nextback()
|
||||
--- it:pop()
|
||||
--- -- 4
|
||||
--- ```
|
||||
---
|
||||
---@see Iter.last
|
||||
---
|
||||
---@return any
|
||||
function Iter:peekback()
|
||||
error('peekback() requires a list-like table')
|
||||
function Iter:rpeek()
|
||||
error('rpeek() requires a list-like table')
|
||||
end
|
||||
|
||||
---@nodoc
|
||||
function ListIter:peekback()
|
||||
function ListIter:rpeek()
|
||||
if self._head ~= self._tail then
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
return self._table[self._tail - inc]
|
||||
|
@ -797,27 +797,27 @@ function ListIter:skip(n)
|
|||
return self
|
||||
end
|
||||
|
||||
--- Skips `n` values backwards from the end of a |list-iterator| pipeline.
|
||||
--- Discards `n` values from the end of a |list-iterator| pipeline.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- local it = vim.iter({ 1, 2, 3, 4, 5 }):skipback(2)
|
||||
--- local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
|
||||
--- it:next()
|
||||
--- -- 1
|
||||
--- it:nextback()
|
||||
--- it:pop()
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@param n number Number of values to skip.
|
||||
---@return Iter
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Iter:skipback(n) -- luacheck: no unused args
|
||||
error('skipback() requires a list-like table')
|
||||
function Iter:rskip(n) -- luacheck: no unused args
|
||||
error('rskip() requires a list-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ListIter:skipback(n)
|
||||
function ListIter:rskip(n)
|
||||
local inc = self._head < self._tail and n or -n
|
||||
self._tail = self._tail - inc
|
||||
if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
|
||||
|
@ -828,51 +828,37 @@ end
|
|||
|
||||
--- Gets the nth value of an iterator (and advances to it).
|
||||
---
|
||||
--- If `n` is negative, offsets from the end of a |list-iterator|.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
---
|
||||
--- local it = vim.iter({ 3, 6, 9, 12 })
|
||||
--- it:nth(2)
|
||||
--- -- 6
|
||||
--- it:nth(2)
|
||||
--- -- 12
|
||||
---
|
||||
--- local it2 = vim.iter({ 3, 6, 9, 12 })
|
||||
--- it2:nth(-2)
|
||||
--- -- 9
|
||||
--- it2:nth(-2)
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@param n number The index of the value to return.
|
||||
---@param n number Index of the value to return. May be negative if the source is a |list-iterator|.
|
||||
---@return any
|
||||
function Iter:nth(n)
|
||||
if n > 0 then
|
||||
return self:skip(n - 1):next()
|
||||
end
|
||||
end
|
||||
|
||||
--- Gets the nth value from the end of a |list-iterator| (and advances to it).
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
---
|
||||
--- local it = vim.iter({ 3, 6, 9, 12 })
|
||||
--- it:nthback(2)
|
||||
--- -- 9
|
||||
--- it:nthback(2)
|
||||
--- -- 3
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@param n number The index of the value to return.
|
||||
---@return any
|
||||
function Iter:nthback(n)
|
||||
if n > 0 then
|
||||
return self:skipback(n - 1):nextback()
|
||||
elseif n < 0 then
|
||||
return self:rskip(math.abs(n) - 1):pop()
|
||||
end
|
||||
end
|
||||
|
||||
--- Sets the start and end of a |list-iterator| pipeline.
|
||||
---
|
||||
--- Equivalent to `:skip(first - 1):skipback(len - last + 1)`.
|
||||
--- Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
|
||||
---
|
||||
---@param first number
|
||||
---@param last number
|
||||
|
@ -884,7 +870,7 @@ end
|
|||
|
||||
---@private
|
||||
function ListIter:slice(first, last)
|
||||
return self:skip(math.max(0, first - 1)):skipback(math.max(0, self._tail - last - 1))
|
||||
return self:skip(math.max(0, first - 1)):rskip(math.max(0, self._tail - last - 1))
|
||||
end
|
||||
|
||||
--- Returns true if any of the items in the iterator match the given predicate.
|
||||
|
@ -950,6 +936,8 @@ end
|
|||
---
|
||||
--- ```
|
||||
---
|
||||
---@see Iter.rpeek
|
||||
---
|
||||
---@return any
|
||||
function Iter:last()
|
||||
local last = self:next()
|
||||
|
@ -1016,6 +1004,26 @@ function ListIter:enumerate()
|
|||
return self
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function Iter:nextback()
|
||||
error('Iter:nextback() was renamed to Iter:pop()')
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function Iter:peekback()
|
||||
error('Iter:peekback() was renamed to Iter:rpeek()')
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function Iter:skipback()
|
||||
error('Iter:skipback() was renamed to Iter:rskip()')
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function Iter:nthback()
|
||||
error('Iter:nthback() was removed, use Iter:nth() with negative index')
|
||||
end
|
||||
|
||||
--- Creates a new Iter object from a table or other |iterable|.
|
||||
---
|
||||
---@param src table|function Table or iterator to drain values from
|
||||
|
|
|
@ -195,10 +195,13 @@ end
|
|||
--- Predicate used to decide if a client should be re-used. Used on all
|
||||
--- running clients. The default implementation re-uses a client if name and
|
||||
--- root_dir matches.
|
||||
--- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean
|
||||
--- @field reuse_client fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean
|
||||
---
|
||||
--- Buffer handle to attach to if starting or re-using a client (0 for current).
|
||||
--- @field bufnr integer
|
||||
---
|
||||
--- Suppress error reporting if the LSP server fails to start (default false).
|
||||
--- @field silent? boolean
|
||||
|
||||
--- Create a new LSP client and start a language server or reuses an already
|
||||
--- running client if one is found matching `name` and `root_dir`.
|
||||
|
@ -246,19 +249,25 @@ function lsp.start(config, opts)
|
|||
|
||||
for _, client in pairs(all_clients) do
|
||||
if reuse_client(client, config) then
|
||||
lsp.buf_attach_client(bufnr, client.id)
|
||||
return client.id
|
||||
if lsp.buf_attach_client(bufnr, client.id) then
|
||||
return client.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local client_id = lsp.start_client(config)
|
||||
|
||||
if not client_id then
|
||||
return -- lsp.start_client will have printed an error
|
||||
local client_id, err = lsp.start_client(config)
|
||||
if err then
|
||||
if not opts.silent then
|
||||
vim.notify(err, vim.log.levels.WARN)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
lsp.buf_attach_client(bufnr, client_id)
|
||||
return client_id
|
||||
if client_id and lsp.buf_attach_client(bufnr, client_id) then
|
||||
return client_id
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Consumes the latest progress messages from all clients and formats them as a string.
|
||||
|
@ -339,7 +348,7 @@ function lsp._set_defaults(client, bufnr)
|
|||
and is_empty_or_default(bufnr, 'keywordprg')
|
||||
and vim.fn.maparg('K', 'n', false, false) == ''
|
||||
then
|
||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr })
|
||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr, desc = 'vim.lsp.buf.hover()' })
|
||||
end
|
||||
end)
|
||||
if client.supports_method(ms.textDocument_diagnostic) then
|
||||
|
@ -420,16 +429,18 @@ end
|
|||
|
||||
--- Starts and initializes a client with the given configuration.
|
||||
--- @param config vim.lsp.ClientConfig Configuration for the server.
|
||||
--- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be
|
||||
--- fully initialized. Use `on_init` to do any actions once
|
||||
--- the client has been initialized.
|
||||
--- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be
|
||||
--- fully initialized. Use `on_init` to do any actions once
|
||||
--- the client has been initialized.
|
||||
--- @return string? # Error message, if any
|
||||
function lsp.start_client(config)
|
||||
local client = require('vim.lsp.client').create(config)
|
||||
|
||||
if not client then
|
||||
return
|
||||
local ok, res = pcall(require('vim.lsp.client').create, config)
|
||||
if not ok then
|
||||
return nil, res --[[@as string]]
|
||||
end
|
||||
|
||||
local client = assert(res)
|
||||
|
||||
--- @diagnostic disable-next-line: invisible
|
||||
table.insert(client._on_exit_cbs, on_client_exit)
|
||||
|
||||
|
@ -437,31 +448,7 @@ function lsp.start_client(config)
|
|||
|
||||
client:initialize()
|
||||
|
||||
return client.id
|
||||
end
|
||||
|
||||
--- Notify all attached clients that a buffer has changed.
|
||||
---@param _ integer
|
||||
---@param bufnr integer
|
||||
---@param changedtick integer
|
||||
---@param firstline integer
|
||||
---@param lastline integer
|
||||
---@param new_lastline integer
|
||||
---@return true?
|
||||
local function text_document_did_change_handler(
|
||||
_,
|
||||
bufnr,
|
||||
changedtick,
|
||||
firstline,
|
||||
lastline,
|
||||
new_lastline
|
||||
)
|
||||
-- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
|
||||
if #lsp.get_clients({ bufnr = bufnr }) == 0 then
|
||||
return true
|
||||
end
|
||||
util.buf_versions[bufnr] = changedtick
|
||||
changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
|
||||
return client.id, nil
|
||||
end
|
||||
|
||||
---Buffer lifecycle handler for textDocument/didSave
|
||||
|
@ -505,11 +492,18 @@ local function text_document_did_save_handler(bufnr)
|
|||
end
|
||||
end
|
||||
|
||||
--- @type table<integer,true>
|
||||
local attached_buffers = {}
|
||||
|
||||
--- @param bufnr integer
|
||||
--- @param client_id integer
|
||||
local function buf_attach(bufnr, client_id)
|
||||
local function buf_attach(bufnr)
|
||||
if attached_buffers[bufnr] then
|
||||
return
|
||||
end
|
||||
attached_buffers[bufnr] = true
|
||||
|
||||
local uri = vim.uri_from_bufnr(bufnr)
|
||||
local augroup = ('lsp_c_%d_b_%d_save'):format(client_id, bufnr)
|
||||
local augroup = ('lsp_b_%d_save'):format(bufnr)
|
||||
local group = api.nvim_create_augroup(augroup, { clear = true })
|
||||
api.nvim_create_autocmd('BufWritePre', {
|
||||
group = group,
|
||||
|
@ -548,7 +542,14 @@ local function buf_attach(bufnr, client_id)
|
|||
})
|
||||
-- First time, so attach and set up stuff.
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_lines = text_document_did_change_handler,
|
||||
on_lines = function(_, _, changedtick, firstline, lastline, new_lastline)
|
||||
if #lsp.get_clients({ bufnr = bufnr }) == 0 then
|
||||
return true -- detach
|
||||
end
|
||||
util.buf_versions[bufnr] = changedtick
|
||||
changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
|
||||
end,
|
||||
|
||||
on_reload = function()
|
||||
local params = { textDocument = { uri = uri } }
|
||||
for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do
|
||||
|
@ -559,6 +560,7 @@ local function buf_attach(bufnr, client_id)
|
|||
client:_text_document_did_open_handler(bufnr)
|
||||
end
|
||||
end,
|
||||
|
||||
on_detach = function()
|
||||
local params = { textDocument = { uri = uri } }
|
||||
for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do
|
||||
|
@ -571,7 +573,9 @@ local function buf_attach(bufnr, client_id)
|
|||
client.attached_buffers[bufnr] = nil
|
||||
end
|
||||
util.buf_versions[bufnr] = nil
|
||||
attached_buffers[bufnr] = nil
|
||||
end,
|
||||
|
||||
-- TODO if we know all of the potential clients ahead of time, then we
|
||||
-- could conditionally set this.
|
||||
-- utf_sizes = size_index > 1;
|
||||
|
@ -597,16 +601,14 @@ function lsp.buf_attach_client(bufnr, client_id)
|
|||
log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr))
|
||||
return false
|
||||
end
|
||||
-- This is our first time attaching to this buffer.
|
||||
if #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 then
|
||||
buf_attach(bufnr, client_id)
|
||||
end
|
||||
|
||||
local client = lsp.get_client_by_id(client_id)
|
||||
if not client then
|
||||
return false
|
||||
end
|
||||
|
||||
buf_attach(bufnr)
|
||||
|
||||
if client.attached_buffers[bufnr] then
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -37,7 +37,7 @@ local validate = vim.validate
|
|||
--- `is_closing` and `terminate`.
|
||||
--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
|
||||
--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
|
||||
--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?
|
||||
--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Directory to launch the `cmd` process. Not related to `root_dir`.
|
||||
--- (default: cwd)
|
||||
|
@ -506,25 +506,17 @@ function Client.create(config)
|
|||
}
|
||||
|
||||
-- Start the RPC client.
|
||||
local rpc --- @type vim.lsp.rpc.PublicClient?
|
||||
local config_cmd = config.cmd
|
||||
if type(config_cmd) == 'function' then
|
||||
rpc = config_cmd(dispatchers)
|
||||
self.rpc = config_cmd(dispatchers)
|
||||
else
|
||||
rpc = lsp.rpc.start(config_cmd, dispatchers, {
|
||||
self.rpc = lsp.rpc.start(config_cmd, dispatchers, {
|
||||
cwd = config.cmd_cwd,
|
||||
env = config.cmd_env,
|
||||
detached = config.detached,
|
||||
})
|
||||
end
|
||||
|
||||
-- Return nil if the rpc client fails to start
|
||||
if not rpc then
|
||||
return
|
||||
end
|
||||
|
||||
self.rpc = rpc
|
||||
|
||||
setmetatable(self, Client)
|
||||
|
||||
return self
|
||||
|
|
|
@ -41,13 +41,13 @@ function M.on_inlayhint(err, result, ctx, _)
|
|||
bufstate.client_hints = vim.defaulttable()
|
||||
bufstate.version = ctx.version
|
||||
end
|
||||
local hints_by_client = bufstate.client_hints
|
||||
local client_hints = bufstate.client_hints
|
||||
local client = assert(vim.lsp.get_client_by_id(client_id))
|
||||
|
||||
local new_hints_by_lnum = vim.defaulttable()
|
||||
local new_lnum_hints = vim.defaulttable()
|
||||
local num_unprocessed = #result
|
||||
if num_unprocessed == 0 then
|
||||
hints_by_client[client_id] = {}
|
||||
client_hints[client_id] = {}
|
||||
bufstate.version = ctx.version
|
||||
api.nvim__buf_redraw_range(bufnr, 0, -1)
|
||||
return
|
||||
|
@ -73,10 +73,10 @@ function M.on_inlayhint(err, result, ctx, _)
|
|||
for _, hint in ipairs(result) do
|
||||
local lnum = hint.position.line
|
||||
hint.position.character = pos_to_byte(hint.position)
|
||||
table.insert(new_hints_by_lnum[lnum], hint)
|
||||
table.insert(new_lnum_hints[lnum], hint)
|
||||
end
|
||||
|
||||
hints_by_client[client_id] = new_hints_by_lnum
|
||||
client_hints[client_id] = new_lnum_hints
|
||||
bufstate.version = ctx.version
|
||||
api.nvim__buf_redraw_range(bufnr, 0, -1)
|
||||
end
|
||||
|
@ -175,19 +175,19 @@ function M.get(filter)
|
|||
end
|
||||
|
||||
--- @type vim.lsp.inlay_hint.get.ret[]
|
||||
local hints = {}
|
||||
local result = {}
|
||||
for _, client in pairs(clients) do
|
||||
local hints_by_lnum = bufstate.client_hints[client.id]
|
||||
if hints_by_lnum then
|
||||
local lnum_hints = bufstate.client_hints[client.id]
|
||||
if lnum_hints then
|
||||
for lnum = range.start.line, range['end'].line do
|
||||
local line_hints = hints_by_lnum[lnum] or {}
|
||||
for _, hint in pairs(line_hints) do
|
||||
local hints = lnum_hints[lnum] or {}
|
||||
for _, hint in pairs(hints) do
|
||||
local line, char = hint.position.line, hint.position.character
|
||||
if
|
||||
(line > range.start.line or char >= range.start.character)
|
||||
and (line < range['end'].line or char <= range['end'].character)
|
||||
then
|
||||
table.insert(hints, {
|
||||
table.insert(result, {
|
||||
bufnr = bufnr,
|
||||
client_id = client.id,
|
||||
inlay_hint = hint,
|
||||
|
@ -197,7 +197,7 @@ function M.get(filter)
|
|||
end
|
||||
end
|
||||
end
|
||||
return hints
|
||||
return result
|
||||
end
|
||||
|
||||
--- Clear inlay hints
|
||||
|
@ -315,14 +315,14 @@ api.nvim_set_decoration_provider(namespace, {
|
|||
if not bufstate.client_hints then
|
||||
return
|
||||
end
|
||||
local hints_by_client = assert(bufstate.client_hints)
|
||||
local client_hints = assert(bufstate.client_hints)
|
||||
|
||||
for lnum = topline, botline do
|
||||
if bufstate.applied[lnum] ~= bufstate.version then
|
||||
api.nvim_buf_clear_namespace(bufnr, namespace, lnum, lnum + 1)
|
||||
for _, hints_by_lnum in pairs(hints_by_client) do
|
||||
local line_hints = hints_by_lnum[lnum] or {}
|
||||
for _, hint in pairs(line_hints) do
|
||||
for _, lnum_hints in pairs(client_hints) do
|
||||
local hints = lnum_hints[lnum] or {}
|
||||
for _, hint in pairs(hints) do
|
||||
local text = ''
|
||||
local label = hint.label
|
||||
if type(label) == 'string' then
|
||||
|
|
|
@ -645,9 +645,23 @@ function M.connect(host_or_path, port)
|
|||
or assert(uv.new_tcp(), 'Could not create new TCP socket')
|
||||
)
|
||||
local closing = false
|
||||
-- Connect returns a PublicClient synchronously so the caller
|
||||
-- can immediately send messages before the connection is established
|
||||
-- -> Need to buffer them until that happens
|
||||
local connected = false
|
||||
-- size should be enough because the client can't really do anything until initialization is done
|
||||
-- which required a response from the server - implying the connection got established
|
||||
local msgbuf = vim.ringbuf(10)
|
||||
local transport = {
|
||||
write = function(msg)
|
||||
handle:write(msg)
|
||||
if connected then
|
||||
local _, err = handle:write(msg)
|
||||
if err and not closing then
|
||||
log.error('Error on handle:write: %q', err)
|
||||
end
|
||||
else
|
||||
msgbuf:push(msg)
|
||||
end
|
||||
end,
|
||||
is_closing = function()
|
||||
return closing
|
||||
|
@ -679,6 +693,10 @@ function M.connect(host_or_path, port)
|
|||
handle:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
|
||||
client:on_error(M.client_errors.READ_ERROR, read_err)
|
||||
end))
|
||||
connected = true
|
||||
for msg in msgbuf do
|
||||
handle:write(msg)
|
||||
end
|
||||
end
|
||||
if port == nil then
|
||||
handle:connect(host_or_path, on_connect)
|
||||
|
@ -704,7 +722,7 @@ end
|
|||
--- @param cmd string[] Command to start the LSP server.
|
||||
--- @param dispatchers? vim.lsp.rpc.Dispatchers
|
||||
--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams
|
||||
--- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods:
|
||||
--- @return vim.lsp.rpc.PublicClient : Client RPC object, with these methods:
|
||||
--- - `notify()` |vim.lsp.rpc.notify()|
|
||||
--- - `request()` |vim.lsp.rpc.request()|
|
||||
--- - `is_closing()` returns a boolean indicating if the RPC is closing.
|
||||
|
@ -779,8 +797,7 @@ function M.start(cmd, dispatchers, extra_spawn_params)
|
|||
end
|
||||
local msg =
|
||||
string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx)
|
||||
vim.notify(msg, vim.log.levels.WARN)
|
||||
return nil
|
||||
error(msg)
|
||||
end
|
||||
|
||||
sysobj = sysobj_or_err --[[@as vim.SystemObj]]
|
||||
|
|
|
@ -257,7 +257,7 @@ end
|
|||
---@param row integer Position row
|
||||
---@param col integer Position column
|
||||
---
|
||||
---@return table[] List of captures `{ capture = "name", metadata = { ... } }`
|
||||
---@return {capture: string, lang: string, metadata: table}[]
|
||||
function M.get_captures_at_pos(bufnr, row, col)
|
||||
if bufnr == 0 then
|
||||
bufnr = api.nvim_get_current_buf()
|
||||
|
|
|
@ -258,7 +258,7 @@ function FoldInfo:foldupdate(bufnr, srow, erow)
|
|||
self.foldupdate_range = { srow, erow }
|
||||
end
|
||||
|
||||
if api.nvim_get_mode().mode == 'i' then
|
||||
if api.nvim_get_mode().mode:match('^i') then
|
||||
-- foldUpdate() is guarded in insert mode. So update folds on InsertLeave
|
||||
if #(api.nvim_get_autocmds({
|
||||
group = group,
|
||||
|
|
|
@ -47,8 +47,8 @@ typedef struct {
|
|||
#define VALID_VIRTCOL 0x04 // w_virtcol (file col) is valid
|
||||
#define VALID_CHEIGHT 0x08 // w_cline_height and w_cline_folded valid
|
||||
#define VALID_CROW 0x10 // w_cline_row is valid
|
||||
#define VALID_BOTLINE 0x20 // w_botine and w_empty_rows are valid
|
||||
#define VALID_BOTLINE_AP 0x40 // w_botine is approximated
|
||||
#define VALID_BOTLINE 0x20 // w_botline and w_empty_rows are valid
|
||||
#define VALID_BOTLINE_AP 0x40 // w_botline is approximated
|
||||
#define VALID_TOPLINE 0x80 // w_topline is valid (for cursor position)
|
||||
|
||||
// flags for b_flags
|
||||
|
|
|
@ -918,15 +918,15 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
|||
for (int i = 0; i < xp->xp_numfiles; i++) {
|
||||
if (i > 0) {
|
||||
if (xp->xp_prefix == XP_PREFIX_NO) {
|
||||
ssp = xstpcpy(ssp, "no");
|
||||
ssp = STPCPY(ssp, "no");
|
||||
} else if (xp->xp_prefix == XP_PREFIX_INV) {
|
||||
ssp = xstpcpy(ssp, "inv");
|
||||
ssp = STPCPY(ssp, "inv");
|
||||
}
|
||||
}
|
||||
ssp = xstpcpy(ssp, xp->xp_files[i]);
|
||||
ssp = STPCPY(ssp, xp->xp_files[i]);
|
||||
|
||||
if (i != xp->xp_numfiles - 1) {
|
||||
ssp = xstpcpy(ssp, (options & WILD_USE_NL) ? "\n" : " ");
|
||||
ssp = STPCPY(ssp, (options & WILD_USE_NL) ? "\n" : " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11621,6 +11621,10 @@ M.funcs = {
|
|||
synconcealed(lnum, 4) [1, 'X', 2]
|
||||
synconcealed(lnum, 5) [1, 'X', 2]
|
||||
synconcealed(lnum, 6) [0, '', 0]
|
||||
|
||||
Note: Doesn't consider |matchadd()| highlighting items,
|
||||
since syntax and matching highlighting are two different
|
||||
mechanisms |syntax-vs-match|.
|
||||
]=],
|
||||
name = 'synconcealed',
|
||||
params = { { 'lnum', 'integer' }, { 'col', 'integer' } },
|
||||
|
|
|
@ -156,8 +156,8 @@ char *ga_concat_strings_sep(const garray_T *gap, const char *sep)
|
|||
|
||||
char *s = ret;
|
||||
for (size_t i = 0; i < nelem - 1; i++) {
|
||||
s = xstpcpy(s, strings[i]);
|
||||
s = xstpcpy(s, sep);
|
||||
s = STPCPY(s, strings[i]);
|
||||
s = STPCPY(s, sep);
|
||||
}
|
||||
strcpy(s, strings[nelem - 1]); // NOLINT(runtime/printf)
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ int ml_open(buf_T *buf)
|
|||
b0p->b0_magic_int = B0_MAGIC_INT;
|
||||
b0p->b0_magic_short = (int16_t)B0_MAGIC_SHORT;
|
||||
b0p->b0_magic_char = B0_MAGIC_CHAR;
|
||||
xstrlcpy(xstpcpy(b0p->b0_version, "VIM "), Version, 6);
|
||||
xstrlcpy(STPCPY(b0p->b0_version, "VIM "), Version, 6);
|
||||
long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
|
||||
|
||||
if (!buf->b_spell) {
|
||||
|
|
|
@ -347,43 +347,16 @@ size_t memcnt(const void *data, char c, size_t len)
|
|||
return cnt;
|
||||
}
|
||||
|
||||
/// Copies the string pointed to by src (including the terminating NUL
|
||||
/// character) into the array pointed to by dst.
|
||||
///
|
||||
/// @returns pointer to the terminating NUL char copied into the dst buffer.
|
||||
/// This is the only difference with strcpy(), which returns dst.
|
||||
///
|
||||
/// WARNING: If copying takes place between objects that overlap, the behavior
|
||||
/// is undefined.
|
||||
///
|
||||
/// Nvim version of POSIX 2008 stpcpy(3). We do not require POSIX 2008, so
|
||||
/// implement our own version.
|
||||
///
|
||||
/// @param dst
|
||||
/// @param src
|
||||
#ifndef HAVE_STPCPY
|
||||
char *xstpcpy(char *restrict dst, const char *restrict src)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const size_t len = strlen(src);
|
||||
return (char *)memcpy(dst, src, len + 1) + len;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Copies not more than n bytes (bytes that follow a NUL character are not
|
||||
/// copied) from the array pointed to by src to the array pointed to by dst.
|
||||
///
|
||||
/// If a NUL character is written to the destination, xstpncpy() returns the
|
||||
/// address of the first such NUL character. Otherwise, it shall return
|
||||
/// &dst[maxlen].
|
||||
///
|
||||
/// WARNING: If copying takes place between objects that overlap, the behavior
|
||||
/// is undefined.
|
||||
///
|
||||
/// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than
|
||||
/// maxlen, zeroes will be written to the remaining bytes.
|
||||
///
|
||||
/// @param dst
|
||||
/// @param src
|
||||
/// @param maxlen
|
||||
#ifndef HAVE_STPNCPY
|
||||
char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
|
@ -398,6 +371,7 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen)
|
|||
return dst + maxlen;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// xstrlcpy - Copy a NUL-terminated string into a sized buffer
|
||||
///
|
||||
|
|
|
@ -68,6 +68,19 @@ EXTERN size_t arena_alloc_count INIT( = 0);
|
|||
# define strnlen xstrnlen // Older versions of SunOS may not have strnlen
|
||||
#endif
|
||||
|
||||
// MacOS doesn't have HAVE_STPCPY defined and defines its own stpcpy in Xcode. So just define STPCPY
|
||||
#ifdef HAVE_STPCPY
|
||||
# define STPCPY stpcpy
|
||||
#else
|
||||
# define STPCPY xstpcpy
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STPNCPY
|
||||
# define STPNCPY stpncpy
|
||||
#else
|
||||
# define STPNCPY xstpncpy
|
||||
#endif
|
||||
|
||||
#define STRCPY(d, s) strcpy((char *)(d), (char *)(s)) // NOLINT(runtime/printf)
|
||||
|
||||
// Like strcpy() but allows overlapped source and destination.
|
||||
|
|
|
@ -2467,6 +2467,7 @@ void win_init_empty(win_T *wp)
|
|||
wp->w_topline = 1;
|
||||
wp->w_topfill = 0;
|
||||
wp->w_botline = 2;
|
||||
wp->w_valid = 0;
|
||||
wp->w_s = &wp->w_buffer->b_s;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,19 +169,19 @@ describe('vim.iter', function()
|
|||
end
|
||||
end)
|
||||
|
||||
it('skipback()', function()
|
||||
it('rskip()', function()
|
||||
do
|
||||
local q = { 4, 3, 2, 1 }
|
||||
eq(q, vim.iter(q):skipback(0):totable())
|
||||
eq({ 4, 3, 2 }, vim.iter(q):skipback(1):totable())
|
||||
eq({ 4, 3 }, vim.iter(q):skipback(2):totable())
|
||||
eq({ 4 }, vim.iter(q):skipback(#q - 1):totable())
|
||||
eq({}, vim.iter(q):skipback(#q):totable())
|
||||
eq({}, vim.iter(q):skipback(#q + 1):totable())
|
||||
eq(q, vim.iter(q):rskip(0):totable())
|
||||
eq({ 4, 3, 2 }, vim.iter(q):rskip(1):totable())
|
||||
eq({ 4, 3 }, vim.iter(q):rskip(2):totable())
|
||||
eq({ 4 }, vim.iter(q):rskip(#q - 1):totable())
|
||||
eq({}, vim.iter(q):rskip(#q):totable())
|
||||
eq({}, vim.iter(q):rskip(#q + 1):totable())
|
||||
end
|
||||
|
||||
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
||||
matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0))
|
||||
matches('rskip%(%) requires a list%-like table', pcall_err(it.rskip, it, 0))
|
||||
end)
|
||||
|
||||
it('slice()', function()
|
||||
|
@ -222,19 +222,19 @@ describe('vim.iter', function()
|
|||
end
|
||||
end)
|
||||
|
||||
it('nthback()', function()
|
||||
it('nth(-x) advances in reverse order starting from end', function()
|
||||
do
|
||||
local q = { 4, 3, 2, 1 }
|
||||
eq(nil, vim.iter(q):nthback(0))
|
||||
eq(1, vim.iter(q):nthback(1))
|
||||
eq(2, vim.iter(q):nthback(2))
|
||||
eq(3, vim.iter(q):nthback(3))
|
||||
eq(4, vim.iter(q):nthback(4))
|
||||
eq(nil, vim.iter(q):nthback(5))
|
||||
eq(nil, vim.iter(q):nth(0))
|
||||
eq(1, vim.iter(q):nth(-1))
|
||||
eq(2, vim.iter(q):nth(-2))
|
||||
eq(3, vim.iter(q):nth(-3))
|
||||
eq(4, vim.iter(q):nth(-4))
|
||||
eq(nil, vim.iter(q):nth(-5))
|
||||
end
|
||||
|
||||
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
||||
matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
|
||||
matches('rskip%(%) requires a list%-like table', pcall_err(it.nth, it, -1))
|
||||
end)
|
||||
|
||||
it('take()', function()
|
||||
|
@ -421,34 +421,34 @@ describe('vim.iter', function()
|
|||
end
|
||||
end)
|
||||
|
||||
it('nextback()', function()
|
||||
it('pop()', function()
|
||||
do
|
||||
local it = vim.iter({ 1, 2, 3, 4 })
|
||||
eq(4, it:nextback())
|
||||
eq(3, it:nextback())
|
||||
eq(2, it:nextback())
|
||||
eq(1, it:nextback())
|
||||
eq(nil, it:nextback())
|
||||
eq(nil, it:nextback())
|
||||
eq(4, it:pop())
|
||||
eq(3, it:pop())
|
||||
eq(2, it:pop())
|
||||
eq(1, it:pop())
|
||||
eq(nil, it:pop())
|
||||
eq(nil, it:pop())
|
||||
end
|
||||
|
||||
do
|
||||
local it = vim.iter(vim.gsplit('hi', ''))
|
||||
matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
|
||||
matches('pop%(%) requires a list%-like table', pcall_err(it.pop, it))
|
||||
end
|
||||
end)
|
||||
|
||||
it('peekback()', function()
|
||||
it('rpeek()', function()
|
||||
do
|
||||
local it = vim.iter({ 1, 2, 3, 4 })
|
||||
eq(4, it:peekback())
|
||||
eq(4, it:peekback())
|
||||
eq(4, it:nextback())
|
||||
eq(4, it:rpeek())
|
||||
eq(4, it:rpeek())
|
||||
eq(4, it:pop())
|
||||
end
|
||||
|
||||
do
|
||||
local it = vim.iter(vim.gsplit('hi', ''))
|
||||
matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
|
||||
matches('rpeek%(%) requires a list%-like table', pcall_err(it.rpeek, it))
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ describe(':Man', function()
|
|||
'--headless',
|
||||
'+autocmd VimLeave * echo "quit works!!"',
|
||||
'+Man!',
|
||||
'+tag ls',
|
||||
'+call nvim_input("q")',
|
||||
}
|
||||
matches('quit works!!', fn.system(args, { 'manpage contents' }))
|
||||
|
|
|
@ -4105,4 +4105,16 @@ func Test_SwapExists_set_other_buf_modified()
|
|||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_BufEnter_botline()
|
||||
set hidden
|
||||
call writefile(range(10), 'Xxx1', 'D')
|
||||
call writefile(range(20), 'Xxx2', 'D')
|
||||
edit Xxx1
|
||||
edit Xxx2
|
||||
au BufEnter Xxx1 call assert_true(line('w$') > 1)
|
||||
edit Xxx1
|
||||
au! BufEnter Xxx1
|
||||
set hidden&vim
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
|
Loading…
Reference in New Issue