aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/compiler/svelte-check.vim19
-rw-r--r--runtime/doc/api.txt10
-rw-r--r--runtime/doc/builtin.txt3
-rw-r--r--runtime/doc/diagnostic.txt2
-rw-r--r--runtime/doc/filetype.txt2
-rw-r--r--runtime/doc/insert.txt5
-rw-r--r--runtime/doc/intro.txt2
-rw-r--r--runtime/doc/lsp.txt2
-rw-r--r--runtime/doc/lua-bit.txt385
-rw-r--r--runtime/doc/lua.txt3
-rw-r--r--runtime/doc/luvref.txt2
-rw-r--r--runtime/doc/news.txt20
-rw-r--r--runtime/doc/treesitter.txt2
-rw-r--r--runtime/doc/ui.txt3
-rw-r--r--runtime/doc/vim_diff.txt1
-rw-r--r--runtime/ftplugin/checkhealth.lua14
-rw-r--r--runtime/ftplugin/dnsmasq.vim11
-rw-r--r--runtime/ftplugin/dockerfile.vim5
-rw-r--r--runtime/ftplugin/dosini.vim5
-rw-r--r--runtime/ftplugin/help.lua55
-rw-r--r--runtime/ftplugin/lua.lua5
-rw-r--r--runtime/ftplugin/mail.vim7
-rw-r--r--runtime/ftplugin/markdown.lua14
-rw-r--r--runtime/ftplugin/sieve.vim13
-rw-r--r--runtime/lua/vim/_defaults.lua8
-rw-r--r--runtime/lua/vim/_editor.lua2
-rw-r--r--runtime/lua/vim/_meta/api.lua8
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua1
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua3
-rw-r--r--runtime/lua/vim/_options.lua6
-rw-r--r--runtime/lua/vim/filetype.lua13
-rw-r--r--runtime/lua/vim/lsp/completion.lua4
-rw-r--r--runtime/lua/vim/lsp/util.lua5
-rw-r--r--runtime/lua/vim/treesitter.lua13
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua12
-rw-r--r--runtime/lua/vim/treesitter/_headings.lua144
-rw-r--r--runtime/lua/vim/treesitter/_meta/tsnode.lua2
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua7
-rw-r--r--runtime/lua/vim/treesitter/language.lua1
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua119
-rw-r--r--runtime/lua/vim/treesitter/query.lua10
-rw-r--r--runtime/lua/vim/vimhelp.lua71
-rw-r--r--runtime/pack/dist/opt/netrw/doc/netrw.txt130
-rw-r--r--runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim21
-rw-r--r--runtime/syntax/vim.vim47
45 files changed, 869 insertions, 348 deletions
diff --git a/runtime/compiler/svelte-check.vim b/runtime/compiler/svelte-check.vim
new file mode 100644
index 0000000000..883aefdbc4
--- /dev/null
+++ b/runtime/compiler/svelte-check.vim
@@ -0,0 +1,19 @@
+" Vim compiler file
+" Compiler: svelte-check
+" Maintainer: @Konfekt
+" Last Change: 2025 Feb 22
+
+if exists("current_compiler") | finish | endif
+let current_compiler = "svelte-check"
+
+CompilerSet makeprg=npx\ svelte-check\ --output\ machine
+CompilerSet errorformat=%*\\d\ %t%*\\a\ \"%f\"\ %l:%c\ %m
+CompilerSet errorformat+=%-G%.%#
+
+" " Fall-back for versions of svelte-check that don't support --output machine
+" " before May 2020 https://github.com/sveltejs/language-tools/commit/9f7a90379d287a41621a5e78af5b010a8ab810c3
+" " which is before the first production release 1.1.31 of Svelte-Check
+" CompilerSet makeprg=npx\ svelte-check
+" CompilerSet errorformat=%E%f:%l:%c,
+" CompilerSet errorformat+=%+ZError\:\ %m,
+" CompilerSet errorformat+=%-G%.%#
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 4f76e7e058..ec3dfebbc0 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -2649,8 +2649,14 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
lines are placed below the buffer line containing the
mark.
• virt_lines_above: place virtual lines above instead.
- • virt_lines_leftcol: Place extmarks in the leftmost column
- of the window, bypassing sign and number columns.
+ • virt_lines_leftcol: Place virtual lines in the leftmost
+ column of the window, bypassing sign and number columns.
+ • virt_lines_overflow: controls how to handle virtual lines
+ wider than the window. Currently takes the one of the
+ following values:
+ • "trunc": truncate virtual lines on the right (default).
+ • "scroll": virtual lines can scroll horizontally with
+ 'nowrap', otherwise the same as "trunc".
• ephemeral : for use with |nvim_set_decoration_provider()|
callbacks. The mark will only be used for the current
redraw cycle, and not be permantently stored in the
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 77d44c36a0..ae7fa8bcf9 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2167,7 +2167,8 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()*
When {expr3} is omitted then "force" is assumed.
{expr1} is changed when {expr2} is not empty. If necessary
- make a copy of {expr1} first.
+ make a copy of {expr1} first or use |extendnew()| to return a
+ new List/Dictionary.
{expr2} remains unchanged.
When {expr1} is locked and {expr2} is not empty the operation
fails.
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 5e1e04ce56..bbc1d1de2c 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -373,7 +373,7 @@ EVENTS *diagnostic-events*
*DiagnosticChanged*
DiagnosticChanged After diagnostics have changed. When used from Lua,
the new diagnostics are passed to the autocmd
- callback in the "data" table.
+ callback in the "data" table. Triggered per buffer.
Example: >lua
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index cc520484b3..b3fe13bfbd 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -708,7 +708,7 @@ Options:
You can also format quoted text with |gq|.
Local mappings:
-<LocalLeader>q or \\MailQuote
+<LocalLeader>q or \MailQuote
Quotes the text selected in Visual mode, or from the cursor position
to the end of the file in Normal mode. This means "> " is inserted in
each line.
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index 06f1a4e73d..8072b41466 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1502,6 +1502,11 @@ both major engines implemented element, even if this is not in standards it
will be suggested. All other elements are not placed in suggestion list.
+LUA *ft-lua-omni*
+
+Lua |ftplugin| sets 'omnifunc' to |vim.lua_omnifunc()|.
+
+
PHP *ft-php-omni*
Completion of PHP code requires a tags file for completion of data from
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index 0c654b8b30..5cb969a531 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -272,6 +272,8 @@ notation meaning equivalent decimal value(s) ~
<S-F1> - <S-F12> shift-function keys 1 to 12 *<S-F1>*
<Help> help key
<Undo> undo key
+<Find> find key
+<Select> select key
<Insert> insert key
<Home> home *home*
<End> end *end*
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 93b5d3cdcc..37f4d43e2c 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -119,7 +119,7 @@ Results in the configuration: >lua
root_markers = { '.clangd', 'compile_commands.json' },
-- From the clangd configuration in init.lua
- -- Overrides the * configuration in init.lua
+ -- Overrides the clangd configuration in <rtp>/lsp/clangd.lua
filetypes = { 'c' },
-- From the * configuration in init.lua
diff --git a/runtime/doc/lua-bit.txt b/runtime/doc/lua-bit.txt
new file mode 100644
index 0000000000..4c47010113
--- /dev/null
+++ b/runtime/doc/lua-bit.txt
@@ -0,0 +1,385 @@
+*lua-bit.txt* Nvim
+ *lua-bit*
+
+ LUA BITOP REFERENCE MANUAL
+
+
+ Adapted from <https://bitop.luajit.org>
+
+
+Lua BitOp is a C extension module for Lua 5.1/5.2 which adds bitwise
+operations on numbers.
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+API FUNCTIONS *lua-bit-api*
+
+This list of API functions is not intended to replace a tutorial. If you are
+not familiar with the terms used, you may want to study the Wikipedia article
+on bitwise operations (https://en.wikipedia.org/wiki/Bitwise_operation) first.
+
+------------------------------------------------------------------------------
+Loading the BitOp module
+ *lua-bit-module*
+
+The suggested way to use the BitOp module is to add the following to the start
+of every Lua file that needs one of its functions: >lua
+ local bit = require("bit")
+<
+This makes the dependency explicit, limits the scope to the current file and
+provides faster access to the bit.* functions, too. It's good programming
+practice not to rely on the global variable bit being set (assuming some other
+part of your application has already loaded the module). The require function
+ensures the module is only loaded once, in any case.
+
+------------------------------------------------------------------------------
+Defining Shortcuts
+ *lua-bit-shortcuts*
+
+It's a common (but not a required) practice to cache often used module
+functions in locals. This serves as a shortcut to save some typing and also
+speeds up resolving them (only relevant if called hundreds of thousands of
+times).
+>lua
+ local bnot = bit.bnot
+ local band, bor, bxor = bit.band, bit.bor, bit.bxor
+ local lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol
+ -- etc...
+
+ -- Example use of the shortcuts:
+ local function tr_i(a, b, c, d, x, s)
+ return rol(bxor(c, bor(b, bnot(d))) + a + x, s) + b
+ end
+<
+
+Remember that `and`, `or` and `not` are reserved keywords in Lua. They cannot
+be used for variable names or literal field names. That's why the
+corresponding bitwise functions have been named `band`, `bor`, and `bnot` (and
+`bxor` for consistency).
+
+While we are at it: a common pitfall is to use bit as the name of a local
+temporary variable — well, don't! :-)
+
+------------------------------------------------------------------------------
+About the Examples
+
+The examples below show small Lua one-liners. Their expected output is shown
+after `-->`. This is interpreted as a comment marker by Lua so you can cut &
+paste the whole line to a Lua prompt and experiment with it.
+
+Note that all bit operations return signed 32 bit numbers (rationale). And
+these print as signed decimal numbers by default.
+
+For clarity the examples assume the definition of a helper function
+`printx()`. This prints its argument as an unsigned 32 bit hexadecimal number
+on all platforms:
+>lua
+ function printx(x)
+ print("0x"..bit.tohex(x))
+ end
+<
+------------------------------------------------------------------------------
+Bit operations
+ *lua-bitop*
+
+y = bit.tobit(x) *bit.tobit()*
+ Normalizes a number to the numeric range for bit operations and returns
+ it. This function is usually not needed since all bit operations already
+ normalize all of their input arguments. Check the |luabit-semantics| for
+ details.
+
+ Example: >lua
+ print(0xffffffff) --> 4294967295 (*)
+ print(bit.tobit(0xffffffff)) --> -1
+ printx(bit.tobit(0xffffffff)) --> 0xffffffff
+ print(bit.tobit(0xffffffff + 1)) --> 0
+ print(bit.tobit(2^40 + 1234)) --> 1234
+<
+ (*) See the treatment of |lua-bit-hex-literals| for an explanation why the
+ printed numbers in the first two lines differ (if your Lua installation
+ uses a double number type).
+
+y = bit.tohex(x [,n]) *bit.tohex()*
+ Converts its first argument to a hex string. The number of hex digits is
+ given by the absolute value of the optional second argument. Positive
+ numbers between 1 and 8 generate lowercase hex digits. Negative numbers
+ generate uppercase hex digits. Only the least-significant `4*|n|` bits are
+ used. The default is to generate 8 lowercase hex digits.
+
+ Example: >lua
+ print(bit.tohex(1)) --> 00000001
+ print(bit.tohex(-1)) --> ffffffff
+ print(bit.tohex(0xffffffff)) --> ffffffff
+ print(bit.tohex(-1, -8)) --> FFFFFFFF
+ print(bit.tohex(0x21, 4)) --> 0021
+ print(bit.tohex(0x87654321, 4)) --> 4321
+<
+y = bit.bnot(x) *bit.bnot()*
+ Returns the bitwise `not` of its argument.
+
+ Example: >lua
+ print(bit.bnot(0)) --> -1
+ printx(bit.bnot(0)) --> 0xffffffff
+ print(bit.bnot(-1)) --> 0
+ print(bit.bnot(0xffffffff)) --> 0
+ printx(bit.bnot(0x12345678)) --> 0xedcba987
+<
+y = bit.bor(x1 [,x2...]) *bit.bor()*
+y = bit.band(x1 [,x2...]) *bit.band()*
+y = bit.bxor(x1 [,x2...]) *bit.bxor()*
+ Returns either the bitwise `or`, bitwise `and`, or bitwise `xor` of all of its
+ arguments. Note that more than two arguments are allowed.
+
+ Example: >lua
+ print(bit.bor(1, 2, 4, 8)) --> 15
+ printx(bit.band(0x12345678, 0xff)) --> 0x00000078
+ printx(bit.bxor(0xa5a5f0f0, 0xaa55ff00)) --> 0x0ff00ff0
+<
+y = bit.lshift(x, n) *bit.lshift()*
+y = bit.rshift(x, n) *bit.rshift()*
+y = bit.arshift(x, n) *bit.arshift()*
+ Returns either the bitwise `logical left-shift`, bitwise `logical`
+ `right-shift`, or bitwise `arithmetic right-shift` of its first argument
+ by the number of bits given by the second argument.
+
+ Logical shifts treat the first argument as an unsigned number and shift in
+ 0-bits. Arithmetic right-shift treats the most-significant bit as a sign
+ bit and replicates it. Only the lower 5 bits of the shift count are used
+ (reduces to the range [0..31]).
+
+ Example: >lua
+ print(bit.lshift(1, 0)) --> 1
+ print(bit.lshift(1, 8)) --> 256
+ print(bit.lshift(1, 40)) --> 256
+ print(bit.rshift(256, 8)) --> 1
+ print(bit.rshift(-256, 8)) --> 16777215
+ print(bit.arshift(256, 8)) --> 1
+ print(bit.arshift(-256, 8)) --> -1
+ printx(bit.lshift(0x87654321, 12)) --> 0x54321000
+ printx(bit.rshift(0x87654321, 12)) --> 0x00087654
+ printx(bit.arshift(0x87654321, 12)) --> 0xfff87654
+<
+y = bit.rol(x, n) *bit.rol()*
+y = bit.ror(x, n) *bit.ror()*
+ Returns either the bitwise `left rotation`, or bitwise `right rotation` of its
+ first argument by the number of bits given by the second argument. Bits
+ shifted out on one side are shifted back in on the other side.
+
+ Only the lower 5 bits of the rotate count are used (reduces to the range
+ [0..31]).
+
+ Example: >lua
+ printx(bit.rol(0x12345678, 12)) --> 0x45678123
+ printx(bit.ror(0x12345678, 12)) --> 0x67812345
+<
+y = bit.bswap(x)
+ Swaps the bytes of its argument and returns it. This can be used to
+ convert little-endian 32 bit numbers to big-endian 32 bit numbers or vice
+ versa.
+
+ Example: >lua
+ printx(bit.bswap(0x12345678)) --> 0x78563412
+ printx(bit.bswap(0x78563412)) --> 0x12345678
+<
+------------------------------------------------------------------------------
+Example Program
+
+This is an implementation of the (naïve) Sieve of Eratosthenes algorithm. It
+counts the number of primes up to some maximum number.
+
+A Lua table is used to hold a bit-vector. Every array index has 32 bits of the
+vector. Bitwise operations are used to access and modify them. Note that the
+shift counts don't need to be masked since this is already done by the BitOp
+shift and rotate functions.
+>lua
+ local bit = require("bit")
+ local band, bxor = bit.band, bit.bxor
+ local rshift, rol = bit.rshift, bit.rol
+
+ local m = tonumber(arg and arg[1]) or 100000
+ if m < 2 then m = 2 end
+ local count = 0
+ local p = {}
+
+ for i=0,(m+31)/32 do p[i] = -1 end
+
+ for i=2,m do
+ if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then
+ count = count + 1
+ for j=i+i,m,i do
+ local jx = rshift(j, 5)
+ p[jx] = band(p[jx], rol(-2, j))
+ end
+ end
+ end
+
+ io.write(string.format("Found %d primes up to %d\n", count, m))
+<
+Lua BitOp is quite fast. This program runs in less than 90 milliseconds on a 3
+GHz CPU with a standard Lua installation, but performs more than a million
+calls to bitwise functions. If you're looking for even more speed, check out
+|lua-luajit|.
+
+------------------------------------------------------------------------------
+Caveats *lua-bit-caveats*
+
+Signed Results ~
+
+Returning signed numbers from bitwise operations may be surprising to
+programmers coming from other programming languages which have both signed and
+unsigned types. But as long as you treat the results of bitwise operations
+uniformly everywhere, this shouldn't cause any problems.
+
+Preferably format results with `bit.tohex` if you want a reliable unsigned
+string representation. Avoid the `"%x"` or `"%u"` formats for `string.format`. They
+fail on some architectures for negative numbers and can return more than 8 hex
+digits on others.
+
+You may also want to avoid the default number to string coercion, since this
+is a signed conversion. The coercion is used for string concatenation and all
+standard library functions which accept string arguments (such as `print()` or
+`io.write()`).
+
+Conditionals ~
+
+If you're transcribing some code from C/C++, watch out for bit operations in
+conditionals. In C/C++ any non-zero value is implicitly considered as `true`.
+E.g. this C code: >c
+ if (x & 3) ...
+<
+must not be turned into this Lua code: >lua
+ if band(x, 3) then ... -- wrong!
+<
+In Lua all objects except `nil` and `false` are considered `true`. This
+includes all numbers. An explicit comparison against zero is required in this
+case: >lua
+ if band(x, 3) ~= 0 then ... -- correct!
+
+Comparing Against Hex Literals ~
+
+Comparing the results of bitwise operations (signed numbers) against hex
+literals (unsigned numbers) needs some additional care. The following
+conditional expression may or may not work right, depending on the platform
+you run it on: >lua
+ bit.bor(x, 1) == 0xffffffff
+<
+E.g. it's never true on a Lua installation with the default number type. Some
+simple solutions:
+
+ Never use hex literals larger than 0x7fffffff in comparisons: >lua
+ bit.bor(x, 1) == -1
+<
+ Or convert them with bit.tobit() before comparing: >lua
+ bit.bor(x, 1) == bit.tobit(0xffffffff)
+<
+ Or use a generic workaround with bit.bxor(): >lua
+ bit.bxor(bit.bor(x, 1), 0xffffffff) == 0
+<
+ Or use a case-specific workaround: >lua
+ bit.rshift(x, 1) == 0x7fffffff
+<
+==============================================================================
+OPERATIONAL SEMANTICS AND RATIONALE *lua-bit-semantics*
+
+
+Input and Output Ranges ~
+ *lua-bit-io-ranges*
+
+Bitwise operations cannot sensibly be applied to FP numbers (or their
+underlying bit patterns). They must be converted to integers before operating
+on them and then back to FP numbers.
+
+It's desirable to define semantics that work the same across all platforms.
+This dictates that all operations are based on the common denominator of 32
+bit integers. The `float` type provides only 24 bits of precision. This makes it
+unsuitable for use in bitwise operations. Lua BitOp refuses to compile against
+a Lua installation with this number type.
+
+Bit operations only deal with the underlying bit patterns and generally ignore
+signedness (except for arithmetic right-shift). They are commonly displayed
+and treated like unsigned numbers, though.
+
+But the Lua number type must be signed and may be limited to 32 bits. Defining
+the result type as an unsigned number would not be cross-platform safe. All
+bit operations are thus defined to return results in the range of signed 32
+bit numbers (converted to the Lua number type).
+
+ *lua-bit-hex-literals*
+Hexadecimal literals are treated as unsigned numbers by the Lua parser before
+converting them to the Lua number type. This means they can be out of the
+range of signed 32 bit integers if the Lua number type has a greater range.
+E.g. 0xffffffff has a value of 4294967295 in the default installation, but may
+be -1 on embedded systems. It's highly desirable that hex literals are treated
+uniformly across systems when used in bitwise operations. All bit operations
+accept arguments in the signed or the unsigned 32 bit range (and more, see
+below). Numbers with the same underlying bit pattern are treated the same by
+all operations.
+
+
+Modular Arithmetic ~
+ *lua-bit-modular-arith*
+
+Arithmetic operations on n-bit integers are usually based on the rules of
+modular arithmetic modulo 2^n. Numbers wrap around when the mathematical result
+of operations is outside their defined range. This simplifies hardware
+implementations and some algorithms actually require this behavior (like many
+cryptographic functions).
+
+E.g. for 32 bit integers the following holds: `0xffffffff + 1 = 0`
+
+Arithmetic modulo 2^32 is trivially available if the Lua number type is a 32
+bit integer. Otherwise normalization steps must be inserted. Modular
+arithmetic should work the same across all platforms as far as possible:
+
+- For the default number type of double, arguments can be in the range of
+ ±2^51 and still be safely normalized across all platforms by taking their
+ least-significant 32 bits. The limit is derived from the way doubles are
+ converted to integers.
+- The function bit.tobit can be used to explicitly normalize numbers to
+ implement modular addition or subtraction. E.g. >lua
+ bit.tobit(0xffffffff + 1)
+ returns 0 on all platforms.
+- The limit on the argument range implies that modular multiplication is
+ usually restricted to multiplying already normalized numbers with small
+ constants. FP numbers are limited to 53 bits of precision, anyway. E.g.
+ (2^30+1)^2 does not return an odd number when computed with doubles.
+
+BTW: The `tr_i` function shown here |lua-bit-shortcuts| is one of the
+non-linear functions of the (flawed) MD5 cryptographic hash and relies on
+modular arithmetic for correct operation. The result is fed back to other
+bitwise operations (not shown) and does not need to be normalized until the
+last step.
+
+
+Restricted and undefined behaviors ~
+ *lua-bit-restrictions*
+
+The following rules are intended to give a precise and useful definition (for
+the programmer), yet give the implementation (interpreter and compiler) the
+maximum flexibility and the freedom to apply advanced optimizations. It's
+strongly advised not to rely on undefined or implementation-defined behavior.
+
+- All kinds of floating-point numbers are acceptable to the bitwise
+ operations. None of them cause an error, but some may invoke undefined
+ behavior:
+ - -0 is treated the same as +0 on input and is never returned as a result.
+ - Passing ±Inf, NaN or numbers outside the range of ±2^51 as input yields
+ an undefined result.
+ - Non-integral numbers may be rounded or truncated in an
+ implementation-defined way. This means the result could differ between
+ different BitOp versions, different Lua VMs, on different platforms or
+ even between interpreted vs. compiled code (as in |LuaJIT|). Avoid
+ passing fractional numbers to bitwise functions. Use `math.floor()` or
+ `math.ceil()` to get defined behavior.
+- Lua provides auto-coercion of string arguments to numbers by default. This
+ behavior is deprecated for bitwise operations.
+
+==============================================================================
+COPYRIGHT
+
+Lua BitOp is Copyright (C) 2008-2012 Mike Pall.
+Lua BitOp is free software, released under the MIT license.
+
+==============================================================================
+ vim:tw=78:ts=4:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 0eca3286d0..ef2125841d 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -46,10 +46,9 @@ before using them: >lua
-- code for plain lua 5.1
end
<
- *lua-bit*
One exception is the LuaJIT `bit` extension, which is always available: when
built with PUC Lua, Nvim includes a fallback implementation which provides
-`require("bit")`.
+`require("bit")`. See |lua-bit|.
*lua-profile*
If Nvim is built with LuaJIT, Lua code can be profiled via >lua
diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt
index 3cbdb53e01..648060e1d5 100644
--- a/runtime/doc/luvref.txt
+++ b/runtime/doc/luvref.txt
@@ -226,7 +226,7 @@ ERROR HANDLING *luv-error-handling*
In libuv, errors are represented by negative numbered constants. While these
constants are made available in the `uv.errno` table, they are not returned by
-luv funtions and the libuv functions used to handle them are not exposed.
+luv functions and the libuv functions used to handle them are not exposed.
Instead, if an internal error is encountered, the failing luv function will
return to the caller an assertable `nil, err, name` tuple:
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index c98084adb6..e8ec6d1820 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -175,6 +175,7 @@ TREESITTER
the tree before returning. Scripts must call |LanguageTree:parse()| explicitly. >lua
local p = vim.treesitter.get_parser(0, 'c')
p:parse()
+• |vim.treesitter.get_parser()| expects its buffer to be loaded.
<
TUI
@@ -201,9 +202,12 @@ API
• |nvim_echo()| `err` field to print error messages and `chunks` accepts
highlight group IDs.
• |nvim_open_win()| `relative` field can be set to "laststatus" and "tabline".
-• |nvim_buf_set_extmark()| `hl_group` field can be an array of layered groups
+• |nvim_buf_set_extmark()| new field `virt_lines_overflow` accepts value `scroll` to
+ enable horizontal scrolling for virtual lines with 'nowrap'.
+ right aligned text that truncates before covering up buffer text.
+• |nvim_buf_set_extmark()| `hl_group` field can be an array of layered groups.
• |vim.hl.range()| now has a optional `timeout` field which allows for a timed highlight
-• |nvim_buf_set_extmark()| virt_text_pos accepts `eol_right_align` to
+• |nvim_buf_set_extmark()| `virt_text_pos` field accepts value `eol_right_align` to
allow for right aligned text that truncates before covering up buffer text.
DEFAULTS
@@ -235,6 +239,9 @@ DEFAULTS
• |[b|, |]b|, |[B|, |]B| navigate through the |buffer-list|
• |[<Space>|, |]<Space>| add an empty line above and below the cursor
+• Options:
+ • Lua |ftplugin| sets |'omnifunc'| to `"v:lua.vim.lua_omnifunc"`.
+
• Snippet:
• `<Tab>` in Insert and Select mode maps to `vim.snippet.jump({ direction = 1 })`
when a snippet is active and jumpable forwards.
@@ -261,6 +268,9 @@ EDITOR
to a literal "~" directory.
• |hl-ComplMatchIns| shows matched text of the currently inserted completion.
• |hl-PmenuMatch| and |hl-PmenuMatchSel| show matched text in completion popup.
+• |gO| now works in `help`, `checkhealth`, and `markdown` buffers.
+• Jump between sections in `help` and `checkhealth` buffers with `[[` and
+ `]]`.
EVENTS
@@ -302,6 +312,7 @@ LUA
• Command-line completions for: `vim.g`, `vim.t`, `vim.w`, `vim.b`, `vim.v`,
`vim.o`, `vim.wo`, `vim.bo`, `vim.opt`, `vim.opt_local`, `vim.opt_global`,
and `vim.fn`.
+• Documentation for |lua-bit|.
• |vim.fs.rm()| can delete files and directories.
• |vim.validate()| now has a new signature which uses less tables,
is more performant and easier to read.
@@ -335,6 +346,11 @@ PERFORMANCE
• Treesitter highlighting is now asynchronous. To force synchronous parsing,
use `vim.g._ts_force_sync_parsing = true`.
• Treesitter folding is now calculated asynchronously.
+• |LanguageTree:parse()| now only runs the injection query on the provided
+ range (as long as the language does not have a combined injection),
+ significantly improving |treesitter-highlight| performance.
+• Treesitter injection query iteration is now asynchronous, making edits in
+ large buffers with combined injections much quicker.
PLUGINS
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index b04f13add5..344bd37ddd 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -713,7 +713,7 @@ TSNode:extra() *TSNode:extra()*
(`boolean`)
TSNode:field({name}) *TSNode:field()*
- Returns a table of the nodes corresponding to the {name} field.
+ Returns a list of all the node's children that have the given field name.
Parameters: ~
• {name} (`string`)
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index d8a0e3d0d7..a3e09a9ea5 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -791,7 +791,8 @@ must handle.
Name indicating the message kind:
"" (empty) Unknown (consider a |feature-request|)
"bufwrite" |:write| message
- "confirm" |confirm()| or |:confirm| dialog
+ "confirm" Message preceding a prompt (|:confirm|,
+ |confirm()|, |inputlist()|, |z=,|, …)
"emsg" Error (|errors|, internal error, |:throw|, …)
"echo" |:echo| message
"echomsg" |:echomsg| message
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index eae341da49..1e1f6c4db7 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -46,6 +46,7 @@ Defaults *defaults* *nvim-defaults*
- 'compatible' is always disabled
- 'complete' excludes "i"
- 'define' defaults to "". The C ftplugin sets it to "^\\s*#\\s*define"
+- 'diffopt' defaults to "internal,filler,closeoff,linematch:40"
- 'directory' defaults to ~/.local/state/nvim/swap// (|xdg|), auto-created
- 'display' defaults to "lastline"
- 'encoding' is UTF-8 (cf. 'fileencoding' for file-content encoding)
diff --git a/runtime/ftplugin/checkhealth.lua b/runtime/ftplugin/checkhealth.lua
new file mode 100644
index 0000000000..d0f8cec074
--- /dev/null
+++ b/runtime/ftplugin/checkhealth.lua
@@ -0,0 +1,14 @@
+vim.keymap.set('n', 'gO', function()
+ require('vim.treesitter._headings').show_toc()
+end, { buffer = 0, silent = true, desc = 'Show table of contents for current buffer' })
+
+vim.keymap.set('n', ']]', function()
+ require('vim.treesitter._headings').jump({ count = 1, level = 1 })
+end, { buffer = 0, silent = false, desc = 'Jump to next section' })
+vim.keymap.set('n', '[[', function()
+ require('vim.treesitter._headings').jump({ count = -1, level = 1 })
+end, { buffer = 0, silent = false, desc = 'Jump to previous section' })
+
+vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
+ .. '\n sil! exe "nunmap <buffer> gO"'
+ .. '\n sil! exe "nunmap <buffer> ]]" | sil! exe "nunmap <buffer> [["'
diff --git a/runtime/ftplugin/dnsmasq.vim b/runtime/ftplugin/dnsmasq.vim
new file mode 100644
index 0000000000..bf93bf9300
--- /dev/null
+++ b/runtime/ftplugin/dnsmasq.vim
@@ -0,0 +1,11 @@
+" Vim filetype plugin
+" Language: dnsmasq
+" Maintainer: dringsim <dringsim@qq.com>
+" Last Change: 2025-02-18
+
+if exists('b:did_ftplugin')
+ finish
+endif
+
+" Behaves mostly just like cfg
+runtime! ftplugin/cfg.vim
diff --git a/runtime/ftplugin/dockerfile.vim b/runtime/ftplugin/dockerfile.vim
index e45bf4c1d8..f9268fe89b 100644
--- a/runtime/ftplugin/dockerfile.vim
+++ b/runtime/ftplugin/dockerfile.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Dockerfile
" Maintainer: Honza Pokorny <http://honza.ca>
-" Last Change: 2024 Dec 20
+" Last Change: 2025 Feb 21
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -11,6 +11,7 @@ endif
" Don't load another plugin for this buffer
let b:did_ftplugin = 1
+setlocal comments=:#
setlocal commentstring=#\ %s
-let b:undo_ftplugin = "setl commentstring<"
+let b:undo_ftplugin = "setl comments< commentstring<"
diff --git a/runtime/ftplugin/dosini.vim b/runtime/ftplugin/dosini.vim
index 6a53dfd096..3470bd3b3b 100644
--- a/runtime/ftplugin/dosini.vim
+++ b/runtime/ftplugin/dosini.vim
@@ -1,7 +1,8 @@
" Vim filetype plugin file
" Language: Configuration File (ini file) for MS-DOS/MS Windows
+" Maintainer: This runtime file is looking for a new maintainer.
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2008-07-09
+" Latest Revision: 2025 Feb 20
if exists("b:did_ftplugin")
finish
@@ -13,7 +14,7 @@ set cpo&vim
let b:undo_ftplugin = "setl com< cms< fo<"
-setlocal comments=:; commentstring=;\ %s formatoptions-=t formatoptions+=croql
+setlocal comments=:;,:# commentstring=;\ %s formatoptions-=t formatoptions+=croql
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/help.lua b/runtime/ftplugin/help.lua
index a6169a1d9d..e19571454d 100644
--- a/runtime/ftplugin/help.lua
+++ b/runtime/ftplugin/help.lua
@@ -1,15 +1,43 @@
-- use treesitter over syntax (for highlighted code blocks)
vim.treesitter.start()
+--- Apply current colorscheme to lists of default highlight groups
+---
+--- Note: {patterns} is assumed to be sorted by occurrence in the file.
+--- @param patterns {start:string,stop:string,match:string}[]
+local function colorize_hl_groups(patterns)
+ local ns = vim.api.nvim_create_namespace('nvim.vimhelp')
+ vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
+
+ local save_cursor = vim.fn.getcurpos()
+
+ for _, pat in pairs(patterns) do
+ local start_lnum = vim.fn.search(pat.start, 'c')
+ local end_lnum = vim.fn.search(pat.stop)
+ if start_lnum == 0 or end_lnum == 0 then
+ break
+ end
+
+ for lnum = start_lnum, end_lnum do
+ local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match(pat.match)
+ if vim.fn.hlexists(word) ~= 0 then
+ vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word })
+ end
+ end
+ end
+
+ vim.fn.setpos('.', save_cursor)
+end
+
-- Add custom highlights for list in `:h highlight-groups`.
local bufname = vim.fs.normalize(vim.api.nvim_buf_get_name(0))
if vim.endswith(bufname, '/doc/syntax.txt') then
- require('vim.vimhelp').highlight_groups({
+ colorize_hl_groups({
{ start = [[\*group-name\*]], stop = '^======', match = '^(%w+)\t' },
{ start = [[\*highlight-groups\*]], stop = '^======', match = '^(%w+)\t' },
})
elseif vim.endswith(bufname, '/doc/treesitter.txt') then
- require('vim.vimhelp').highlight_groups({
+ colorize_hl_groups({
{
start = [[\*treesitter-highlight-groups\*]],
stop = [[\*treesitter-highlight-spell\*]],
@@ -17,24 +45,31 @@ elseif vim.endswith(bufname, '/doc/treesitter.txt') then
},
})
elseif vim.endswith(bufname, '/doc/diagnostic.txt') then
- require('vim.vimhelp').highlight_groups({
+ colorize_hl_groups({
{ start = [[\*diagnostic-highlights\*]], stop = '^======', match = '^(%w+)' },
})
elseif vim.endswith(bufname, '/doc/lsp.txt') then
- require('vim.vimhelp').highlight_groups({
+ colorize_hl_groups({
{ start = [[\*lsp-highlight\*]], stop = '^------', match = '^(%w+)' },
{ start = [[\*lsp-semantic-highlight\*]], stop = '^======', match = '^@[%w%p]+' },
})
end
vim.keymap.set('n', 'gO', function()
- require('vim.vimhelp').show_toc()
-end, { buffer = 0, silent = true })
+ require('vim.treesitter._headings').show_toc()
+end, { buffer = 0, silent = true, desc = 'Show table of contents for current buffer' })
+
+vim.keymap.set('n', ']]', function()
+ require('vim.treesitter._headings').jump({ count = 1 })
+end, { buffer = 0, silent = false, desc = 'Jump to next section' })
+vim.keymap.set('n', '[[', function()
+ require('vim.treesitter._headings').jump({ count = -1 })
+end, { buffer = 0, silent = false, desc = 'Jump to previous section' })
-- Add "runnables" for Lua/Vimscript code examples.
---@type table<integer, { lang: string, code: string }>
local code_blocks = {}
-local tree = vim.treesitter.get_parser():parse()[1]
+local parser = assert(vim.treesitter.get_parser(0, 'vimdoc', { error = false }))
local query = vim.treesitter.query.parse(
'vimdoc',
[[
@@ -46,10 +81,11 @@ local query = vim.treesitter.query.parse(
(#set! @code lang @_lang))
]]
)
+local root = parser:parse()[1]:root()
local run_message_ns = vim.api.nvim_create_namespace('nvim.vimdoc.run_message')
vim.api.nvim_buf_clear_namespace(0, run_message_ns, 0, -1)
-for _, match, metadata in query:iter_matches(tree:root(), 0, 0, -1) do
+for _, match, metadata in query:iter_matches(root, 0, 0, -1) do
for id, nodes in pairs(match) do
local name = query.captures[id]
local node = nodes[1]
@@ -82,5 +118,6 @@ vim.keymap.set('n', 'g==', function()
end, { buffer = true })
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
- .. '\n exe "nunmap <buffer> gO" | exe "nunmap <buffer> g=="'
+ .. '\n sil! exe "nunmap <buffer> gO" | sil! exe "nunmap <buffer> g=="'
+ .. '\n sil! exe "nunmap <buffer> ]]" | sil! exe "nunmap <buffer> [["'
vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | call v:lua.vim.treesitter.stop()'
diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua
index 75deb6b190..e2a7631b29 100644
--- a/runtime/ftplugin/lua.lua
+++ b/runtime/ftplugin/lua.lua
@@ -1,4 +1,7 @@
-- use treesitter over syntax
vim.treesitter.start()
-vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n call v:lua.vim.treesitter.stop()'
+vim.bo.omnifunc = 'v:lua.vim.lua_omnifunc'
+
+vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
+ .. '\n call v:lua.vim.treesitter.stop() \n setl omnifunc<'
diff --git a/runtime/ftplugin/mail.vim b/runtime/ftplugin/mail.vim
index 3cef84f528..de88f4d1e8 100644
--- a/runtime/ftplugin/mail.vim
+++ b/runtime/ftplugin/mail.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Mail
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2025 Feb 20
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Only do this when not done yet for this buffer
@@ -10,7 +10,7 @@ if exists("b:did_ftplugin")
endif
let b:did_ftplugin = 1
-let b:undo_ftplugin = "setl modeline< tw< fo< comments<"
+let b:undo_ftplugin = "setl modeline< tw< fo< comments< commentstring<"
" Don't use modelines in e-mail messages, avoid trojan horses and nasty
" "jokes" (e.g., setting 'textwidth' to 5).
@@ -24,6 +24,9 @@ endif
" Set 'formatoptions' to break text lines and keep the comment leader ">".
setlocal fo+=tcql
+" Set commentstring to quoting sign ">" so comment shortcuts can be used to
+" edit quoted parts of mail
+setlocal commentstring=>\ %s
" Add n:> to 'comments, in case it was removed elsewhere
setlocal comments+=n:>
diff --git a/runtime/ftplugin/markdown.lua b/runtime/ftplugin/markdown.lua
new file mode 100644
index 0000000000..d9958706c8
--- /dev/null
+++ b/runtime/ftplugin/markdown.lua
@@ -0,0 +1,14 @@
+vim.keymap.set('n', 'gO', function()
+ require('vim.treesitter._headings').show_toc()
+end, { buffer = 0, silent = true, desc = 'Show table of contents for current buffer' })
+
+vim.keymap.set('n', ']]', function()
+ require('vim.treesitter._headings').jump({ count = 1 })
+end, { buffer = 0, silent = false, desc = 'Jump to next section' })
+vim.keymap.set('n', '[[', function()
+ require('vim.treesitter._headings').jump({ count = -1 })
+end, { buffer = 0, silent = false, desc = 'Jump to previous section' })
+
+vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
+ .. '\n sil! exe "nunmap <buffer> gO"'
+ .. '\n sil! exe "nunmap <buffer> ]]" | sil! exe "nunmap <buffer> [["'
diff --git a/runtime/ftplugin/sieve.vim b/runtime/ftplugin/sieve.vim
index 3092b5d2d3..8161fe99ac 100644
--- a/runtime/ftplugin/sieve.vim
+++ b/runtime/ftplugin/sieve.vim
@@ -1,20 +1,19 @@
" Vim filetype plugin file
" Language: Sieve filtering language input file
+" Maintainer: This runtime file is looking for a new maintainer.
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2008-07-09
+" Latest Revision: 2025 Feb 20
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
-let s:cpo_save = &cpo
-set cpo&vim
-
-let b:undo_ftplugin = "setl com< cms< fo<"
+let b:undo_ftplugin = "setl com< cms< fo< ff<"
setlocal comments=s1:/*,mb:*,ex:*/,:# commentstring=#\ %s
setlocal formatoptions-=t formatoptions+=croql
-let &cpo = s:cpo_save
-unlet s:cpo_save
+" https://datatracker.ietf.org/doc/html/rfc5228#section-2.2 says
+" "newlines (CRLF, never just CR or LF)"
+setlocal fileformat=dos
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index 6c8ef0ad9f..c2e4e76dd6 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -24,6 +24,14 @@ do
vim.api.nvim_create_user_command('EditQuery', function(cmd)
vim.treesitter.query.edit(cmd.fargs[1])
end, { desc = 'Edit treesitter query', nargs = '?' })
+
+ vim.api.nvim_create_user_command('Open', function(cmd)
+ vim.ui.open(cmd.fargs[1])
+ end, {
+ desc = 'Open file with system default handler. See :help vim.ui.open()',
+ nargs = 1,
+ complete = 'file',
+ })
end
--- Default mappings
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index a77ea9bb91..94168bea5d 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -56,7 +56,7 @@ vim._extra = {
inspect_pos = true,
}
---- @private
+--- @nodoc
vim.log = {
--- @enum vim.log.levels
levels = {
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 3d10729d23..a6ffb43146 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -638,10 +638,14 @@ function vim.api.nvim_buf_line_count(buffer) end
--- placed below the buffer line containing the mark.
---
--- - virt_lines_above: place virtual lines above instead.
---- - virt_lines_leftcol: Place extmarks in the leftmost
+--- - virt_lines_leftcol: Place virtual lines in the leftmost
--- column of the window, bypassing
--- sign and number columns.
----
+--- - virt_lines_overflow: controls how to handle virtual lines wider
+--- than the window. Currently takes the one of the following values:
+--- - "trunc": truncate virtual lines on the right (default).
+--- - "scroll": virtual lines can scroll horizontally with 'nowrap',
+--- otherwise the same as "trunc".
--- - ephemeral : for use with `nvim_set_decoration_provider()`
--- callbacks. The mark will only be used for the current
--- redraw cycle, and not be permantently stored in the
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index 4d0665872b..a66e373851 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -258,6 +258,7 @@ error('Cannot require a meta file')
--- @field virt_lines? any[]
--- @field virt_lines_above? boolean
--- @field virt_lines_leftcol? boolean
+--- @field virt_lines_overflow? string
--- @field strict? boolean
--- @field sign_text? string
--- @field sign_hl_group? integer|string
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index f4c395ce39..4970a3023b 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -1928,7 +1928,8 @@ function vim.fn.expandcmd(string, options) end
--- When {expr3} is omitted then "force" is assumed.
---
--- {expr1} is changed when {expr2} is not empty. If necessary
---- make a copy of {expr1} first.
+--- make a copy of {expr1} first or use |extendnew()| to return a
+--- new List/Dictionary.
--- {expr2} remains unchanged.
--- When {expr1} is locked and {expr2} is not empty the operation
--- fails.
diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua
index 973ad87ee8..e98b95f837 100644
--- a/runtime/lua/vim/_options.lua
+++ b/runtime/lua/vim/_options.lua
@@ -922,11 +922,11 @@ function Option:prepend(value) end -- luacheck: no unused
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:remove(value) end -- luacheck: no unused
----@private
+--- @nodoc
vim.opt = create_option_accessor()
----@private
+--- @nodoc
vim.opt_local = create_option_accessor('local')
----@private
+--- @nodoc
vim.opt_global = create_option_accessor('global')
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 6974b6508d..66ee45587a 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -1802,6 +1802,7 @@ local filename = {
Vagrantfile = 'ruby',
['smb.conf'] = 'samba',
['.lips_repl_history'] = 'scheme',
+ ['.guile'] = 'scheme',
screenrc = 'screen',
['.screenrc'] = 'screen',
['/etc/sensors3.conf'] = 'sensors',
@@ -2150,11 +2151,6 @@ local pattern = {
['/usr/.*/gnupg/options%.skel$'] = 'gpg',
['/usr/share/upstart/.*%.conf$'] = 'upstart',
['/usr/share/upstart/.*%.override$'] = 'upstart',
- ['/usr/share/X11/xkb/compat/'] = detect_xkb,
- ['/usr/share/X11/xkb/geometry/'] = detect_xkb,
- ['/usr/share/X11/xkb/keycodes/'] = detect_xkb,
- ['/usr/share/X11/xkb/symbols/'] = detect_xkb,
- ['/usr/share/X11/xkb/types/'] = detect_xkb,
},
['/var/'] = {
['/var/backups/group%.bak$'] = 'group',
@@ -2329,6 +2325,13 @@ local pattern = {
['^Neomuttrc'] = detect_neomuttrc,
['%.neomuttdebug'] = 'neomuttlog',
},
+ ['/%.?xkb/'] = {
+ ['/%.?xkb/compat/'] = detect_xkb,
+ ['/%.?xkb/geometry/'] = detect_xkb,
+ ['/%.?xkb/keycodes/'] = detect_xkb,
+ ['/%.?xkb/symbols/'] = detect_xkb,
+ ['/%.?xkb/types/'] = detect_xkb,
+ },
['^%.'] = {
['^%.cshrc'] = detect.csh,
['^%.login'] = detect.csh,
diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua
index d99b1ffd0d..1466dcf438 100644
--- a/runtime/lua/vim/lsp/completion.lua
+++ b/runtime/lua/vim/lsp/completion.lua
@@ -132,7 +132,7 @@ end
--- @return string
local function get_completion_word(item, prefix, match)
if item.insertTextFormat == protocol.InsertTextFormat.Snippet then
- if item.textEdit then
+ if item.textEdit or (item.insertText and item.insertText ~= '') then
-- Use label instead of text if text has different starting characters.
-- label is used as abbr (=displayed), but word is used for filtering
-- This is required for things like postfix completion.
@@ -154,8 +154,6 @@ local function get_completion_word(item, prefix, match)
else
return word
end
- elseif item.insertText and item.insertText ~= '' then
- return parse_snippet(item.insertText)
else
return item.label
end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 9e84e27205..905b9822ba 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -1417,6 +1417,11 @@ function M._make_floating_popup_size(contents, opts)
-- make sure borders are always inside the screen
width = math.min(width, screen_width - border_width)
+ -- Make sure that the width is large enough to fit the title.
+ if opts.title then
+ width = math.max(width, vim.fn.strdisplaywidth(opts.title))
+ end
+
if wrap_at then
wrap_at = math.min(wrap_at, width)
end
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 10638e10d8..44372415fd 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -34,8 +34,6 @@ M.minimum_language_version = vim._ts_get_minimum_language_version()
function M._create_parser(bufnr, lang, opts)
bufnr = vim._resolve_bufnr(bufnr)
- vim.fn.bufload(bufnr)
-
local self = LanguageTree.new(bufnr, lang, opts)
local function bytes_cb(_, ...)
@@ -102,6 +100,9 @@ function M.get_parser(bufnr, lang, opts)
return nil, err_msg
end
elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
+ if not api.nvim_buf_is_loaded(bufnr) then
+ error(('Buffer %s must be loaded to create parser'):format(bufnr))
+ end
local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts)
if not parser then
local err_msg =
@@ -415,6 +416,14 @@ end
---@param lang string? Language of the parser (default: from buffer filetype)
function M.start(bufnr, lang)
bufnr = vim._resolve_bufnr(bufnr)
+ -- Ensure buffer is loaded. `:edit` over `bufload()` to show swapfile prompt.
+ if not api.nvim_buf_is_loaded(bufnr) then
+ if api.nvim_buf_get_name(bufnr) ~= '' then
+ pcall(api.nvim_buf_call, bufnr, vim.cmd.edit)
+ else
+ vim.fn.bufload(bufnr)
+ end
+ end
local parser = assert(M.get_parser(bufnr, lang, { error = false }))
M.highlighter.new(parser)
end
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index 38318347a7..1064004320 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -75,7 +75,15 @@ local function compute_folds_levels(bufnr, info, srow, erow, callback)
erow = erow or api.nvim_buf_line_count(bufnr)
local parser = info.parser
- if not parser then
+ if
+ not parser
+ -- Parsing an empty buffer results in problems with the parsing state,
+ -- resulting in both a broken highlighter and foldexpr.
+ or api.nvim_buf_line_count(bufnr) == 1
+ and api.nvim_buf_call(bufnr, function()
+ return vim.fn.line2byte(1) <= 0
+ end)
+ then
return
end
@@ -380,7 +388,7 @@ function M.foldexpr(lnum)
if not foldinfos[bufnr] then
foldinfos[bufnr] = FoldInfo.new(bufnr)
- api.nvim_create_autocmd({ 'BufUnload', 'VimEnter' }, {
+ api.nvim_create_autocmd({ 'BufUnload', 'VimEnter', 'FileType' }, {
buffer = bufnr,
once = true,
callback = function()
diff --git a/runtime/lua/vim/treesitter/_headings.lua b/runtime/lua/vim/treesitter/_headings.lua
new file mode 100644
index 0000000000..4e8833c93a
--- /dev/null
+++ b/runtime/lua/vim/treesitter/_headings.lua
@@ -0,0 +1,144 @@
+local ts = vim.treesitter
+local api = vim.api
+
+--- Treesitter-based navigation functions for headings
+local M = {}
+
+-- TODO(clason): use runtimepath queries (for other languages)
+local heading_queries = {
+ vimdoc = [[
+ (h1 (heading) @h1)
+ (h2 (heading) @h2)
+ (h3 (heading) @h3)
+ (column_heading (heading) @h4)
+ ]],
+ markdown = [[
+ (setext_heading
+ heading_content: (_) @h1
+ (setext_h1_underline))
+ (setext_heading
+ heading_content: (_) @h2
+ (setext_h2_underline))
+ (atx_heading
+ (atx_h1_marker)
+ heading_content: (_) @h1)
+ (atx_heading
+ (atx_h2_marker)
+ heading_content: (_) @h2)
+ (atx_heading
+ (atx_h3_marker)
+ heading_content: (_) @h3)
+ (atx_heading
+ (atx_h4_marker)
+ heading_content: (_) @h4)
+ (atx_heading
+ (atx_h5_marker)
+ heading_content: (_) @h5)
+ (atx_heading
+ (atx_h6_marker)
+ heading_content: (_) @h6)
+ ]],
+}
+
+local function hash_tick(bufnr)
+ return tostring(vim.b[bufnr].changedtick)
+end
+
+---@class TS.Heading
+---@field bufnr integer
+---@field lnum integer
+---@field text string
+---@field level integer
+
+--- Extract headings from buffer
+--- @param bufnr integer buffer to extract headings from
+--- @return TS.Heading[]
+local get_headings = vim.func._memoize(hash_tick, function(bufnr)
+ local lang = ts.language.get_lang(vim.bo[bufnr].filetype)
+ if not lang then
+ return {}
+ end
+ local parser = assert(ts.get_parser(bufnr, lang, { error = false }))
+ local query = ts.query.parse(lang, heading_queries[lang])
+ local root = parser:parse()[1]:root()
+ local headings = {}
+ for id, node, _, _ in query:iter_captures(root, bufnr) do
+ local text = ts.get_node_text(node, bufnr)
+ local row, col = node:start()
+ --- why can't you just be normal?!
+ local skip ---@type boolean|integer
+ if lang == 'vimdoc' then
+ -- only column_headings at col 1 are headings, otherwise it's code examples
+ skip = (id == 4 and col > 0)
+ -- ignore tabular material
+ or (id == 4 and (text:find('\t') or text:find(' ')))
+ -- ignore tag-only headings
+ or (node:child_count() == 1 and node:child(0):type() == 'tag')
+ end
+ if not skip then
+ table.insert(headings, {
+ bufnr = bufnr,
+ lnum = row + 1,
+ text = text,
+ level = id,
+ })
+ end
+ end
+ return headings
+end)
+
+--- Show a table of contents for the help buffer in a loclist
+function M.show_toc()
+ local bufnr = api.nvim_get_current_buf()
+ local headings = get_headings(bufnr)
+ if #headings == 0 then
+ return
+ end
+ -- add indentation for nicer list formatting
+ for _, heading in pairs(headings) do
+ if heading.level > 2 then
+ heading.text = '  ' .. heading.text
+ end
+ if heading.level > 4 then
+ heading.text = '  ' .. heading.text
+ end
+ end
+ vim.fn.setloclist(0, headings, ' ')
+ vim.fn.setloclist(0, {}, 'a', { title = 'Help TOC' })
+ vim.cmd.lopen()
+end
+
+--- Jump to section
+--- @param opts table jump options
+--- - count integer direction to jump (>0 forward, <0 backward)
+--- - level integer only consider headings up to level
+--- todo(clason): support count
+function M.jump(opts)
+ local bufnr = api.nvim_get_current_buf()
+ local headings = get_headings(bufnr)
+ if #headings == 0 then
+ return
+ end
+
+ local winid = api.nvim_get_current_win()
+ local curpos = vim.fn.getcurpos(winid)[2] --[[@as integer]]
+ local maxlevel = opts.level or 6
+
+ if opts.count > 0 then
+ for _, heading in ipairs(headings) do
+ if heading.lnum > curpos and heading.level <= maxlevel then
+ api.nvim_win_set_cursor(winid, { heading.lnum, 0 })
+ return
+ end
+ end
+ elseif opts.count < 0 then
+ for i = #headings, 1, -1 do
+ if headings[i].lnum < curpos and headings[i].level <= maxlevel then
+ api.nvim_win_set_cursor(winid, { headings[i].lnum, 0 })
+ return
+ end
+ end
+ end
+end
+
+return M
diff --git a/runtime/lua/vim/treesitter/_meta/tsnode.lua b/runtime/lua/vim/treesitter/_meta/tsnode.lua
index 552905c3f0..2f9d7f214a 100644
--- a/runtime/lua/vim/treesitter/_meta/tsnode.lua
+++ b/runtime/lua/vim/treesitter/_meta/tsnode.lua
@@ -43,7 +43,7 @@ function TSNode:prev_named_sibling() end
--- @return fun(): TSNode, string
function TSNode:iter_children() end
---- Returns a table of the nodes corresponding to the {name} field.
+--- Returns a list of all the node's children that have the given field name.
--- @param name string
--- @return TSNode[]
function TSNode:field(name) end
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 6dd47811bd..475a1f0aa5 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -232,7 +232,12 @@ end
---@return vim.treesitter.highlighter.Query
function TSHighlighter:get_query(lang)
if not self._queries[lang] then
- self._queries[lang] = TSHighlighterQuery.new(lang)
+ local success, result = pcall(TSHighlighterQuery.new, lang)
+ if not success then
+ self:destroy()
+ error(result)
+ end
+ self._queries[lang] = result
end
return self._queries[lang]
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 16d19bfc5a..38d309a102 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -5,6 +5,7 @@ local M = {}
---@type table<string,string>
local ft_to_lang = {
help = 'vimdoc',
+ checkhealth = 'vimdoc',
}
--- Returns the filetypes for which a parser named {lang} is used.
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index d8db489d54..f2e745ec65 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -46,6 +46,9 @@ local Range = require('vim.treesitter._range')
local default_parse_timeout_ms = 3
+---@type Range2
+local entire_document_range = { 0, math.huge }
+
---@alias TSCallbackName
---| 'changedtree'
---| 'bytes'
@@ -77,7 +80,7 @@ local TSCallbackNames = {
---@field package _callbacks_rec table<TSCallbackName,function[]> Callback handlers (recursive)
---@field private _children table<string,vim.treesitter.LanguageTree> Injected languages
---@field private _injection_query vim.treesitter.Query Queries defining injected languages
----@field private _injections_processed boolean
+---@field private _processed_injection_range Range? Range for which injections have been processed
---@field private _opts table Options
---@field private _parser TSParser Parser for language
---Table of regions for which the tree is currently running an async parse
@@ -95,6 +98,7 @@ local TSCallbackNames = {
---@field private _trees table<integer, TSTree> Reference to parsed tree (one for each language).
---Each key is the index of region, which is synced with _regions and _valid.
---@field private _valid_regions table<integer,true> Set of valid region IDs.
+---@field private _num_valid_regions integer Number of valid regions
---@field private _is_entirely_valid boolean Whether the entire tree (excluding children) is valid.
---@field private _logger? fun(logtype: string, msg: string)
---@field private _logfile? file*
@@ -136,8 +140,9 @@ function LanguageTree.new(source, lang, opts)
_opts = opts,
_injection_query = injections[lang] and query.parse(lang, injections[lang])
or query.get(lang, 'injections'),
- _injections_processed = false,
+ _processed_injection_range = nil,
_valid_regions = {},
+ _num_valid_regions = 0,
_num_regions = 1,
_is_entirely_valid = false,
_parser = vim._create_ts_parser(lang),
@@ -246,6 +251,7 @@ end
---@param reload boolean|nil
function LanguageTree:invalidate(reload)
self._valid_regions = {}
+ self._num_valid_regions = 0
self._is_entirely_valid = false
self._parser:reset()
@@ -331,7 +337,10 @@ function LanguageTree:is_valid(exclude_children, range)
end
if not exclude_children then
- if not self._injections_processed then
+ if
+ not self._processed_injection_range
+ or not Range.contains(self._processed_injection_range, range or entire_document_range)
+ then
return false
end
@@ -363,7 +372,6 @@ end
--- @return Range6[] changes
--- @return integer no_regions_parsed
--- @return number total_parse_time
---- @return boolean finished whether async parsing still needs time
function LanguageTree:_parse_regions(range, thread_state)
local changes = {}
local no_regions_parsed = 0
@@ -388,12 +396,14 @@ function LanguageTree:_parse_regions(range, thread_state)
if tree then
break
end
- coroutine.yield(changes, no_regions_parsed, total_parse_time, false)
+ coroutine.yield(self._trees, false)
parse_time, tree, tree_changes =
tcall(self._parser.parse, self._parser, self._trees[i], self._source, true)
end
+ self:_subtract_time(thread_state, parse_time)
+
self:_do_callback('changedtree', tree_changes, tree)
self._trees[i] = tree
vim.list_extend(changes, tree_changes)
@@ -401,24 +411,22 @@ function LanguageTree:_parse_regions(range, thread_state)
total_parse_time = total_parse_time + parse_time
no_regions_parsed = no_regions_parsed + 1
self._valid_regions[i] = true
+ self._num_valid_regions = self._num_valid_regions + 1
- -- _valid_regions can have holes, but that is okay because this equality is only true when it
- -- has no holes (meaning all regions are valid)
- if #self._valid_regions == self._num_regions then
+ if self._num_valid_regions == self._num_regions then
self._is_entirely_valid = true
end
end
end
- return changes, no_regions_parsed, total_parse_time, true
+ return changes, no_regions_parsed, total_parse_time
end
--- @private
---- @return number
-function LanguageTree:_add_injections()
+--- @param injections_by_lang table<string, Range6[][]>
+function LanguageTree:_add_injections(injections_by_lang)
local seen_langs = {} ---@type table<string,boolean>
- local query_time, injections_by_lang = tcall(self._get_injections, self)
for lang, injection_regions in pairs(injections_by_lang) do
local has_lang = pcall(language.add, lang)
@@ -442,8 +450,6 @@ function LanguageTree:_add_injections()
self:remove_child(lang)
end
end
-
- return query_time
end
--- @param range boolean|Range?
@@ -567,6 +573,15 @@ function LanguageTree:parse(range, on_parse)
return trees
end
+---@param thread_state ParserThreadState
+---@param time integer
+function LanguageTree:_subtract_time(thread_state, time)
+ thread_state.timeout = thread_state.timeout and math.max(thread_state.timeout - time, 0)
+ if thread_state.timeout == 0 then
+ coroutine.yield(self._trees, false)
+ end
+end
+
--- @private
--- @param range boolean|Range|nil
--- @param thread_state ParserThreadState
@@ -587,28 +602,27 @@ function LanguageTree:_parse(range, thread_state)
-- At least 1 region is invalid
if not self:is_valid(true, type(range) == 'table' and range or nil) then
- ---@type fun(self: vim.treesitter.LanguageTree, range: boolean|Range?, thread_state: ParserThreadState): Range6[], integer, number, boolean
- local parse_regions = coroutine.wrap(self._parse_regions)
- while true do
- local is_finished
- changes, no_regions_parsed, total_parse_time, is_finished =
- parse_regions(self, range, thread_state)
- thread_state.timeout = thread_state.timeout
- and math.max(thread_state.timeout - total_parse_time, 0)
- if is_finished then
- break
- end
- coroutine.yield(self._trees, false)
- end
+ changes, no_regions_parsed, total_parse_time = self:_parse_regions(range, thread_state)
+
-- Need to run injections when we parsed something
if no_regions_parsed > 0 then
- self._injections_processed = false
+ self._processed_injection_range = nil
end
end
- if not self._injections_processed and range then
- query_time = self:_add_injections()
- self._injections_processed = true
+ if
+ range
+ and not (
+ self._processed_injection_range
+ and Range.contains(
+ self._processed_injection_range,
+ range ~= true and range or entire_document_range
+ )
+ )
+ then
+ local injections_by_lang = self:_get_injections(range, thread_state)
+ local time = tcall(self._add_injections, self, injections_by_lang)
+ self:_subtract_time(thread_state, time)
end
self:_log({
@@ -620,21 +634,7 @@ function LanguageTree:_parse(range, thread_state)
})
for _, child in pairs(self._children) do
- if thread_state.timeout == 0 then
- coroutine.yield(self._trees, false)
- end
-
- ---@type fun(): table<integer, TSTree>, boolean
- local parse = coroutine.wrap(child._parse)
-
- while true do
- local ctime, _, child_finished = tcall(parse, child, range, thread_state)
- if child_finished then
- thread_state.timeout = thread_state.timeout and math.max(thread_state.timeout - ctime, 0)
- break
- end
- coroutine.yield(self._trees, child_finished)
- end
+ child:_parse(range, thread_state)
end
return self._trees, true
@@ -745,6 +745,7 @@ function LanguageTree:_iter_regions(fn)
-- just by checking the length of _valid_regions.
self._valid_regions[i] = fn(i, region) and true or nil
if not self._valid_regions[i] then
+ self._num_valid_regions = self._num_valid_regions - 1
self:_log(function()
return 'invalidating region', i, region_tostr(region)
end)
@@ -983,18 +984,29 @@ end
--- TODO: Allow for an offset predicate to tailor the injection range
--- instead of using the entire nodes range.
--- @private
+--- @param range Range|true
+--- @param thread_state ParserThreadState
--- @return table<string, Range6[][]>
-function LanguageTree:_get_injections()
+function LanguageTree:_get_injections(range, thread_state)
if not self._injection_query or #self._injection_query.captures == 0 then
+ self._processed_injection_range = entire_document_range
return {}
end
---@type table<integer,vim.treesitter.languagetree.Injection>
local injections = {}
+ local start = vim.uv.hrtime()
+
+ local full_scan = range == true or self._injection_query.has_combined_injections
for index, tree in pairs(self._trees) do
local root_node = tree:root()
- local start_line, _, end_line, _ = root_node:range()
+ local start_line, end_line ---@type integer, integer
+ if full_scan then
+ start_line, _, end_line = root_node:range()
+ else
+ start_line, _, end_line = Range.unpack4(range --[[@as Range]])
+ end
for pattern, match, metadata in
self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1)
@@ -1005,6 +1017,11 @@ function LanguageTree:_get_injections()
else
self:_log('match from injection query failed for pattern', pattern)
end
+
+ -- Check the current function duration against the timeout, if it exists.
+ local current_time = vim.uv.hrtime()
+ self:_subtract_time(thread_state, (current_time - start) / 1000000)
+ start = current_time
end
end
@@ -1031,6 +1048,12 @@ function LanguageTree:_get_injections()
end
end
+ if full_scan then
+ self._processed_injection_range = entire_document_range
+ else
+ self._processed_injection_range = range --[[@as Range]]
+ end
+
return result
end
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 10fb82e533..d26aa8e604 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -30,9 +30,11 @@ end
--- Splits the query patterns into predicates and directives.
---@param patterns table<integer, (integer|string)[][]>
---@return table<integer, vim.treesitter.query.ProcessedPattern>
+---@return boolean
local function process_patterns(patterns)
---@type table<integer, vim.treesitter.query.ProcessedPattern>
local processed_patterns = {}
+ local has_combined = false
for k, pattern_list in pairs(patterns) do
---@type vim.treesitter.query.ProcessedPredicate[]
@@ -47,6 +49,9 @@ local function process_patterns(patterns)
if is_directive(pred_name) then
table.insert(directives, pattern)
+ if vim.deep_equal(pattern, { 'set!', 'injection.combined' }) then
+ has_combined = true
+ end
else
local should_match = true
if pred_name:match('^not%-') then
@@ -60,7 +65,7 @@ local function process_patterns(patterns)
processed_patterns[k] = { predicates = predicates, directives = directives }
end
- return processed_patterns
+ return processed_patterns, has_combined
end
---@nodoc
@@ -71,6 +76,7 @@ end
---@field captures string[] list of (unique) capture names defined in query
---@field info vim.treesitter.QueryInfo query context (e.g. captures, predicates, directives)
---@field query TSQuery userdata query object
+---@field has_combined_injections boolean whether the query contains combined injections
---@field private _processed_patterns table<integer, vim.treesitter.query.ProcessedPattern>
local Query = {}
Query.__index = Query
@@ -90,7 +96,7 @@ function Query.new(lang, ts_query)
patterns = query_info.patterns,
}
self.captures = self.info.captures
- self._processed_patterns = process_patterns(self.info.patterns)
+ self._processed_patterns, self.has_combined_injections = process_patterns(self.info.patterns)
return self
end
diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua
deleted file mode 100644
index a494d311b1..0000000000
--- a/runtime/lua/vim/vimhelp.lua
+++ /dev/null
@@ -1,71 +0,0 @@
--- Extra functionality for displaying Vim help.
-
-local M = {}
-
---- Apply current colorscheme to lists of default highlight groups
----
---- Note: {patterns} is assumed to be sorted by occurrence in the file.
---- @param patterns {start:string,stop:string,match:string}[]
-function M.highlight_groups(patterns)
- local ns = vim.api.nvim_create_namespace('nvim.vimhelp')
- vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
-
- local save_cursor = vim.fn.getcurpos()
-
- for _, pat in pairs(patterns) do
- local start_lnum = vim.fn.search(pat.start, 'c')
- local end_lnum = vim.fn.search(pat.stop)
- if start_lnum == 0 or end_lnum == 0 then
- break
- end
-
- for lnum = start_lnum, end_lnum do
- local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match(pat.match)
- if vim.fn.hlexists(word) ~= 0 then
- vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word })
- end
- end
- end
-
- vim.fn.setpos('.', save_cursor)
-end
-
---- Show a table of contents for the help buffer in a loclist
-function M.show_toc()
- local bufnr = vim.api.nvim_get_current_buf()
- local parser = assert(vim.treesitter.get_parser(bufnr, 'vimdoc', { error = false }))
- local query = vim.treesitter.query.parse(
- parser:lang(),
- [[
- (h1 (heading) @h1)
- (h2 (heading) @h2)
- (h3 (heading) @h3)
- (column_heading (heading) @h4)
- ]]
- )
- local root = parser:parse()[1]:root()
- local headings = {}
- for id, node, _, _ in query:iter_captures(root, bufnr) do
- local text = vim.treesitter.get_node_text(node, bufnr)
- local capture = query.captures[id]
- local row, col = node:start()
- -- only column_headings at col 1 are headings, otherwise it's code examples
- local is_code = (capture == 'h4' and col > 0)
- -- ignore tabular material
- local is_table = (capture == 'h4' and (text:find('\t') or text:find(' ')))
- -- ignore tag-only headings
- local is_tag = node:child_count() == 1 and node:child(0):type() == 'tag'
- if not (is_code or is_table or is_tag) then
- table.insert(headings, {
- bufnr = bufnr,
- lnum = row + 1,
- text = (capture == 'h3' or capture == 'h4') and '  ' .. text or text,
- })
- end
- end
- vim.fn.setloclist(0, headings, ' ')
- vim.fn.setloclist(0, {}, 'a', { title = 'Help TOC' })
- vim.cmd.lopen()
-end
-
-return M
diff --git a/runtime/pack/dist/opt/netrw/doc/netrw.txt b/runtime/pack/dist/opt/netrw/doc/netrw.txt
index 9fc7b42bb7..b1f9d3a927 100644
--- a/runtime/pack/dist/opt/netrw/doc/netrw.txt
+++ b/runtime/pack/dist/opt/netrw/doc/netrw.txt
@@ -58,7 +58,6 @@ Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright*
Changing local-only File Permission.................|netrw-gp|
Changing To A Predecessor Directory.................|netrw-u|
Changing To A Successor Directory...................|netrw-U|
- Customizing Browsing With A Special Handler.........|netrw-x|
Deleting Bookmarks..................................|netrw-mB|
Deleting Files Or Directories.......................|netrw-D|
Directory Exploring Commands........................|netrw-explore|
@@ -401,9 +400,6 @@ settings are described below, in |netrw-browser-options|, and in
*g:netrw_menu* =0 disable netrw's menu
=1 (default) netrw's menu enabled
- *g:netrw_nogx* if this variable exists, then the "gx" map will not
- be available (see |netrw-gx|)
-
*g:netrw_uid* (ftp) user-id, retained on a per-vim-session basis
*s:netrw_passwd* (ftp) password, retained on a per-vim-session basis
@@ -1108,7 +1104,7 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2
U Change to subsequently-visited directory |netrw-U|
v Enter the file/directory under the cursor in a new |netrw-v|
browser window. A vertical split is used.
- x View file with an associated program |netrw-x|
+ x View file with an associated program
X Execute filename under cursor via |system()| |netrw-X|
% Open a new file in netrw's current directory |netrw-%|
@@ -1461,106 +1457,6 @@ With either form of the command, netrw will first ask for confirmation
that the removal is in fact what you want to do. If netrw doesn't have
permission to remove a file, it will issue an error message.
-CUSTOMIZING BROWSING WITH A SPECIAL HANDLER *netrw-x* *netrw-handler* {{{2
-
-Certain files, such as html, gif, jpeg, (word/office) doc, etc, files, are
-best seen with a special handler (ie. a tool provided with your computer's
-operating system). Netrw allows one to invoke such special handlers by:
-
- * hitting gx with the cursor atop the file path or alternatively x
- in a netrw buffer; the former can be disabled by defining the
- |g:netrw_nogx| variable
- * when in command line, typing :Open <path>, see |:Open| below.
-
-One may also use visual mode (see |visual-start|) to select the text that the
-special handler will use. Normally gx checks for a close-by URL or file name
-to pick up the text under the cursor; one may change what |expand()| uses via the
-|g:netrw_gx| variable (options include "<cword>", "<cWORD>"). Note that
-expand("<cfile>") depends on the |'isfname'| setting. Alternatively, one may
-select the text to be used by gx by making a visual selection (see
-|visual-block|) and then pressing gx.
-
-The selection function can be adapted for each filetype by adding a function
-`Netrw_get_URL_<filetype>`, where <filetype> is given by the 'filetype'.
-The function should return the URL or file name to be used by gx, and will
-fall back to the default behavior if it returns an empty string.
-For example, special handlers for links Markdown and HTML are
-
-" make gx work on concealed links regardless of exact cursor position: >
-
- function Netrw_get_URL_markdown()
- " markdown URL such as [link text](http://ya.ru 'yandex search')
- try
- let save_view = winsaveview()
- if searchpair('\[.\{-}\](', '', ')\zs', 'cbW', '', line('.')) > 0
- return matchstr(getline('.')[col('.')-1:],
- \ '\[.\{-}\](\zs' .. g:netrw_regex_url .. '\ze\(\s\+.\{-}\)\?)')
- endif
- return ''
- finally
- call winrestview(save_view)
- endtry
- endfunction
-
- function Netrw_get_URL_html()
- " HTML URL such as <a href='http://www.python.org'>Python is here</a>
- " <a href="http://www.python.org"/>
- try
- let save_view = winsaveview()
- if searchpair('<a\s\+href=', '', '\%(</a>\|/>\)\zs', 'cbW', '', line('.')) > 0
- return matchstr(getline('.')[col('.') - 1 : ],
- \ 'href=["'.."'"..']\?\zs\S\{-}\ze["'.."'"..']\?/\?>')
- endif
- return ''
- finally
- call winrestview(save_view)
- endtry
- endfunction
-<
-Other than a file path, the text under the cursor may be a URL. Netrw uses
-by default the following regular expression to determine if the text under the
-cursor is a URL:
->
- :let g:netrw_regex_url = '\%(\%(http\|ftp\|irc\)s\?\|file\)://\S\{-}'
-<
-Associated setting variables:
- |g:netrw_gx| control how gx picks up the text under the cursor
- |g:netrw_nogx| prevent gx map while editing
- |g:netrw_suppress_gx_mesg| controls gx's suppression of browser messages
-
-OPENING FILES AND LAUNCHING APPS *netrw-gx* *:Open* *:Launch* {{{2
-
-Netrw determines which special handler by the following method:
-
- * if |g:netrw_browsex_viewer| exists, then it will be used to attempt to
- view files.
- If the viewer you wish to use does not support handling of a remote URL
- directory, set |g:netrw_browsex_support_remote| to 0.
- * otherwise:
-
- * for Windows : explorer.exe is used
- * for Mac OS X : open is used.
- * for Linux : xdg-open is used.
-
-To open a path (or URL) <path> by the appropriate handler, type >
-
- :Open <path>
-<
-No escaping, neither for the shell nor for Vim's command-line, is needed.
-
-To launch a specific application <app> <args>, often <args> being <path> >
-
- :Launch <app> <args>.
-
-Since <args> can be arbitrarily complex, in particular contain many file
-paths, the escaping is left to the user.
-
-If you disabled the netrw plugin by setting g:loaded_netrwPlugin (see
-|netrw-noload|), then you can use >
-
- :call netrw#Launch('<app> <args>')
- :call netrw#Open('<path>')
-<
*netrw-curdir*
DELETING BOOKMARKS *netrw-mB* {{{2
@@ -2570,14 +2466,6 @@ your browsing preferences. (see also: |netrw-settings|)
|netrw-C| |netrw-cr|
|netrw-ctrl-r|
- *g:netrw_browsex_viewer* specify user's preference for a viewer: >
- "kfmclient exec"
- "gnome-open"
-<
- *g:netrw_browsex_support_remote*
- specify if the specified viewer supports a
- remote URL. (see |netrw-handler|).
-
*g:netrw_chgperm* Unix/Linux: "chmod PERM FILENAME"
Windows: "cacls FILENAME /e /p PERM"
Used to change access permission for a file.
@@ -2600,12 +2488,11 @@ your browsing preferences. (see also: |netrw-settings|)
*g:Netrw_corehandler* Allows one to specify something additional
to do when handling <core> files via netrw's
- browser's "x" command (see |netrw-x|). If
- present, g:Netrw_corehandler specifies
- either one or more function references
- (see |Funcref|). (the capital g:Netrw...
- is required its holding a function reference)
-
+ browser's "x" command. If present,
+ g:Netrw_corehandler specifies either one or
+ more function references (see |Funcref|).
+ (the capital g:Netrw... is required its
+ holding a function reference)
*g:netrw_ctags* ="ctags"
The default external program used to create
@@ -2754,11 +2641,6 @@ your browsing preferences. (see also: |netrw-settings|)
These characters in directory names are
escaped before applying glob()
- *g:netrw_gx* ="<cfile>"
- This option controls how gx (|netrw-gx|) picks
- up the text under the cursor. See |expand()|
- for possibilities.
-
*g:netrw_hide* Controlled by the "a" map (see |netrw-a|)
=0 : show all
=1 : show not-hidden files
diff --git a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
index 8d10c00153..388a7f2ba3 100644
--- a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
+++ b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
@@ -20,12 +20,6 @@ let g:loaded_netrwPlugin = "v175"
let s:keepcpo = &cpo
set cpo&vim
-" Commands Launch/URL: {{{
-
-command -complete=shellcmd -nargs=1 Launch call netrw#Launch(trim(<q-args>))
-command -complete=file -nargs=1 Open call netrw#Open(trim(<q-args>))
-
-" }}}
" Local Browsing Autocmds: {{{
augroup FileExplorer
@@ -85,21 +79,6 @@ command! -bang NetrwClean call netrw#Clean(<bang>0)
" }}}
" Maps: {{{
-if !exists("g:netrw_nogx")
- if maparg('gx','n') == ""
- if !hasmapto('<Plug>NetrwBrowseX')
- nmap <unique> gx <Plug>NetrwBrowseX
- endif
- nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(netrw#GX(),netrw#CheckIfRemote(netrw#GX()))<cr>
- endif
- if maparg('gx','x') == ""
- if !hasmapto('<Plug>NetrwBrowseXVis')
- xmap <unique> gx <Plug>NetrwBrowseXVis
- endif
- xno <silent> <Plug>NetrwBrowseXVis :<c-u>call netrw#BrowseXVis()<cr>
- endif
-endif
-
if exists("g:netrw_usetab") && g:netrw_usetab
if maparg('<c-tab>','n') == ""
nmap <unique> <c-tab> <Plug>NetrwShrink
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 3d62f883b2..9dfccf0bc7 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -192,7 +192,6 @@ syn match vimNumber '\<0o\=\o\+' skipwhite nextgroup=vimGlobal,vimSubst1,@vimC
syn match vimNumber '\<0x\x\+' skipwhite nextgroup=vimGlobal,vimSubst1,@vimComment,vimSubscript
syn match vimNumber '\<0z\>' skipwhite nextgroup=vimGlobal,vimSubst1,@vimComment
syn match vimNumber '\<0z\%(\x\x\)\+\%(\.\%(\x\x\)\+\)*' skipwhite nextgroup=vimGlobal,vimSubst1,@vimComment,vimSubscript
-syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSubst1,@vimComment
syn case match
" All vimCommands are contained by vimIsCommand. {{{2
@@ -353,7 +352,7 @@ syn match vim9LambdaOperatorComment contained "#.*" skipwhite skipempty nextgrou
syn cluster vimFuncList contains=vimFuncBang,vimFunctionError,vimFuncKey,vimFuncScope,vimFuncSID,Tag
syn cluster vimDefList contains=vimFuncBang,vimFunctionError,vimDefKey,vimFuncScope,vimFuncSID,Tag
-syn cluster vimFuncBodyCommon contains=@vimCmdList,vimCmplxRepeat,vimContinue,vimCtrlChar,vimDef,vimFBVar,vimFunc,vimFunction,vimLetHereDoc,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegister,vimSpecFile,vimString,vimSubst,vimFuncFold,vimDefFold
+syn cluster vimFuncBodyCommon contains=@vimCmdList,vimCmplxRepeat,vimContinue,vimCtrlChar,vimDef,vimFBVar,vimFunc,vimFunction,vimLetHereDoc,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegister,vimSpecFile,vimString,vimSubst,vimFuncFold,vimDefFold
syn cluster vimFuncBodyList contains=@vimFuncBodyCommon,vimComment,vimLineComment,vimInsert,vimConst,vimLet,vimSearch
syn cluster vimDefBodyList contains=@vimFuncBodyCommon,vim9Comment,vim9LineComment,vim9Block,vim9Const,vim9Final,vim9Var,vim9Null,vim9Boolean,vim9For,vim9LhsVariable,vim9LhsVariableList,vim9LhsRegister,vim9Search,@vimSpecialVar
@@ -625,7 +624,10 @@ syn match vimCommentError contained +".*+
syn match vimEnvvar "\$\I\i*"
syn match vimEnvvar "\${\I\i*}"
-" In-String Specials: {{{2
+" Strings {{{2
+" =======
+
+" In-String Specials:
" Try to catch strings, if nothing else matches (therefore it must precede the others!)
" vimEscapeBrace handles ["] []"] (ie. "s don't terminate string inside [])
syn region vimEscapeBrace oneline contained transparent start="[^\\]\(\\\\\)*\[\zs\^\=\]\=" skip="\\\\\|\\\]" end="]"me=e-1
@@ -638,8 +640,6 @@ syn cluster vimStringGroup contains=vimEscape,vimEscapeBrace,vimPatSep,vimNotPat
syn region vimString oneline keepend matchgroup=vimString start=+[^a-zA-Z>\\@]"+lc=1 skip=+\\\\\|\\"+ matchgroup=vimStringEnd end=+"+ nextgroup=vimSubscript contains=@vimStringGroup extend
syn region vimString oneline matchgroup=vimString start=+[^a-zA-Z>\\@]'+lc=1 end=+'+ nextgroup=vimSubscript contains=vimQuoteEscape extend
"syn region vimString oneline start="\s/\s*\A"lc=1 skip="\\\\\|\\+" end="/" contains=@vimStringGroup " see tst45.vim
-syn match vimString contained +"[^"]*\\$+ skipnl nextgroup=vimStringCont
-syn match vimStringCont contained +\(\\\\\|.\)\{-}[^\\]"+
syn match vimEscape contained "\\."
" syn match vimEscape contained +\\[befnrt\"]+
@@ -680,9 +680,6 @@ syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
syn match vimSubstDelim contained "\\"
syn match vimSubstPat contained "\\\ze[/?&]" contains=vimSubstDelim nextgroup=vimSubstRep4
-" 'String': {{{2
-syn match vimString "[^(,]'[^']\{-}\zs'"
-
" Marks, Registers, Addresses, Filters: {{{2
syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
syn match vimMark "'[[\]{}()<>]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
@@ -876,22 +873,22 @@ syn match vimMenutranslateComment +".*+ contained containedin=vimMenutranslate
" Angle-Bracket Notation: (tnx to Michael Geddes) {{{2
" ======================
syn case ignore
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}x\=\%(f\d\{1,2}\|[^ \t:]\|space\|bar\|bslash\|nl\|newline\|lf\|linefeed\|cr\|retu\%[rn]\|enter\|k\=del\%[ete]\|bs\|backspace\|tab\|esc\|csi\|right\|paste\%(start\|end\)\|left\|help\|undo\|k\=insert\|ins\|mouse\|[kz]\=home\|[kz]\=end\|kplus\|kminus\|kdivide\|kmultiply\|kenter\|kpoint\|space\|k\=\%(page\)\=\%(\|down\|up\|k\d\>\)\)>" contains=vimBracket
-
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(net\|dec\|jsb\|pterm\|urxvt\|sgr\)mouse>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(left\|middle\|right\)\%(mouse\|drag\|release\)>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}left\%(mouse\|release\)nm>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}x[12]\%(mouse\|drag\|release\)>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}sgrmouserelease>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}mouse\%(up\|down\|move\)>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}scrollwheel\%(up\|down\|right\|left\)>" contains=vimBracket
-
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%(sid\|nop\|nul\|lt\|drop\)>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%(snr\|plug\|cursorhold\|ignore\|cmd\|scriptcmd\|focus\%(gained\|lost\)\)>" contains=vimBracket
-syn match vimNotation '\%(\\\|<lt>\)\=<C-R>[0-9a-z"%#:.\-=]'he=e-1 contains=vimBracket
-syn match vimNotation '\%#=1\%(\\\|<lt>\)\=<\%(q-\)\=\%(line[12]\|count\|bang\|reg\|args\|mods\|f-args\|f-mods\|lt\)>' contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([cas]file\|abuf\|amatch\|cexpr\|cword\|cWORD\|client\|stack\|script\|sf\=lnum\)>" contains=vimBracket
-syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}char-\%(\d\+\|0\o\+\|0x\x\+\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}x\=\%(f\d\{1,2}\|[^ \t:]\|space\|bar\|bslash\|nl\|newline\|lf\|linefeed\|cr\|retu\%[rn]\|enter\|k\=del\%[ete]\|bs\|backspace\|tab\|esc\|csi\|right\|paste\%(start\|end\)\|left\|help\|undo\|k\=insert\|ins\|mouse\|[kz]\=home\|[kz]\=end\|kplus\|kminus\|kdivide\|kmultiply\|kenter\|kpoint\|space\|k\=\%(page\)\=\%(\|down\|up\|k\d\>\)\)>" contains=vimBracket
+
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(net\|dec\|jsb\|pterm\|urxvt\|sgr\)mouse>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(left\|middle\|right\)\%(mouse\|drag\|release\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}left\%(mouse\|release\)nm>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}x[12]\%(mouse\|drag\|release\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}sgrmouserelease>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}mouse\%(up\|down\|move\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}scrollwheel\%(up\|down\|right\|left\)>" contains=vimBracket
+
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%(sid\|nop\|nul\|lt\|drop\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%(snr\|plug\|cursorhold\|ignore\|cmd\|scriptcmd\|focus\%(gained\|lost\)\)>" contains=vimBracket
+syn match vimNotation contained '\%(\\\|<lt>\)\=<C-R>[0-9a-z"%#:.\-=]'he=e-1 contains=vimBracket
+syn match vimNotation contained '\%#=1\%(\\\|<lt>\)\=<\%(q-\)\=\%(line[12]\|count\|bang\|reg\|args\|mods\|f-args\|f-mods\|lt\)>' contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([cas]file\|abuf\|amatch\|cexpr\|cword\|cWORD\|client\|stack\|script\|sf\=lnum\)>" contains=vimBracket
+syn match vimNotation contained "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}char-\%(\d\+\|0\o\+\|0x\x\+\)>" contains=vimBracket
syn match vimBracket contained "[\\<>]"
syn case match
@@ -917,7 +914,7 @@ if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimfunctionerror")
syn match vimBufnrWarn /\<bufnr\s*(\s*["']\.['"]\s*)/
endif
-syn match vimNotFunc "\<if\>\|\<el\%[seif]\>\|\<retu\%[rn]\>\|\<while\>" skipwhite nextgroup=@vimExprList,vimNotation
+syn match vimNotFunc "\%#=1\<\%(if\|el\%[seif]\|retu\%[rn]\|while\)\>" skipwhite nextgroup=@vimExprList,vimNotation
" Match: {{{2
" =====