aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/doc/builtin.txt15
-rw-r--r--runtime/doc/eval.txt3
-rw-r--r--runtime/doc/gui.txt186
-rw-r--r--runtime/doc/health.txt11
-rw-r--r--runtime/doc/index.txt15
-rw-r--r--runtime/doc/lsp.txt2
-rw-r--r--runtime/doc/lua.txt20
-rw-r--r--runtime/doc/news.txt44
-rw-r--r--runtime/doc/starting.txt19
-rw-r--r--runtime/doc/treesitter.txt10
-rw-r--r--runtime/doc/tui.txt188
-rw-r--r--runtime/doc/usr_41.txt3
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/doc/vvars.txt15
-rw-r--r--runtime/doc/windows.txt4
-rw-r--r--runtime/ftplugin/shaderslang.vim54
-rw-r--r--runtime/ftplugin/tiasm.vim18
-rw-r--r--runtime/ftplugin/vim.vim8
-rw-r--r--runtime/lua/coxpcall.lua4
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua6
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua14
-rw-r--r--runtime/lua/vim/_meta/vvars.lua12
-rw-r--r--runtime/lua/vim/_options.lua6
-rw-r--r--runtime/lua/vim/filetype.lua3
-rw-r--r--runtime/lua/vim/filetype/detect.lua15
-rw-r--r--runtime/lua/vim/fs.lua4
-rw-r--r--runtime/lua/vim/func.lua14
-rw-r--r--runtime/lua/vim/func/_memoize.lua56
-rw-r--r--runtime/lua/vim/health.lua52
-rw-r--r--runtime/lua/vim/lsp/util.lua10
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua34
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua4
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua2
-rw-r--r--runtime/lua/vim/treesitter/query.lua221
-rw-r--r--runtime/pack/dist/opt/matchit/autoload/matchit.vim10
-rw-r--r--runtime/pack/dist/opt/matchit/doc/matchit.txt2
-rw-r--r--runtime/plugin/matchparen.vim4
-rw-r--r--runtime/syntax/java.vim33
-rw-r--r--runtime/syntax/sh.vim3
-rw-r--r--runtime/syntax/shaderslang.vim360
-rw-r--r--runtime/syntax/tiasm.vim102
-rw-r--r--runtime/syntax/vim.vim21
-rw-r--r--runtime/syntax/xf86conf.vim8
-rw-r--r--runtime/syntax/zsh.vim25
44 files changed, 1214 insertions, 428 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index f321c880a4..f466dde861 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -4182,6 +4182,21 @@ getscriptinfo([{opts}]) *getscriptinfo()*
Return: ~
(`vim.fn.getscriptinfo.ret[]`)
+getstacktrace() *getstacktrace()*
+ Returns the current stack trace of Vim scripts.
+ Stack trace is a |List|, of which each item is a |Dictionary|
+ with the following items:
+ funcref The funcref if the stack is at a function,
+ otherwise this item is omitted.
+ event The string of the event description if the
+ stack is at an autocmd event, otherwise this
+ item is omitted.
+ lnum The line number in the script on the stack.
+ filepath The file path of the script on the stack.
+
+ Return: ~
+ (`table[]`)
+
gettabinfo([{tabnr}]) *gettabinfo()*
If {tabnr} is not specified, then information about all the
tab pages is returned as a |List|. Each List item is a
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e0c45503cc..60238bc90d 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2848,7 +2848,8 @@ in the variable |v:exception|: >
: echo "Number thrown. Value is" v:exception
You may also be interested where an exception was thrown. This is stored in
-|v:throwpoint|. Note that "v:exception" and "v:throwpoint" are valid for the
+|v:throwpoint|. And you can obtain the stack trace from |v:stacktrace|.
+Note that "v:exception", "v:stacktrace" and "v:throwpoint" are valid for the
exception most recently caught as long it is not finished.
Example: >
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index eb787af3c9..6fc5b27580 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -68,6 +68,192 @@ Example: this sets "g:gui" to the value of the UI's "rgb" field: >
Obsolete, use ":set lines=11 columns=22".
==============================================================================
+Using the mouse *mouse-using*
+
+ *mouse-mode-table* *mouse-overview*
+Overview of what the mouse buttons do, when 'mousemodel' is "extend":
+
+ *<S-LeftMouse>* *<A-RightMouse>* *<S-RightMouse>* *<RightDrag>*
+ *<RightRelease>* *<LeftDrag>*
+Normal Mode: >
+ event position selection change action
+ cursor window
+ ---------------------------------------------------------------------------
+ <LeftMouse> yes end yes
+ <C-LeftMouse> yes end yes "CTRL-]" (2)
+ <S-LeftMouse> yes no change yes "*" (2)
+ <LeftDrag> yes start or extend (1) no
+ <LeftRelease> yes start or extend (1) no
+ <MiddleMouse> yes if not active no put
+ <MiddleMouse> yes if active no yank and put
+ <RightMouse> yes start or extend yes
+ <A-RightMouse> yes start or extend blockw. yes
+ <S-RightMouse> yes no change yes "#" (2)
+ <C-RightMouse> no no change no "CTRL-T"
+ <RightDrag> yes extend no
+ <RightRelease> yes extend no
+
+Insert or Replace Mode: >
+ event position selection change action
+ cursor window
+ ---------------------------------------------------------------------------
+ <LeftMouse> yes (cannot be active) yes
+ <C-LeftMouse> yes (cannot be active) yes "CTRL-O^]" (2)
+ <S-LeftMouse> yes (cannot be active) yes "CTRL-O*" (2)
+ <LeftDrag> yes start or extend (1) no like CTRL-O (1)
+ <LeftRelease> yes start or extend (1) no like CTRL-O (1)
+ <MiddleMouse> no (cannot be active) no put register
+ <RightMouse> yes start or extend yes like CTRL-O
+ <A-RightMouse> yes start or extend blockw. yes
+ <S-RightMouse> yes (cannot be active) yes "CTRL-O#" (2)
+ <C-RightMouse> no (cannot be active) no "CTRL-O CTRL-T"
+
+In a help window: >
+ event position selection change action
+ cursor window
+ ---------------------------------------------------------------------------
+ <2-LeftMouse> yes (cannot be active) no "^]" (jump to help tag)
+
+When 'mousemodel' is "popup", these are different:
+
+ *<A-LeftMouse>*
+Normal Mode: >
+ event position selection change action
+ cursor window
+ ---------------------------------------------------------------------------
+ <S-LeftMouse> yes start or extend (1) no
+ <A-LeftMouse> yes start/extend blockw no
+ <RightMouse> no popup menu no
+
+Insert or Replace Mode: >
+ event position selection change action
+ cursor window
+ ---------------------------------------------------------------------------
+ <S-LeftMouse> yes start or extend (1) no like CTRL-O (1)
+ <A-LeftMouse> yes start/extend blockw no
+ <RightMouse> no popup menu no
+
+(1) only if mouse pointer moved since press
+(2) only if click is in same buffer
+
+Clicking the left mouse button causes the cursor to be positioned. If the
+click is in another window that window is made the active window. When
+editing the command-line the cursor can only be positioned on the
+command-line. When in Insert mode Vim remains in Insert mode. If 'scrolloff'
+is set, and the cursor is positioned within 'scrolloff' lines from the window
+border, the text is scrolled.
+
+A selection can be started by pressing the left mouse button on the first
+character, moving the mouse to the last character, then releasing the mouse
+button. You will not always see the selection until you release the button,
+only in some versions (GUI, Win32) will the dragging be shown immediately.
+Note that you can make the text scroll by moving the mouse at least one
+character in the first/last line in the window when 'scrolloff' is non-zero.
+
+In Normal, Visual and Select mode clicking the right mouse button causes the
+Visual area to be extended. When 'mousemodel' is "popup", the left button has
+to be used while keeping the shift key pressed. When clicking in a window
+which is editing another buffer, the Visual or Select mode is stopped.
+
+In Normal, Visual and Select mode clicking the right mouse button with the alt
+key pressed causes the Visual area to become blockwise. When 'mousemodel' is
+"popup" the left button has to be used with the alt key. Note that this won't
+work on systems where the window manager consumes the mouse events when the
+alt key is pressed (it may move the window).
+
+ *double-click* *<2-LeftMouse>* *<3-LeftMouse>* *<4-LeftMouse>*
+Double, triple and quadruple clicks are supported. For selecting text, extra
+clicks extend the selection: >
+
+ click select
+ ---------------------------------
+ double word or % match
+ triple line
+ quadruple rectangular block
+
+Exception: In a :help window, double-click jumps to help for the word that is
+clicked on.
+
+Double-click on a word selects that word. 'iskeyword' is used to specify
+which characters are included in a word. Double-click on a character that has
+a match selects until that match (like using "v%"). If the match is an
+#if/#else/#endif block, the selection becomes linewise. The time for
+double-clicking can be set with the 'mousetime' option.
+
+Example: configure double-click to jump to the tag under the cursor: >vim
+ :map <2-LeftMouse> :exe "tag " .. expand("<cword>")<CR>
+
+Dragging the mouse with a double-click (button-down, button-up, button-down
+and then drag) will result in whole words to be selected. This continues
+until the button is released, at which point the selection is per character
+again.
+
+For scrolling with the mouse see |scroll-mouse-wheel|.
+
+In Insert mode, when a selection is started, Vim goes into Normal mode
+temporarily. When Visual or Select mode ends, it returns to Insert mode.
+This is like using CTRL-O in Insert mode. Select mode is used when the
+'selectmode' option contains "mouse".
+
+ *X1Mouse* *X1Drag* *X1Release*
+ *X2Mouse* *X2Drag* *X2Release*
+ *<MiddleRelease>* *<MiddleDrag>*
+Mouse clicks can be mapped using these |keycodes|: >
+ code mouse button normal action
+ ---------------------------------------------------------------------------
+ <LeftMouse> left pressed set cursor position
+ <LeftDrag> left moved while pressed extend selection
+ <LeftRelease> left released set selection end
+ <MiddleMouse> middle pressed paste text at cursor position
+ <MiddleDrag> middle moved while pressed -
+ <MiddleRelease> middle released -
+ <RightMouse> right pressed extend selection
+ <RightDrag> right moved while pressed extend selection
+ <RightRelease> right released set selection end
+ <X1Mouse> X1 button pressed -
+ <X1Drag> X1 moved while pressed -
+ <X1Release> X1 button release -
+ <X2Mouse> X2 button pressed -
+ <X2Drag> X2 moved while pressed -
+ <X2Release> X2 button release -
+
+The X1 and X2 buttons refer to the extra buttons found on some mice (e.g. the
+right thumb).
+
+Examples: >vim
+ :noremap <MiddleMouse> <LeftMouse><MiddleMouse>
+Paste at the position of the middle mouse button click (otherwise the paste
+would be done at the cursor position). >vim
+
+ :noremap <LeftRelease> <LeftRelease>y
+Immediately yank the selection, when using Visual mode.
+
+Note the use of ":noremap" instead of "map" to avoid a recursive mapping.
+>vim
+ :map <X1Mouse> <C-O>
+ :map <X2Mouse> <C-I>
+Map the X1 and X2 buttons to go forwards and backwards in the jump list, see
+|CTRL-O| and |CTRL-I|.
+
+ *mouse-swap-buttons*
+To swap the meaning of the left and right mouse buttons: >vim
+ :noremap <LeftMouse> <RightMouse>
+ :noremap <LeftDrag> <RightDrag>
+ :noremap <LeftRelease> <RightRelease>
+ :noremap <RightMouse> <LeftMouse>
+ :noremap <RightDrag> <LeftDrag>
+ :noremap <RightRelease> <LeftRelease>
+ :noremap g<LeftMouse> <C-RightMouse>
+ :noremap g<RightMouse> <C-LeftMouse>
+ :noremap! <LeftMouse> <RightMouse>
+ :noremap! <LeftDrag> <RightDrag>
+ :noremap! <LeftRelease> <RightRelease>
+ :noremap! <RightMouse> <LeftMouse>
+ :noremap! <RightDrag> <LeftDrag>
+ :noremap! <RightRelease> <LeftRelease>
+<
+
+==============================================================================
Scrollbars *gui-scrollbars*
There are vertical scrollbars and a horizontal scrollbar. You may
diff --git a/runtime/doc/health.txt b/runtime/doc/health.txt
index cb70961b55..bca145bd8e 100644
--- a/runtime/doc/health.txt
+++ b/runtime/doc/health.txt
@@ -21,6 +21,17 @@ To run all healthchecks, use: >vim
<
Plugin authors are encouraged to write new healthchecks. |health-dev|
+ *g:health*
+g:health This global variable controls the behavior and appearance of the
+ `health` floating window. It should be a dictionary containing the
+ following optional keys:
+ - `style`: string? Determines the display style of the `health` window.
+ Set to `'float'` to enable a floating window. Other
+ styles are not currently supported.
+
+ Example: >lua
+ vim.g.health = { style = 'float' }
+
Commands *health-commands*
*:che* *:checkhealth*
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index 0182123a12..0256707420 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1190,7 +1190,7 @@ tag command action ~
|:breakdel| :breakd[el] delete a debugger breakpoint
|:breaklist| :breakl[ist] list debugger breakpoints
|:browse| :bro[wse] use file selection dialog
-|:bufdo| :bufdo execute command in each listed buffer
+|:bufdo| :bufd[o] execute command in each listed buffer
|:buffers| :buffers list all files in the buffer list
|:bunload| :bun[load] unload a specific buffer
|:bwipeout| :bw[ipeout] really delete a buffer
@@ -1206,7 +1206,7 @@ tag command action ~
|:cafter| :caf[ter] go to error after current cursor
|:call| :cal[l] call a function
|:catch| :cat[ch] part of a :try command
-|:cbefore| :cbef[ore] go to error before current cursor
+|:cbefore| :cbe[fore] go to error before current cursor
|:cbelow| :cbel[ow] go to error below current line
|:cbottom| :cbo[ttom] scroll to the bottom of the quickfix window
|:cbuffer| :cb[uffer] parse error messages and jump to first error
@@ -1262,6 +1262,7 @@ tag command action ~
|:delete| :d[elete] delete lines
|:debug| :deb[ug] run a command in debugging mode
|:debuggreedy| :debugg[reedy] read debug mode commands from normal input
+|:defer| :defe[r] call function when current function is done
|:delcommand| :delc[ommand] delete user-defined command
|:delfunction| :delf[unction] delete a user function
|:delmarks| :delm[arks] delete marks
@@ -1271,7 +1272,7 @@ tag command action ~
|:diffpatch| :diffp[atch] apply a patch and show differences
|:diffput| :diffpu[t] remove differences in other buffer
|:diffsplit| :diffs[plit] show differences with another file
-|:diffthis| :diffthis make current window a diff window
+|:diffthis| :difft[his] make current window a diff window
|:digraphs| :dig[raphs] show or enter digraphs
|:display| :di[splay] display registers
|:djump| :dj[ump] jump to #define
@@ -1372,7 +1373,7 @@ tag command action ~
|:last| :la[st] go to the last file in the argument list
|:language| :lan[guage] set the language (locale)
|:later| :lat[er] go to newer change, redo
-|:lbefore| :lbef[ore] go to location before current cursor
+|:lbefore| :lbe[fore] go to location before current cursor
|:lbelow| :lbel[ow] go to location below current line
|:lbottom| :lbo[ttom] scroll to the bottom of the location window
|:lbuffer| :lb[uffer] parse locations and jump to first location
@@ -1410,7 +1411,7 @@ tag command action ~
|:lockmarks| :loc[kmarks] following command keeps marks where they are
|:lockvar| :lockv[ar] lock variables
|:lolder| :lol[der] go to older location list
-|:lopen| :lope[n] open location window
+|:lopen| :lop[en] open location window
|:lprevious| :lp[revious] go to previous location
|:lpfile| :lpf[ile] go to last location in previous file
|:lrewind| :lr[ewind] go to the specified location, default first one
@@ -1618,7 +1619,7 @@ tag command action ~
|:tNext| :tN[ext] jump to previous matching tag
|:tabNext| :tabN[ext] go to previous tab page
|:tabclose| :tabc[lose] close current tab page
-|:tabdo| :tabdo execute command in each tab page
+|:tabdo| :tabd[o] execute command in each tab page
|:tabedit| :tabe[dit] edit a file in a new tab page
|:tabfind| :tabf[ind] find file in 'path', edit it in a new tab page
|:tabfirst| :tabfir[st] go to first tab page
@@ -1687,7 +1688,7 @@ tag command action ~
|:vsplit| :vs[plit] split current window vertically
|:vunmap| :vu[nmap] like ":unmap" but for Visual+Select mode
|:vunmenu| :vunme[nu] remove menu for Visual+Select mode
-|:windo| :windo execute command in each window
+|:windo| :wind[o] execute command in each window
|:write| :w[rite] write to a file
|:wNext| :wN[ext] write to a file and go to previous file in
argument list
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 71e8a12ca3..16e6abe294 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -2024,7 +2024,7 @@ Lua module: vim.lsp.util *lsp-util*
• {zindex}? (`integer`) override `zindex`, defaults to 50
• {title}? (`string`)
• {title_pos}? (`'left'|'center'|'right'`)
- • {relative}? (`'mouse'|'cursor'`) (default: `'cursor'`)
+ • {relative}? (`'mouse'|'cursor'|'editor'`) (default: `'cursor'`)
• {anchor_bias}? (`'auto'|'above'|'below'`, default: `'auto'`) -
"auto": place window based on which side of the
cursor has more lines
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 463389ed65..6547a76f56 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -618,20 +618,20 @@ Example: TCP echo-server *tcp-server*
Multithreading *lua-loop-threading*
Plugins can perform work in separate (os-level) threads using the threading
-APIs in luv, for instance `vim.uv.new_thread`. Note that every thread
-gets its own separate Lua interpreter state, with no access to Lua globals
-in the main thread. Neither can the state of the editor (buffers, windows,
-etc) be directly accessed from threads.
+APIs in luv, for instance `vim.uv.new_thread`. Each thread has its own
+separate Lua interpreter state, with no access to Lua globals on the main
+thread. Neither can the editor state (buffers, windows, etc) be directly
+accessed from threads.
-A subset of the `vim.*` API is available in threads. This includes:
+A subset of the `vim.*` stdlib is available in threads, including:
- `vim.uv` with a separate event loop per thread.
- `vim.mpack` and `vim.json` (useful for serializing messages between threads)
- `require` in threads can use Lua packages from the global |package.path|
- `print()` and `vim.inspect`
- `vim.diff`
-- most utility functions in `vim.*` for working with pure Lua values
- like `vim.split`, `vim.tbl_*`, `vim.list_*`, and so on.
+- Most utility functions in `vim.*` that work with pure Lua values, like
+ `vim.split`, `vim.tbl_*`, `vim.list_*`, etc.
- `vim.is_thread()` returns true from a non-main thread.
@@ -1473,10 +1473,8 @@ vim.go *vim.go*
<
vim.o *vim.o*
- Get or set |options|. Like `:set`. Invalid key is an error.
-
- Note: this works on both buffer-scoped and window-scoped options using the
- current buffer and window.
+ Get or set |options|. Works like `:set`, so buffer/window-scoped options
+ target the current buffer/window. Invalid key is an error.
Example: >lua
vim.o.cmdheight = 4
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index c2f1a6a2ee..931f5e117c 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -40,7 +40,6 @@ These changes may require adaptations in your config or plugins.
API
-• Improved API "meta" docstrings and :help documentation.
• `vim.rpcnotify(0)` and `rpcnotify(0)` broadcast to ALL channels. Previously
they would "multicast" only to subscribed channels (controlled by
`nvim_subscribe()`). Plugins and clients that want "multicast" behavior must
@@ -62,16 +61,11 @@ On Windows, only building with the UCRT runtime is supported.
DEFAULTS
-• |]d-default| and |[d-default| accept a count.
-• |[D-default| and |]D-default| jump to the first and last diagnostic in the
- current buffer, respectively.
• 'number', 'relativenumber', 'signcolumn', and 'foldcolumn' are disabled in
|terminal| buffers. See |terminal-config| for an example of changing these defaults.
DIAGNOSTICS
-• |vim.diagnostic.config()| accepts a "jump" table to specify defaults for
- |vim.diagnostic.jump()|.
• The "underline" diagnostics handler sorts diagnostics by severity when using
the "severity_sort" option.
@@ -109,11 +103,6 @@ HIGHLIGHTS
LSP
-• Improved rendering of LSP hover docs. |K-lsp-default|
-• |vim.lsp.completion.enable()| gained the `convert` callback which enables
- customizing the transformation of an LSP CompletionItem to |complete-items|.
-• |vim.lsp.diagnostic.from()| can be used to convert a list of
- |vim.Diagnostic| objects into their LSP diagnostic representation.
• |vim.lsp.buf.references()|, |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|,
|vim.lsp.buf.type_definition()|, |vim.lsp.buf.implementation()| and
|vim.lsp.buf.hover()| now support merging the results of multiple clients
@@ -130,15 +119,11 @@ LSP
• |vim.lsp.util.make_position_params()|, |vim.lsp.util.make_range_params()|
and |vim.lsp.util.make_given_range_params()| now require the `position_encoding`
parameter.
-• `:checkhealth vim.lsp` displays the server version (if available).
LUA
• API functions now consistently return an empty dictionary as
|vim.empty_dict()|. Earlier, a |lua-special-tbl| was sometimes used.
-• 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`.
• |vim.json.encode()| no longer escapes forward slashes "/" by default
OPTIONS
@@ -171,9 +156,6 @@ TREESITTER
if no languages are explicitly registered.
• |vim.treesitter.language.add()| returns `true` if a parser was loaded
successfully and `nil,errmsg` otherwise instead of throwing an error.
-• New |TSNode:child_with_descendant()|, which is nearly identical to
- |TSNode:child_containing_descendant()| except that it can return the
- descendant itself.
TUI
@@ -194,6 +176,7 @@ The following new features were added.
API
+• Improved API "meta" docstrings and :help documentation.
• |nvim__ns_set()| can set properties for a namespace
DEFAULTS
@@ -212,6 +195,9 @@ DEFAULTS
on a URL.
• Mouse |popup-menu| includes a "Go to definition" item when LSP is active
in the buffer.
+ • |]d-default| and |[d-default| accept a count.
+ • |[D-default| and |]D-default| jump to the first and last diagnostic in the
+ current buffer, respectively.
• Mappings inspired by Tim Pope's vim-unimpaired:
• |[q|, |]q|, |[Q|, |]Q|, |[CTRL-Q|, |]CTRL-Q| navigate through the |quickfix| list
• |[l|, |]l|, |[L|, |]L|, |[CTRL-L|, |]CTRL-L| navigate through the |location-list|
@@ -226,6 +212,11 @@ DEFAULTS
• `<S-Tab>` in Insert and Select mode maps to `vim.snippet.jump({ direction = -1 })`
when a snippet is active and jumpable backwards.
+DIAGNOSTICS
+
+• |vim.diagnostic.config()| accepts a "jump" table to specify defaults for
+ |vim.diagnostic.jump()|.
+
EDITOR
• Improved |paste| handling for redo (dot-repeat) and macros (|recording|):
@@ -245,6 +236,12 @@ EVENTS
LSP
+• Improved rendering of LSP hover docs. |K-lsp-default|
+• |vim.lsp.completion.enable()| gained the `convert` callback which enables
+ customizing the transformation of an LSP CompletionItem to |complete-items|.
+• |vim.lsp.diagnostic.from()| can be used to convert a list of
+ |vim.Diagnostic| objects into their LSP diagnostic representation.
+• `:checkhealth vim.lsp` displays the server version (if available).
• Completion side effects (including snippet expansion, execution of commands
and application of additional text edits) is now built-in.
• |vim.lsp.util.locations_to_items()| sets `end_col` and `end_lnum` fields.
@@ -267,6 +264,9 @@ LSP
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`.
• |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.
@@ -287,6 +287,8 @@ PERFORMANCE
highlighting.
• LSP diagnostics and inlay hints are de-duplicated (new requests cancel
inflight requests). This greatly improves performance with slow LSP servers.
+• 10x speedup for |vim.treesitter.foldexpr()| (when no parser exists for the
+ buffer).
PLUGINS
@@ -295,6 +297,7 @@ PLUGINS
STARTUP
+• |-es| ("script mode") disables shada by default.
• Nvim will fail if the |--listen| or |$NVIM_LISTEN_ADDRESS| address is
invalid, instead of silently skipping an invalid address.
@@ -325,6 +328,9 @@ TREESITTER
• |treesitter-directive-trim!| can trim all whitespace (not just empty lines)
from both sides of a node.
• |vim.treesitter.get_captures_at_pos()| now returns the `id` of each capture
+• New |TSNode:child_with_descendant()|, which is nearly identical to
+ |TSNode:child_containing_descendant()| except that it can return the
+ descendant itself.
TUI
@@ -353,6 +359,8 @@ UI
• |vim.diagnostic.setqflist()| updates an existing quickfix list with the
given title if found
• |ui-messages| content chunks now also contain the highlight group ID.
+• |:checkhealth| can be display in a floating window and controlled by
+ the |g:health| variable.
==============================================================================
CHANGED FEATURES *news-changed*
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 3b0fa2b371..0bfbea75fb 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -207,12 +207,12 @@ argument.
:print
:set
With |:verbose| or 'verbose', other commands display on stderr: >
- nvim -es +":verbose echo 'foo'"
- nvim -V1 -es +foo
-
-< User |config| is skipped unless |-u| was given.
- Swap file is skipped (like |-n|).
- User |shada| is loaded (unless "-i NONE" is given).
+ nvim -es +"verbose echo 'foo'"
+ nvim -V1 -es +"echo 'foo'"
+<
+ Skips user |config| unless |-u| was given.
+ Disables |shada| unless |-i| was given.
+ Disables swapfile (like |-n|).
*-l*
-l {script} [args]
@@ -235,6 +235,11 @@ argument.
nvim +q -l foo.lua
< This loads Lua module "bar" before executing "foo.lua": >
nvim +"lua require('bar')" -l foo.lua
+< *lua-shebang*
+ You can set the "shebang" of the script so that Nvim executes
+ the script when called with "./" from a shell (remember to
+ "chmod u+x"): >
+ #!/usr/bin/env -S nvim -l
<
Skips user |config| unless |-u| was given.
Disables plugins unless 'loadplugins' was set.
@@ -243,7 +248,7 @@ argument.
*-ll*
-ll {script} [args]
- Execute a Lua script, similarly to |-l|, but the editor is not
+ Executes a Lua script, similarly to |-l|, but the editor is not
initialized. This gives a Lua environment similar to a worker
thread. See |lua-loop-threading|.
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 956fb80e73..28fe943359 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -157,12 +157,12 @@ The following predicates are built in:
(field_identifier) @method)) @_parent
(#has-parent? @_parent template_method function_declarator))
<
- *lua-treesitter-not-predicate*
+ *treesitter-predicate-not*
Each predicate has a `not-` prefixed predicate that is just the negation of
the predicate.
- *lua-treesitter-all-predicate*
- *lua-treesitter-any-predicate*
+ *treesitter-predicate-all*
+ *treesitter-predicate-any*
Queries can use quantifiers to capture multiple nodes. When a capture contains
multiple nodes, predicates match only if ALL nodes contained by the capture
match the predicate. Some predicates (`eq?`, `match?`, `lua-match?`,
@@ -1114,7 +1114,7 @@ stop({bufnr}) *vim.treesitter.stop()*
==============================================================================
-Lua module: vim.treesitter.language *lua-treesitter-language*
+Lua module: vim.treesitter.language *treesitter-language*
add({lang}, {opts}) *vim.treesitter.language.add()*
Load parser with name {lang}
@@ -1463,7 +1463,7 @@ set({lang}, {query_name}, {text}) *vim.treesitter.query.set()*
==============================================================================
-Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree*
+Lua module: vim.treesitter.languagetree *treesitter-languagetree*
A *LanguageTree* contains a tree of parsers: the root treesitter parser for
{lang} and any "injected" language parsers, which themselves may inject other
diff --git a/runtime/doc/tui.txt b/runtime/doc/tui.txt
index 9493f91b1e..96ac54abc5 100644
--- a/runtime/doc/tui.txt
+++ b/runtime/doc/tui.txt
@@ -280,191 +280,5 @@ colours of whitespace are immaterial, in practice they change the colours of
cursors and selections that cross them. This may have a visible, but minor,
effect on some UIs.
-==============================================================================
-Using the mouse *mouse-using*
-
- *mouse-mode-table* *mouse-overview*
-Overview of what the mouse buttons do, when 'mousemodel' is "extend":
-
- *<S-LeftMouse>* *<A-RightMouse>* *<S-RightMouse>* *<RightDrag>*
- *<RightRelease>* *<LeftDrag>*
-Normal Mode: >
- event position selection change action
- cursor window
- ---------------------------------------------------------------------------
- <LeftMouse> yes end yes
- <C-LeftMouse> yes end yes "CTRL-]" (2)
- <S-LeftMouse> yes no change yes "*" (2)
- <LeftDrag> yes start or extend (1) no
- <LeftRelease> yes start or extend (1) no
- <MiddleMouse> yes if not active no put
- <MiddleMouse> yes if active no yank and put
- <RightMouse> yes start or extend yes
- <A-RightMouse> yes start or extend blockw. yes
- <S-RightMouse> yes no change yes "#" (2)
- <C-RightMouse> no no change no "CTRL-T"
- <RightDrag> yes extend no
- <RightRelease> yes extend no
-
-Insert or Replace Mode: >
- event position selection change action
- cursor window
- ---------------------------------------------------------------------------
- <LeftMouse> yes (cannot be active) yes
- <C-LeftMouse> yes (cannot be active) yes "CTRL-O^]" (2)
- <S-LeftMouse> yes (cannot be active) yes "CTRL-O*" (2)
- <LeftDrag> yes start or extend (1) no like CTRL-O (1)
- <LeftRelease> yes start or extend (1) no like CTRL-O (1)
- <MiddleMouse> no (cannot be active) no put register
- <RightMouse> yes start or extend yes like CTRL-O
- <A-RightMouse> yes start or extend blockw. yes
- <S-RightMouse> yes (cannot be active) yes "CTRL-O#" (2)
- <C-RightMouse> no (cannot be active) no "CTRL-O CTRL-T"
-
-In a help window: >
- event position selection change action
- cursor window
- ---------------------------------------------------------------------------
- <2-LeftMouse> yes (cannot be active) no "^]" (jump to help tag)
-
-When 'mousemodel' is "popup", these are different:
-
- *<A-LeftMouse>*
-Normal Mode: >
- event position selection change action
- cursor window
- ---------------------------------------------------------------------------
- <S-LeftMouse> yes start or extend (1) no
- <A-LeftMouse> yes start/extend blockw no
- <RightMouse> no popup menu no
-
-Insert or Replace Mode: >
- event position selection change action
- cursor window
- ---------------------------------------------------------------------------
- <S-LeftMouse> yes start or extend (1) no like CTRL-O (1)
- <A-LeftMouse> yes start/extend blockw no
- <RightMouse> no popup menu no
-
-(1) only if mouse pointer moved since press
-(2) only if click is in same buffer
-
-Clicking the left mouse button causes the cursor to be positioned. If the
-click is in another window that window is made the active window. When
-editing the command-line the cursor can only be positioned on the
-command-line. When in Insert mode Vim remains in Insert mode. If 'scrolloff'
-is set, and the cursor is positioned within 'scrolloff' lines from the window
-border, the text is scrolled.
-
-A selection can be started by pressing the left mouse button on the first
-character, moving the mouse to the last character, then releasing the mouse
-button. You will not always see the selection until you release the button,
-only in some versions (GUI, Win32) will the dragging be shown immediately.
-Note that you can make the text scroll by moving the mouse at least one
-character in the first/last line in the window when 'scrolloff' is non-zero.
-
-In Normal, Visual and Select mode clicking the right mouse button causes the
-Visual area to be extended. When 'mousemodel' is "popup", the left button has
-to be used while keeping the shift key pressed. When clicking in a window
-which is editing another buffer, the Visual or Select mode is stopped.
-
-In Normal, Visual and Select mode clicking the right mouse button with the alt
-key pressed causes the Visual area to become blockwise. When 'mousemodel' is
-"popup" the left button has to be used with the alt key. Note that this won't
-work on systems where the window manager consumes the mouse events when the
-alt key is pressed (it may move the window).
-
- *double-click* *<2-LeftMouse>* *<3-LeftMouse>* *<4-LeftMouse>*
-Double, triple and quadruple clicks are supported when the GUI is active, for
-Win32 and for an xterm. For selecting text, extra clicks extend the
-selection: >
-
- click select
- ---------------------------------
- double word or % match
- triple line
- quadruple rectangular block
-
-Exception: In a Help window a double click jumps to help for the word that is
-clicked on.
-
-A double click on a word selects that word. 'iskeyword' is used to specify
-which characters are included in a word. A double click on a character
-that has a match selects until that match (like using "v%"). If the match is
-an #if/#else/#endif block, the selection becomes linewise.
-For MS-Windows and xterm the time for double clicking can be set with the
-'mousetime' option. For the other systems this time is defined outside of Vim.
-An example, for using a double click to jump to the tag under the cursor: >vim
- :map <2-LeftMouse> :exe "tag " .. expand("<cword>")<CR>
-
-Dragging the mouse with a double click (button-down, button-up, button-down
-and then drag) will result in whole words to be selected. This continues
-until the button is released, at which point the selection is per character
-again.
-
-For scrolling with the mouse see |scroll-mouse-wheel|.
-
-In Insert mode, when a selection is started, Vim goes into Normal mode
-temporarily. When Visual or Select mode ends, it returns to Insert mode.
-This is like using CTRL-O in Insert mode. Select mode is used when the
-'selectmode' option contains "mouse".
-
- *X1Mouse* *X1Drag* *X1Release*
- *X2Mouse* *X2Drag* *X2Release*
- *<MiddleRelease>* *<MiddleDrag>*
-Mouse clicks can be mapped. The codes for mouse clicks are: >
- code mouse button normal action
- ---------------------------------------------------------------------------
- <LeftMouse> left pressed set cursor position
- <LeftDrag> left moved while pressed extend selection
- <LeftRelease> left released set selection end
- <MiddleMouse> middle pressed paste text at cursor position
- <MiddleDrag> middle moved while pressed -
- <MiddleRelease> middle released -
- <RightMouse> right pressed extend selection
- <RightDrag> right moved while pressed extend selection
- <RightRelease> right released set selection end
- <X1Mouse> X1 button pressed -
- <X1Drag> X1 moved while pressed -
- <X1Release> X1 button release -
- <X2Mouse> X2 button pressed -
- <X2Drag> X2 moved while pressed -
- <X2Release> X2 button release -
-
-The X1 and X2 buttons refer to the extra buttons found on some mice. The
-'Microsoft Explorer' mouse has these buttons available to the right thumb.
-Currently X1 and X2 only work on Win32 and X11 environments.
-
-Examples: >vim
- :noremap <MiddleMouse> <LeftMouse><MiddleMouse>
-Paste at the position of the middle mouse button click (otherwise the paste
-would be done at the cursor position). >vim
-
- :noremap <LeftRelease> <LeftRelease>y
-Immediately yank the selection, when using Visual mode.
-
-Note the use of ":noremap" instead of "map" to avoid a recursive mapping.
->vim
- :map <X1Mouse> <C-O>
- :map <X2Mouse> <C-I>
-Map the X1 and X2 buttons to go forwards and backwards in the jump list, see
-|CTRL-O| and |CTRL-I|.
-
- *mouse-swap-buttons*
-To swap the meaning of the left and right mouse buttons: >vim
- :noremap <LeftMouse> <RightMouse>
- :noremap <LeftDrag> <RightDrag>
- :noremap <LeftRelease> <RightRelease>
- :noremap <RightMouse> <LeftMouse>
- :noremap <RightDrag> <LeftDrag>
- :noremap <RightRelease> <LeftRelease>
- :noremap g<LeftMouse> <C-RightMouse>
- :noremap g<RightMouse> <C-LeftMouse>
- :noremap! <LeftMouse> <RightMouse>
- :noremap! <LeftDrag> <RightDrag>
- :noremap! <LeftRelease> <RightRelease>
- :noremap! <RightMouse> <LeftMouse>
- :noremap! <RightDrag> <LeftDrag>
- :noremap! <RightRelease> <LeftRelease>
-<
+
vim:et:sw=2:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 3202a70b76..f958491ccf 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -1103,7 +1103,8 @@ Various: *various-functions*
did_filetype() check if a FileType autocommand was used
eventhandler() check if invoked by an event handler
getpid() get process ID of Vim
- getscriptinfo() get list of sourced vim scripts
+ getscriptinfo() get list of sourced Vim scripts
+ getstacktrace() get current stack trace of Vim scripts
libcall() call a function in an external library
libcallnr() idem, returning a number
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 9f28b373ee..a92ddf33e6 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -409,6 +409,8 @@ Startup:
- |-es| and |-Es| have improved behavior:
- Quits automatically, don't need "-c qa!".
- Skips swap-file dialog.
+ - Optimized for non-interactive scripts: disables swapfile, shada.
+- |-l| Executes Lua scripts non-interactively.
- |-s| reads Normal commands from stdin if the script name is "-".
- Reading text (instead of commands) from stdin |--|:
- works by default: "-" file is optional
diff --git a/runtime/doc/vvars.txt b/runtime/doc/vvars.txt
index 32f3b96269..0ebb54e38a 100644
--- a/runtime/doc/vvars.txt
+++ b/runtime/doc/vvars.txt
@@ -6,7 +6,8 @@
Predefined variables *vvars*
-Some variables can be set by the user, but the type cannot be changed.
+Most variables are read-only, when a variable can be set by the user, it will
+be mentioned at the variable description below. The type cannot be changed.
Type |gO| to see the table of contents.
@@ -195,7 +196,8 @@ v:event
*v:exception* *exception-variable*
v:exception
The value of the exception most recently caught and not
- finished. See also |v:throwpoint| and |throw-variables|.
+ finished. See also |v:stacktrace|, |v:throwpoint|, and
+ |throw-variables|.
Example: >vim
try
throw "oops"
@@ -586,6 +588,13 @@ v:shell_error
endif
<
+ *v:stacktrace* *stacktrace-variable*
+v:stacktrace
+ The stack trace of the exception most recently caught and
+ not finished. Refer to |getstacktrace()| for the structure of
+ stack trace. See also |v:exception|, |v:throwpoint|, and
+ |throw-variables|.
+
*v:statusmsg* *statusmsg-variable*
v:statusmsg
Last given status message.
@@ -679,7 +688,7 @@ v:this_session
v:throwpoint
The point where the exception most recently caught and not
finished was thrown. Not set when commands are typed. See
- also |v:exception| and |throw-variables|.
+ also |v:exception|, |v:stacktrace|, and |throw-variables|.
Example: >vim
try
throw "oops"
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index d3482ff3ec..6dd90f7e49 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -941,8 +941,8 @@ set in the preview window to be able to recognize it. The 'winfixheight'
option is set to have it keep the same height when opening/closing other
windows.
- *:pta* *:ptag*
-:pta[g][!] [tagname]
+ *:pt* *:ptag*
+:pt[ag][!] [tagname]
Does ":tag[!] [tagname]" and shows the found tag in a
"Preview" window without changing the current buffer or cursor
position. If a "Preview" window already exists, it is re-used
diff --git a/runtime/ftplugin/shaderslang.vim b/runtime/ftplugin/shaderslang.vim
new file mode 100644
index 0000000000..f3d1ab8c1c
--- /dev/null
+++ b/runtime/ftplugin/shaderslang.vim
@@ -0,0 +1,54 @@
+" Vim filetype plugin file
+" Language: Slang
+" Maintainer: Austin Shijo <epestr@proton.me>
+" Last Change: 2025 Jan 05
+
+" Only do this when not done yet for this buffer
+if exists("b:did_ftplugin")
+ finish
+endif
+
+" Don't load another plugin for this buffer
+let b:did_ftplugin = 1
+
+" Using line continuation here.
+let s:cpo_save = &cpo
+set cpo-=C
+
+let b:undo_ftplugin = "setl fo< com< cms< inc<"
+
+" Set 'formatoptions' to break comment lines but not other lines,
+" and insert the comment leader when hitting <CR> or using "o".
+setlocal fo-=t fo+=croql
+
+" Set comment string (Slang uses C-style comments)
+setlocal commentstring=//\ %s
+
+" Set 'comments' to format dashed lists in comments
+setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,://
+
+" When the matchit plugin is loaded, this makes the % command skip parens and
+" braces in comments properly, and adds support for shader-specific keywords
+if exists("loaded_matchit")
+ " Add common shader control structures
+ let b:match_words = '{\|^\s*\<\(if\|for\|while\|switch\|struct\|class\)\>:}\|^\s*\<break\>,' ..
+ \ '^\s*#\s*if\(\|def\|ndef\)\>:^\s*#\s*elif\>:^\s*#\s*else\>:^\s*#\s*endif\>,' ..
+ \ '\[:\]'
+ let b:match_skip = 's:comment\|string\|character\|special'
+ let b:match_ignorecase = 0
+ let b:undo_ftplugin ..= " | unlet! b:match_skip b:match_words b:match_ignorecase"
+endif
+
+" Win32 and GTK can filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Slang Source Files (*.slang)\t*.slang\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/ftplugin/tiasm.vim b/runtime/ftplugin/tiasm.vim
new file mode 100644
index 0000000000..13a3dc64f7
--- /dev/null
+++ b/runtime/ftplugin/tiasm.vim
@@ -0,0 +1,18 @@
+" Vim filetype plugin file
+" Language: TI linear assembly language
+" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu>
+" Last Change: 2025 Jan 08
+
+if exists("b:did_ftplugin") | finish | endif
+let b:did_ftplugin = 1
+
+setlocal comments=:;
+setlocal commentstring=;\ %s
+
+let b:undo_ftplugin = "setl commentstring< comments<"
+
+if exists("loaded_matchit")
+ let b:match_words = '^\s\+\.if\>:^\s\+\.elseif:^\s\+\.else\>:^\s\+\.endif\>,^\s\+\.group:^\s\+\.gmember:^\s\+\.endgroup,^\s\+\.loop:^\s\+\.break:^\s\+\.endloop,^\s\+\.macro:^\s\+\.mexit:^\s\+\.endm,^\s\+\.asmfunc:^\s\+\.endasmfunc,^\s\+\.c\?struct:^\s\+\.endstruct,^\s\+\.c\?union:^\s\+\.endunion,^\s\+\.c\?proc:^\s\+\.return:^\s\+\.endproc'
+ let b:match_ignorecase = 1
+ let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words"
+endif
diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim
index b5e8e693f6..6ba057fc03 100644
--- a/runtime/ftplugin/vim.vim
+++ b/runtime/ftplugin/vim.vim
@@ -1,9 +1,9 @@
" Vim filetype plugin
" Language: Vim
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2024 Apr 13
-" 2024 May 23 by Riley Bruins <ribru17@gmail.com> ('commentstring')
+" Last Change: 2025 Jan 06
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
+" Contributors: Riley Bruins <ribru17@gmail.com> ('commentstring')
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -103,8 +103,8 @@ if exists("loaded_matchit")
\ '\<try\>:\%(\%(^\||\)\s*\)\@<=\<cat\%[ch]\>:\%(\%(^\||\)\s*\)\@<=\<fina\%[lly]\>:\%(\%(^\||\)\s*\)\@<=\<endt\%[ry]\>,' ..
\ '\<aug\%[roup]\s\+\%(END\>\)\@!\S:\<aug\%[roup]\s\+END\>,' ..
\ '\<class\>:\<endclass\>,' ..
- \ '\<inte\%[rface]\>:\<endinterface\>,' ..
- \ '\<enu\%[m]\>:\<endenum\>,'
+ \ '\<interface\>:\<endinterface\>,' ..
+ \ '\<enum\>:\<endenum\>'
" Ignore syntax region commands and settings, any 'en*' would clobber
" if-endif.
diff --git a/runtime/lua/coxpcall.lua b/runtime/lua/coxpcall.lua
index 6b179f1ef0..75e7a43567 100644
--- a/runtime/lua/coxpcall.lua
+++ b/runtime/lua/coxpcall.lua
@@ -1,6 +1,10 @@
-------------------------------------------------------------------------------
+-- (Not needed for LuaJIT or Lua 5.2+)
+--
-- Coroutine safe xpcall and pcall versions
--
+-- https://keplerproject.github.io/coxpcall/
+--
-- Encapsulates the protected calls with a coroutine based loop, so errors can
-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines
-- yielding inside the call to pcall or xpcall.
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index e11dddb2d3..c08ab0663b 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -227,10 +227,10 @@ error('Cannot require a meta file')
--- @field do_source? boolean
--- @class vim.api.keyset.set_decoration_provider
---- @field on_start? fun(_: "start", tick: integer)
+--- @field on_start? fun(_: "start", tick: integer): boolean?
--- @field on_buf? fun(_: "buf", bufnr: integer, tick: integer)
---- @field on_win? fun(_: "win", winid: integer, bufnr: integer, toprow: integer, botrow: integer)
---- @field on_line? fun(_: "line", winid: integer, bufnr: integer, row: integer)
+--- @field on_win? fun(_: "win", winid: integer, bufnr: integer, toprow: integer, botrow: integer): boolean?
+--- @field on_line? fun(_: "line", winid: integer, bufnr: integer, row: integer): boolean?
--- @field on_end? fun(_: "end", tick: integer)
--- @field _on_hl_def? fun(_: "hl_def")
--- @field _on_spell_nav? fun(_: "spell_nav")
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index 6662fca84f..031b109b38 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -3770,6 +3770,20 @@ function vim.fn.getregtype(regname) end
--- @return vim.fn.getscriptinfo.ret[]
function vim.fn.getscriptinfo(opts) end
+--- Returns the current stack trace of Vim scripts.
+--- Stack trace is a |List|, of which each item is a |Dictionary|
+--- with the following items:
+--- funcref The funcref if the stack is at a function,
+--- otherwise this item is omitted.
+--- event The string of the event description if the
+--- stack is at an autocmd event, otherwise this
+--- item is omitted.
+--- lnum The line number in the script on the stack.
+--- filepath The file path of the script on the stack.
+---
+--- @return table[]
+function vim.fn.getstacktrace() end
+
--- If {tabnr} is not specified, then information about all the
--- tab pages is returned as a |List|. Each List item is a
--- |Dictionary|. Otherwise, {tabnr} specifies the tab page
diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua
index 445da4e02f..c1b8695bbf 100644
--- a/runtime/lua/vim/_meta/vvars.lua
+++ b/runtime/lua/vim/_meta/vvars.lua
@@ -203,7 +203,8 @@ vim.v.errors = ...
vim.v.event = ...
--- The value of the exception most recently caught and not
---- finished. See also `v:throwpoint` and `throw-variables`.
+--- finished. See also `v:stacktrace`, `v:throwpoint`, and
+--- `throw-variables`.
--- Example:
---
--- ```vim
@@ -616,6 +617,13 @@ vim.v.servername = ...
--- @type integer
vim.v.shell_error = ...
+--- The stack trace of the exception most recently caught and
+--- not finished. Refer to `getstacktrace()` for the structure of
+--- stack trace. See also `v:exception`, `v:throwpoint`, and
+--- `throw-variables`.
+--- @type table[]
+vim.v.stacktrace = ...
+
--- Last given status message.
--- Modifiable (can be set).
--- @type string
@@ -718,7 +726,7 @@ vim.v.this_session = ...
--- The point where the exception most recently caught and not
--- finished was thrown. Not set when commands are typed. See
---- also `v:exception` and `throw-variables`.
+--- also `v:exception`, `v:stacktrace`, and `throw-variables`.
--- Example:
---
--- ```vim
diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua
index 77d7054626..dc37595578 100644
--- a/runtime/lua/vim/_options.lua
+++ b/runtime/lua/vim/_options.lua
@@ -229,10 +229,8 @@ end
--- global value of a |global-local| option, see |:setglobal|.
--- </pre>
---- Get or set |options|. Like `:set`. Invalid key is an error.
----
---- Note: this works on both buffer-scoped and window-scoped options using the
---- current buffer and window.
+--- Get or set |options|. Works like `:set`, so buffer/window-scoped options target the current
+--- buffer/window. Invalid key is an error.
---
--- Example:
---
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index b6d6906589..dee1bd88ca 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -1064,11 +1064,11 @@ local extension = {
builder = 'ruby',
rake = 'ruby',
rs = 'rust',
+ sa = detect.sa,
sage = 'sage',
sls = 'salt',
sas = 'sas',
sass = 'sass',
- sa = 'sather',
sbt = 'sbt',
scala = 'scala',
ss = 'scheme',
@@ -1097,6 +1097,7 @@ local extension = {
la = 'sh',
lai = 'sh',
mdd = 'sh',
+ slang = 'shaderslang',
sieve = 'sieve',
siv = 'sieve',
sig = detect.sig,
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index a1c17bc1af..2d989fdbac 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -34,6 +34,12 @@ local matchregex = vim.filetype._matchregex
-- can be detected from the first five lines of the file.
--- @type vim.filetype.mapfn
function M.asm(path, bufnr)
+ -- tiasm uses `* commment`
+ local lines = table.concat(getlines(bufnr, 1, 10), '\n')
+ if findany(lines, { '^%*', '\n%*', 'Texas Instruments Incorporated' }) then
+ return 'tiasm'
+ end
+
local syntax = vim.b[bufnr].asmsyntax
if not syntax or syntax == '' then
syntax = M.asm_syntax(path, bufnr)
@@ -1424,6 +1430,15 @@ function M.sig(_, bufnr)
end
end
+--- @type vim.filetype.mapfn
+function M.sa(_, bufnr)
+ local lines = table.concat(getlines(bufnr, 1, 4), '\n')
+ if findany(lines, { '^;', '\n;' }) then
+ return 'tiasm'
+ end
+ return 'sather'
+end
+
-- This function checks the first 25 lines of file extension "sc" to resolve
-- detection between scala and SuperCollider
--- @type vim.filetype.mapfn
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index ee713e4b58..04a6e43db1 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -629,8 +629,8 @@ function M.normalize(path, opts)
return prefix .. path
end
- -- Remove extraneous slashes from the prefix
- prefix = prefix:gsub('/+', '/')
+ -- Ensure capital drive and remove extraneous slashes from the prefix
+ prefix = prefix:gsub('^%a:', string.upper):gsub('/+', '/')
end
if not opts._fast then
diff --git a/runtime/lua/vim/func.lua b/runtime/lua/vim/func.lua
index f71659ffb4..fc8fa62c71 100644
--- a/runtime/lua/vim/func.lua
+++ b/runtime/lua/vim/func.lua
@@ -3,9 +3,6 @@ local M = {}
-- TODO(lewis6991): Private for now until:
-- - There are other places in the codebase that could benefit from this
-- (e.g. LSP), but might require other changes to accommodate.
--- - Invalidation of the cache needs to be controllable. Using weak tables
--- is an acceptable invalidation policy, but it shouldn't be the only
--- one.
-- - I don't think the story around `hash` is completely thought out. We
-- may be able to have a good default hash by hashing each argument,
-- so basically a better 'concat'.
@@ -17,6 +14,10 @@ local M = {}
--- Internally uses a |lua-weaktable| to cache the results of {fn} meaning the
--- cache will be invalidated whenever Lua does garbage collection.
---
+--- The cache can also be manually invalidated by calling `:clear()` on the returned object.
+--- Calling this function with no arguments clears the entire cache; otherwise, the arguments will
+--- be interpreted as function inputs, and only the cache entry at their hash will be cleared.
+---
--- The memoized function returns shared references so be wary about
--- mutating return values.
---
@@ -32,11 +33,12 @@ local M = {}
--- first n arguments passed to {fn}.
---
--- @param fn F Function to memoize.
---- @param strong? boolean Do not use a weak table
+--- @param weak? boolean Use a weak table (default `true`)
--- @return F # Memoized version of {fn}
--- @nodoc
-function M._memoize(hash, fn, strong)
- return require('vim.func._memoize')(hash, fn, strong)
+function M._memoize(hash, fn, weak)
+ -- this is wrapped in a function to lazily require the module
+ return require('vim.func._memoize')(hash, fn, weak)
end
return M
diff --git a/runtime/lua/vim/func/_memoize.lua b/runtime/lua/vim/func/_memoize.lua
index 6e557905a7..c46f878067 100644
--- a/runtime/lua/vim/func/_memoize.lua
+++ b/runtime/lua/vim/func/_memoize.lua
@@ -1,5 +1,7 @@
--- Module for private utility functions
+--- @alias vim.func.MemoObj { _hash: (fun(...): any), _weak: boolean?, _cache: table<any> }
+
--- @param argc integer?
--- @return fun(...): any
local function concat_hash(argc)
@@ -33,29 +35,49 @@ local function resolve_hash(hash)
return hash
end
+--- @param weak boolean?
+--- @return table
+local create_cache = function(weak)
+ return setmetatable({}, {
+ __mode = weak ~= false and 'kv',
+ })
+end
+
--- @generic F: function
--- @param hash integer|string|fun(...): any
--- @param fn F
---- @param strong? boolean
+--- @param weak? boolean
--- @return F
-return function(hash, fn, strong)
+return function(hash, fn, weak)
vim.validate('hash', hash, { 'number', 'string', 'function' })
vim.validate('fn', fn, 'function')
+ vim.validate('weak', weak, 'boolean', true)
- ---@type table<any,table<any,any>>
- local cache = {}
- if not strong then
- setmetatable(cache, { __mode = 'kv' })
- end
-
- hash = resolve_hash(hash)
+ --- @type vim.func.MemoObj
+ local obj = {
+ _cache = create_cache(weak),
+ _hash = resolve_hash(hash),
+ _weak = weak,
+ --- @param self vim.func.MemoObj
+ clear = function(self, ...)
+ if select('#', ...) == 0 then
+ self._cache = create_cache(self._weak)
+ return
+ end
+ local key = self._hash(...)
+ self._cache[key] = nil
+ end,
+ }
- return function(...)
- local key = hash(...)
- if cache[key] == nil then
- cache[key] = vim.F.pack_len(fn(...))
- end
-
- return vim.F.unpack_len(cache[key])
- end
+ return setmetatable(obj, {
+ --- @param self vim.func.MemoObj
+ __call = function(self, ...)
+ local key = self._hash(...)
+ local cache = self._cache
+ if cache[key] == nil then
+ cache[key] = vim.F.pack_len(fn(...))
+ end
+ return vim.F.unpack_len(cache[key])
+ end,
+ })
end
diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua
index 52a7a13966..6dc902489f 100644
--- a/runtime/lua/vim/health.lua
+++ b/runtime/lua/vim/health.lua
@@ -11,6 +11,17 @@
--- <
--- Plugin authors are encouraged to write new healthchecks. |health-dev|
---
+--- *g:health*
+--- g:health This global variable controls the behavior and appearance of the
+--- `health` floating window. It should be a dictionary containing the
+--- following optional keys:
+--- - `style`: string? Determines the display style of the `health` window.
+--- Set to `'float'` to enable a floating window. Other
+--- styles are not currently supported.
+---
+--- Example: >lua
+--- vim.g.health = { style = 'float' }
+---
--- Commands *health-commands*
---
--- *:che* *:checkhealth*
@@ -331,13 +342,31 @@ function M._check(mods, plugin_names)
local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$')
- -- When no command modifiers are used:
- -- - If the current buffer is empty, open healthcheck directly.
- -- - If not specified otherwise open healthcheck in a tab.
- local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab sbuffer'
-
local bufnr = vim.api.nvim_create_buf(true, true)
- vim.cmd(buf_cmd .. ' ' .. bufnr)
+ if
+ vim.g.health
+ and type(vim.g.health) == 'table'
+ and vim.tbl_get(vim.g.health, 'style') == 'float'
+ then
+ local max_height = math.floor(vim.o.lines * 0.8)
+ local max_width = 80
+ local float_bufnr, float_winid = vim.lsp.util.open_floating_preview({}, '', {
+ height = max_height,
+ width = max_width,
+ offset_x = math.floor((vim.o.columns - max_width) / 2),
+ offset_y = math.floor((vim.o.lines - max_height) / 2) - 1,
+ relative = 'editor',
+ })
+ vim.api.nvim_set_current_win(float_winid)
+ vim.bo[float_bufnr].modifiable = true
+ vim.wo[float_winid].list = false
+ else
+ -- When no command modifiers are used:
+ -- - If the current buffer is empty, open healthcheck directly.
+ -- - If not specified otherwise open healthcheck in a tab.
+ local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab sbuffer'
+ vim.cmd(buf_cmd .. ' ' .. bufnr)
+ end
if vim.fn.bufexists('health://') == 1 then
vim.cmd.bwipe('health://')
@@ -407,6 +436,17 @@ function M._check(mods, plugin_names)
-- Clear the 'Running healthchecks...' message.
vim.cmd.redraw()
vim.print('')
+
+ -- Quit with 'q' inside healthcheck buffers.
+ vim.keymap.set('n', 'q', function()
+ local ok, _ = pcall(vim.cmd.close)
+ if not ok then
+ vim.cmd.bdelete()
+ end
+ end, { buffer = bufnr, silent = true, noremap = true, nowait = true })
+
+ -- Once we're done writing checks, set nomodifiable.
+ vim.bo[bufnr].modifiable = false
end
return M
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 6bee5bc31f..5cccb3321f 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -875,15 +875,17 @@ function M.make_floating_popup_options(width, height, opts)
return {
anchor = anchor,
+ row = row + (opts.offset_y or 0),
col = col + (opts.offset_x or 0),
height = height,
focusable = opts.focusable,
- relative = opts.relative == 'mouse' and 'mouse' or 'cursor',
- row = row + (opts.offset_y or 0),
+ relative = opts.relative == 'mouse' and 'mouse'
+ or opts.relative == 'editor' and 'editor'
+ or 'cursor',
style = 'minimal',
width = width,
border = opts.border or default_border,
- zindex = opts.zindex or 50,
+ zindex = opts.zindex or (api.nvim_win_get_config(0).zindex or 49) + 1,
title = title,
title_pos = title_pos,
}
@@ -1494,7 +1496,7 @@ end
--- @field title_pos? 'left'|'center'|'right'
---
--- (default: `'cursor'`)
---- @field relative? 'mouse'|'cursor'
+--- @field relative? 'mouse'|'cursor'|'editor'
---
--- - "auto": place window based on which side of the cursor has more lines
--- - "above": place the window above the cursor unless there are not enough lines
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index 207ac1ab67..d16013eca2 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -19,14 +19,19 @@ local api = vim.api
---The range on which to evaluate foldexpr.
---When in insert mode, the evaluation is deferred to InsertLeave.
---@field foldupdate_range? Range2
+---
+---The treesitter parser associated with this buffer.
+---@field parser? vim.treesitter.LanguageTree
local FoldInfo = {}
FoldInfo.__index = FoldInfo
---@private
-function FoldInfo.new()
+---@param bufnr integer
+function FoldInfo.new(bufnr)
return setmetatable({
levels0 = {},
levels = {},
+ parser = ts.get_parser(bufnr, nil, { error = false }),
}, FoldInfo)
end
@@ -69,7 +74,10 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections)
srow = srow or 0
erow = erow or api.nvim_buf_line_count(bufnr)
- local parser = assert(ts.get_parser(bufnr, nil, { error = false }))
+ local parser = info.parser
+ if not parser then
+ return
+ end
parser:parse(parse_injections and { srow, erow } or nil)
@@ -347,13 +355,21 @@ function M.foldexpr(lnum)
lnum = lnum or vim.v.lnum
local bufnr = api.nvim_get_current_buf()
- local parser = ts.get_parser(bufnr, nil, { error = false })
- if not parser then
- return '0'
- end
-
if not foldinfos[bufnr] then
- foldinfos[bufnr] = FoldInfo.new()
+ foldinfos[bufnr] = FoldInfo.new(bufnr)
+ api.nvim_create_autocmd('BufUnload', {
+ buffer = bufnr,
+ once = true,
+ callback = function()
+ foldinfos[bufnr] = nil
+ end,
+ })
+
+ local parser = foldinfos[bufnr].parser
+ if not parser then
+ return '0'
+ end
+
compute_folds_levels(bufnr, foldinfos[bufnr])
parser:register_cbs({
@@ -383,7 +399,7 @@ api.nvim_create_autocmd('OptionSet', {
or foldinfos[buf] and { buf }
or {}
for _, bufnr in ipairs(bufs) do
- foldinfos[bufnr] = FoldInfo.new()
+ foldinfos[bufnr] = FoldInfo.new(bufnr)
api.nvim_buf_call(bufnr, function()
compute_folds_levels(bufnr, foldinfos[bufnr])
end)
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 8ce8652f7d..96503c38ea 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -299,6 +299,8 @@ local function on_line_impl(self, buf, line, is_spell_nav)
state.highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1)
end
+ local captures = state.highlighter_query:query().captures
+
while line >= state.next_row do
local capture, node, metadata, match = state.iter(line)
@@ -311,7 +313,7 @@ local function on_line_impl(self, buf, line, is_spell_nav)
if capture then
local hl = state.highlighter_query:get_hl_from_capture(capture)
- local capture_name = state.highlighter_query:query().captures[capture]
+ local capture_name = captures[capture]
local spell, spell_pri_offset = get_spell(capture_name)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 4b42164dc8..330eb45749 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -443,7 +443,7 @@ function LanguageTree:parse(range)
end
end
- if not self._injections_processed and range ~= false and range ~= nil then
+ if not self._injections_processed and range then
query_time = self:_add_injections()
self._injections_processed = true
end
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index f9c497337f..1fc001b39f 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -7,6 +7,59 @@ local memoize = vim.func._memoize
local M = {}
+local function is_directive(name)
+ return string.sub(name, -1) == '!'
+end
+
+---@nodoc
+---@class vim.treesitter.query.ProcessedPredicate
+---@field [1] string predicate name
+---@field [2] boolean should match
+---@field [3] (integer|string)[] the original predicate
+
+---@alias vim.treesitter.query.ProcessedDirective (integer|string)[]
+
+---@nodoc
+---@class vim.treesitter.query.ProcessedPattern {
+---@field predicates vim.treesitter.query.ProcessedPredicate[]
+---@field directives vim.treesitter.query.ProcessedDirective[]
+
+--- Splits the query patterns into predicates and directives.
+---@param patterns table<integer, (integer|string)[][]>
+---@return table<integer, vim.treesitter.query.ProcessedPattern>
+local function process_patterns(patterns)
+ ---@type table<integer, vim.treesitter.query.ProcessedPattern>
+ local processed_patterns = {}
+
+ for k, pattern_list in pairs(patterns) do
+ ---@type vim.treesitter.query.ProcessedPredicate[]
+ local predicates = {}
+ ---@type vim.treesitter.query.ProcessedDirective[]
+ local directives = {}
+
+ for _, pattern in ipairs(pattern_list) do
+ -- Note: tree-sitter strips the leading # from predicates for us.
+ local pred_name = pattern[1]
+ ---@cast pred_name string
+
+ if is_directive(pred_name) then
+ table.insert(directives, pattern)
+ else
+ local should_match = true
+ if pred_name:match('^not%-') then
+ pred_name = pred_name:sub(5)
+ should_match = false
+ end
+ table.insert(predicates, { pred_name, should_match, pattern })
+ end
+ end
+
+ processed_patterns[k] = { predicates = predicates, directives = directives }
+ end
+
+ return processed_patterns
+end
+
---@nodoc
---Parsed query, see |vim.treesitter.query.parse()|
---
@@ -15,6 +68,7 @@ local M = {}
---@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 private _processed_patterns table<integer, vim.treesitter.query.ProcessedPattern>
local Query = {}
Query.__index = Query
@@ -33,6 +87,7 @@ function Query.new(lang, ts_query)
patterns = query_info.patterns,
}
self.captures = self.info.captures
+ self._processed_patterns = process_patterns(self.info.patterns)
return self
end
@@ -751,84 +806,50 @@ function M.list_predicates()
return vim.tbl_keys(predicate_handlers)
end
-local function xor(x, y)
- return (x or y) and not (x and y)
-end
-
-local function is_directive(name)
- return string.sub(name, -1) == '!'
-end
-
---@private
----@param match TSQueryMatch
+---@param pattern_i integer
+---@param predicates vim.treesitter.query.ProcessedPredicate[]
+---@param captures table<integer, TSNode[]>
---@param source integer|string
-function Query:match_preds(match, source)
- local _, pattern = match:info()
- local preds = self.info.patterns[pattern]
-
- if not preds then
- return true
- end
-
- local captures = match:captures()
-
- for _, pred in pairs(preds) do
- -- Here we only want to return if a predicate DOES NOT match, and
- -- continue on the other case. This way unknown predicates will not be considered,
- -- which allows some testing and easier user extensibility (#12173).
- -- Also, tree-sitter strips the leading # from predicates for us.
- local is_not = false
-
- -- Skip over directives... they will get processed after all the predicates.
- if not is_directive(pred[1]) then
- local pred_name = pred[1]
- if pred_name:match('^not%-') then
- pred_name = pred_name:sub(5)
- is_not = true
- end
-
- local handler = predicate_handlers[pred_name]
-
- if not handler then
- error(string.format('No handler for %s', pred[1]))
- return false
- end
-
- local pred_matches = handler(captures, pattern, source, pred)
+---@return boolean whether the predicates match
+function Query:_match_predicates(predicates, pattern_i, captures, source)
+ for _, predicate in ipairs(predicates) do
+ local processed_name = predicate[1]
+ local should_match = predicate[2]
+ local orig_predicate = predicate[3]
+
+ local handler = predicate_handlers[processed_name]
+ if not handler then
+ error(string.format('No handler for %s', orig_predicate[1]))
+ return false
+ end
- if not xor(is_not, pred_matches) then
- return false
- end
+ local does_match = handler(captures, pattern_i, source, orig_predicate)
+ if does_match ~= should_match then
+ return false
end
end
return true
end
---@private
----@param match TSQueryMatch
+---@param pattern_i integer
+---@param directives vim.treesitter.query.ProcessedDirective[]
+---@param source integer|string
+---@param captures table<integer, TSNode[]>
---@return vim.treesitter.query.TSMetadata metadata
-function Query:apply_directives(match, source)
+function Query:_apply_directives(directives, pattern_i, captures, source)
---@type vim.treesitter.query.TSMetadata
local metadata = {}
- local _, pattern = match:info()
- local preds = self.info.patterns[pattern]
- if not preds then
- return metadata
- end
+ for _, directive in pairs(directives) do
+ local handler = directive_handlers[directive[1]]
- local captures = match:captures()
-
- for _, pred in pairs(preds) do
- if is_directive(pred[1]) then
- local handler = directive_handlers[pred[1]]
-
- if not handler then
- error(string.format('No handler for %s', pred[1]))
- end
-
- handler(captures, pattern, source, pred, metadata)
+ if not handler then
+ error(string.format('No handler for %s', directive[1]))
end
+
+ handler(captures, pattern_i, source, directive, metadata)
end
return metadata
@@ -852,12 +873,6 @@ local function value_or_node_range(start, stop, node)
return start, stop
end
---- @param match TSQueryMatch
---- @return integer
-local function match_id_hash(_, match)
- return (match:info())
-end
-
--- Iterates over all captures from all matches in {node}.
---
--- {source} is required if the query contains predicates; then the caller
@@ -902,8 +917,10 @@ function Query:iter_captures(node, source, start, stop)
local cursor = vim._create_ts_querycursor(node, self.query, start, stop, { match_limit = 256 })
- local apply_directives = memoize(match_id_hash, self.apply_directives, true)
- local match_preds = memoize(match_id_hash, self.match_preds, true)
+ -- For faster checks that a match is not in the cache.
+ local highest_cached_match_id = -1
+ ---@type table<integer, vim.treesitter.query.TSMetadata>
+ local match_cache = {}
local function iter(end_line)
local capture, captured_node, match = cursor:next_capture()
@@ -912,16 +929,37 @@ function Query:iter_captures(node, source, start, stop)
return
end
- if not match_preds(self, match, source) then
- local match_id = match:info()
- cursor:remove_match(match_id)
- if end_line and captured_node:range() > end_line then
- return nil, captured_node, nil, nil
- end
- return iter(end_line) -- tail call: try next match
+ local match_id, pattern_i = match:info()
+
+ --- @type vim.treesitter.query.TSMetadata
+ local metadata
+ if match_id <= highest_cached_match_id then
+ metadata = match_cache[match_id]
end
- local metadata = apply_directives(self, match, source)
+ if not metadata then
+ metadata = {}
+
+ local processed_pattern = self._processed_patterns[pattern_i]
+ if processed_pattern then
+ local captures = match:captures()
+
+ local predicates = processed_pattern.predicates
+ if not self:_match_predicates(predicates, pattern_i, captures, source) then
+ cursor:remove_match(match_id)
+ if end_line and captured_node:range() > end_line then
+ return nil, captured_node, nil, nil
+ end
+ return iter(end_line) -- tail call: try next match
+ end
+
+ local directives = processed_pattern.directives
+ metadata = self:_apply_directives(directives, pattern_i, captures, source)
+ end
+
+ highest_cached_match_id = math.max(highest_cached_match_id, match_id)
+ match_cache[match_id] = metadata
+ end
return capture, captured_node, metadata, match
end
@@ -984,17 +1022,22 @@ function Query:iter_matches(node, source, start, stop, opts)
return
end
- local match_id, pattern = match:info()
+ local match_id, pattern_i = match:info()
+ local processed_pattern = self._processed_patterns[pattern_i]
+ local captures = match:captures()
- if not self:match_preds(match, source) then
- cursor:remove_match(match_id)
- return iter() -- tail call: try next match
+ --- @type vim.treesitter.query.TSMetadata
+ local metadata = {}
+ if processed_pattern then
+ local predicates = processed_pattern.predicates
+ if not self:_match_predicates(predicates, pattern_i, captures, source) then
+ cursor:remove_match(match_id)
+ return iter() -- tail call: try next match
+ end
+ local directives = processed_pattern.directives
+ metadata = self:_apply_directives(directives, pattern_i, captures, source)
end
- local metadata = self:apply_directives(match, source)
-
- local captures = match:captures()
-
if opts.all == false then
-- Convert the match table into the old buggy version for backward
-- compatibility. This is slow, but we only do it when the caller explicitly opted into it by
@@ -1003,11 +1046,11 @@ function Query:iter_matches(node, source, start, stop, opts)
for k, v in pairs(captures or {}) do
old_match[k] = v[#v]
end
- return pattern, old_match, metadata
+ return pattern_i, old_match, metadata
end
-- TODO(lewis6991): create a new function that returns {match, metadata}
- return pattern, captures, metadata
+ return pattern_i, captures, metadata
end
return iter
end
diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
index aa977488e5..8a220eeb9b 100644
--- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim
+++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
@@ -222,6 +222,7 @@ function matchit#Match_wrapper(word, forward, mode) range
let view = winsaveview()
call cursor(0, curcol + 1)
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
+ \ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight')
let skip = "0"
else
execute "if " .. skip .. "| let skip = '0' | endif"
@@ -678,6 +679,7 @@ fun! matchit#MultiMatch(spflag, mode)
let middlepat = substitute(middlepat, ',', '\\|', 'g')
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
+ \ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight')
let skip = '0'
else
try
@@ -760,10 +762,16 @@ endfun
" S:foo becomes (current syntax item) !~ foo
" r:foo becomes (line before cursor) =~ foo
" R:foo becomes (line before cursor) !~ foo
+" t:foo becomes (current treesitter captures) =~ foo
+" T:foo becomes (current treesitter captures) !~ foo
fun! s:ParseSkip(str)
let skip = a:str
if skip[1] == ":"
- if skip[0] ==# "s"
+ if skip[0] ==# "t" || skip[0] ==# "s" && &syntax != 'on' && exists("b:ts_highlight")
+ let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') != -1"
+ elseif skip[0] ==# "T" || skip[0] ==# "S" && &syntax != 'on' && exists("b:ts_highlight")
+ let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') == -1"
+ elseif skip[0] ==# "s"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" ..
\ strpart(skip,2) .. "'"
elseif skip[0] ==# "S"
diff --git a/runtime/pack/dist/opt/matchit/doc/matchit.txt b/runtime/pack/dist/opt/matchit/doc/matchit.txt
index 8d56df6ddc..58031d8a8a 100644
--- a/runtime/pack/dist/opt/matchit/doc/matchit.txt
+++ b/runtime/pack/dist/opt/matchit/doc/matchit.txt
@@ -237,6 +237,8 @@ supported by matchit.vim:
S:foo becomes (current syntax item) !~ foo
r:foo becomes (line before cursor) =~ foo
R:foo becomes (line before cursor) !~ foo
+ t:foo becomes (current treesitter captures) =~ foo
+ T:foo becomes (current treesitter captures) !~ foo
(The "s" is meant to suggest "syntax", and the "r" is meant to suggest
"regular expression".)
diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim
index 661a34b578..13d1b6824f 100644
--- a/runtime/plugin/matchparen.vim
+++ b/runtime/plugin/matchparen.vim
@@ -109,6 +109,10 @@ func s:Highlight_Matching_Pair()
if !has("syntax") || !exists("g:syntax_on")
let s_skip = "0"
+ elseif exists("b:ts_highlight") && &syntax != 'on'
+ let s_skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '"
+ \ .. 'string\|character\|singlequote\|escape\|symbol\|comment'
+ \ .. "') != -1"
else
" Build an expression that detects whether the current cursor position is
" in certain syntax types (string, comment, etc.), for use as
diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim
index b3e17b55f6..9b38ccd4dc 100644
--- a/runtime/syntax/java.vim
+++ b/runtime/syntax/java.vim
@@ -3,7 +3,7 @@
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
" Repository: https://github.com/zzzyxwvut/java-vim.git
-" Last Change: 2024 Oct 10
+" Last Change: 2025 Jan 02
" Please check ":help java.vim" for comments on some of the options
" available.
@@ -391,18 +391,32 @@ if !exists("g:java_ignore_javadoc") && (s:with_html || s:with_markdown) && g:mai
if s:with_markdown
try
syntax include @javaMarkdown syntax/markdown.vim
- let s:ff.WithMarkdown = s:ff.LeftConstant
+
+ try
+ syn clear markdownId markdownLineStart markdownH1 markdownH2 markdownHeadingRule markdownRule markdownCode markdownCodeBlock markdownIdDeclaration
+ let s:ff.WithMarkdown = s:ff.LeftConstant
+ catch /\<E28:/
+ call s:ReportOnce(v:exception)
+ let s:no_support = 1
+ unlet! g:java_ignore_markdown
+ let g:java_ignore_markdown = 28
+ endtry
catch /\<E48[45]:/
call s:ReportOnce(v:exception)
- unlockvar s:with_markdown
- let s:with_markdown = 0
- lockvar s:with_markdown
- hi clear markdownCode
- hi clear markdownCodeBlock
- hi clear markdownCodeDelimiter
- hi clear markdownLinkDelimiter
+ let s:no_support = 1
finally
unlet! b:current_syntax
+
+ if exists("s:no_support")
+ unlet s:no_support
+ unlockvar s:with_markdown
+ let s:with_markdown = 0
+ lockvar s:with_markdown
+ hi clear markdownCode
+ hi clear markdownCodeBlock
+ hi clear markdownCodeDelimiter
+ hi clear markdownLinkDelimiter
+ endif
endtry
endif
@@ -422,7 +436,6 @@ if !exists("g:java_ignore_javadoc") && (s:with_html || s:with_markdown) && g:mai
exec 'syn region javaMarkdownCommentTitle contained matchgroup=javaMarkdownComment start="\%(///.*\r\=\n\s*\)\@' . s:ff.Peek('80', '') . '<!///\s*\%({@return\>\)\@=" matchgroup=javaMarkdownCommentTitle end="}\%(\s*\.*\)*" contains=javaMarkdownShortcutLink,@javaMarkdown,javaMarkdownCommentMask,javaTodo,@Spell,@javaDocTags,javaTitleSkipBlock'
exec 'syn region javaMarkdownCommentTitle contained matchgroup=javaMarkdownComment start="\%(///.*\r\=\n\s*\)\@' . s:ff.Peek('80', '') . '<!///\s*\%({@summary\>\)\@=" matchgroup=javaMarkdownCommentTitle end="}" contains=javaMarkdownShortcutLink,@javaMarkdown,javaMarkdownCommentMask,javaTodo,@Spell,@javaDocTags,javaTitleSkipBlock'
- syn clear markdownId markdownLineStart markdownH1 markdownH2 markdownHeadingRule markdownRule markdownCode markdownCodeBlock markdownIdDeclaration
" REDEFINE THE MARKDOWN ITEMS ANCHORED WITH "^", OBSERVING THE
" DEFINITION ORDER.
syn match markdownLineStart contained "^\s*///\s*[<@]\@!" contains=@markdownBlock,javaMarkdownCommentTitle,javaMarkdownCommentMask nextgroup=@markdownBlock,htmlSpecialChar
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index 0a8fb47b7d..d71a966553 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -5,6 +5,7 @@
" Lennart Schultz <Lennart.Schultz@ecmwf.int>
" Last Change: 2024 Mar 04 by Vim Project
" 2024 Nov 03 by Aliaksei Budavei <0x000c70 AT gmail DOT com> (improved bracket expressions, #15941)
+" 2025 Jan 06 add $PS0 to bashSpecialVariables (#16394)
" Version: 208
" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
@@ -404,7 +405,7 @@ syn region shCmdParenRegion matchgroup=shCmdSubRegion start="((\@!" skip='\\\\\|
if exists("b:is_bash")
syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
syn cluster shCaseList add=bashAdminStatement,bashStatement
- syn keyword bashSpecialVariables contained auto_resume BASH BASH_ALIASES BASH_ALIASES BASH_ARGC BASH_ARGC BASH_ARGV BASH_ARGV BASH_CMDS BASH_CMDS BASH_COMMAND BASH_COMMAND BASH_ENV BASH_EXECUTION_STRING BASH_EXECUTION_STRING BASH_LINENO BASH_LINENO BASHOPTS BASHOPTS BASHPID BASHPID BASH_REMATCH BASH_REMATCH BASH_SOURCE BASH_SOURCE BASH_SUBSHELL BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH_XTRACEFD BASH_XTRACEFD CDPATH COLUMNS COLUMNS COMP_CWORD COMP_CWORD COMP_KEY COMP_KEY COMP_LINE COMP_LINE COMP_POINT COMP_POINT COMPREPLY COMPREPLY COMP_TYPE COMP_TYPE COMP_WORDBREAKS COMP_WORDBREAKS COMP_WORDS COMP_WORDS COPROC COPROC DIRSTACK EMACS EMACS ENV ENV EUID FCEDIT FIGNORE FUNCNAME FUNCNAME FUNCNEST FUNCNEST GLOBIGNORE GROUPS histchars HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HISTTIMEFORMAT HISTTIMEFORMAT HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_CTYPE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_NUMERIC LINENO LINES LINES MACHTYPE MAIL MAILCHECK MAILPATH MAPFILE MAPFILE OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS POSIXLY_CORRECT POSIXLY_CORRECT PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM READLINE_LINE READLINE_LINE READLINE_POINT READLINE_POINT REPLY SECONDS SHELL SHELL SHELLOPTS SHLVL TIMEFORMAT TIMEOUT TMPDIR TMPDIR UID
+ syn keyword bashSpecialVariables contained auto_resume BASH BASH_ALIASES BASH_ALIASES BASH_ARGC BASH_ARGC BASH_ARGV BASH_ARGV BASH_CMDS BASH_CMDS BASH_COMMAND BASH_COMMAND BASH_ENV BASH_EXECUTION_STRING BASH_EXECUTION_STRING BASH_LINENO BASH_LINENO BASHOPTS BASHOPTS BASHPID BASHPID BASH_REMATCH BASH_REMATCH BASH_SOURCE BASH_SOURCE BASH_SUBSHELL BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH_XTRACEFD BASH_XTRACEFD CDPATH COLUMNS COLUMNS COMP_CWORD COMP_CWORD COMP_KEY COMP_KEY COMP_LINE COMP_LINE COMP_POINT COMP_POINT COMPREPLY COMPREPLY COMP_TYPE COMP_TYPE COMP_WORDBREAKS COMP_WORDBREAKS COMP_WORDS COMP_WORDS COPROC COPROC DIRSTACK EMACS EMACS ENV ENV EUID FCEDIT FIGNORE FUNCNAME FUNCNAME FUNCNEST FUNCNEST GLOBIGNORE GROUPS histchars HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HISTTIMEFORMAT HISTTIMEFORMAT HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_CTYPE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_NUMERIC LINENO LINES LINES MACHTYPE MAIL MAILCHECK MAILPATH MAPFILE MAPFILE OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS POSIXLY_CORRECT POSIXLY_CORRECT PPID PROMPT_COMMAND PS0 PS1 PS2 PS3 PS4 PWD RANDOM READLINE_LINE READLINE_LINE READLINE_POINT READLINE_POINT REPLY SECONDS SHELL SHELL SHELLOPTS SHLVL TIMEFORMAT TIMEOUT TMPDIR TMPDIR UID
syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep head less ls mkdir mv rm rmdir rpm sed sleep sort strip tail
syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
syn keyword bashStatement command compgen
diff --git a/runtime/syntax/shaderslang.vim b/runtime/syntax/shaderslang.vim
new file mode 100644
index 0000000000..1cae202b04
--- /dev/null
+++ b/runtime/syntax/shaderslang.vim
@@ -0,0 +1,360 @@
+" Vim syntax file
+" Language: Slang
+" Maintainer: Austin Shijo <epestr@proton.me>
+" Last Change: 2024 Jan 05
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Read the C syntax to start with
+runtime! syntax/c.vim
+unlet b:current_syntax
+
+" Annotations
+syn match shaderslangAnnotation /<.*;>/
+
+" Attributes
+syn match shaderslangAttribute /^\s*\[maxvertexcount(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[domain(\s*"\(tri\|quad\|isoline\)"\s*)\]/
+syn match shaderslangAttribute /^\s*\[earlydepthstencil\]/
+syn match shaderslangAttribute /^\s*\[instance(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[maxtessfactor(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[numthreads(\s*\w\+\s*,\s*\w\+\s*,\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[outputcontrolpoints(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[outputtopology(\s*"\(point\|line\|triangle_cw\|triangle_ccw\|triangle\)"\s*)\]/
+syn match shaderslangAttribute /^\s*\[partitioning(\s*"\(integer\|fractional_even\|fractional_odd\|pow2\)"\s*)\]/
+syn match shaderslangAttribute /^\s*\[patchconstantfunc(\s*"\(\d\|\w\|_\)\+"\s*)\]/
+syn match shaderslangAttribute /^\s*\[WaveSize(\s*\w\+\(\s*,\s*\w\+\(\s*,\s*\w\+\)\?\)\?\s*)\]/
+syn match shaderslangAttribute /^\s*\[shader(\s*"\(anyhit\|callable\|closesthit\|intersection\|miss\|raygeneration\)"\s*)\]/
+
+syn match shaderslangAttribute /^\s*\[fastopt\]/
+syn match shaderslangAttribute /^\s*\[loop\]/
+syn match shaderslangAttribute /^\s*\[unroll\]/
+syn match shaderslangAttribute /^\s*\[allow_uav_condition\]/
+syn match shaderslangAttribute /^\s*\[branch\]/
+syn match shaderslangAttribute /^\s*\[flatten\]/
+syn match shaderslangAttribute /^\s*\[forcecase\]/
+syn match shaderslangAttribute /^\s*\[call\]/
+syn match shaderslangAttribute /^\s*\[WaveOpsIncludeHelperLanes\]/
+
+syn match shaderslangAttribute /\[raypayload\]/
+
+" Work graph shader target attributes
+syn match shaderslangAttribute /^\s*\[Shader(\s*"\(\d\|\w\|_\)\+"\s*)\]/
+
+" Work graph shader function attributes
+syn match shaderslangAttribute /^\s*\[NodeLaunch(\s*"\(broadcasting\|coalescing\|thread\)"\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeIsProgramEntry\]/
+syn match shaderslangAttribute /^\s*\[NodeLocalRootArgumentsTableIndex(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[NumThreads(\s*\w\+\s*,\s*\w\+\s*,\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeShareInputOf(\s*"\w\+"\(\s*,\s*\w\+\)\?\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeDispatchGrid(\s*\w\+\s*,\s*\w\+\s*,\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeMaxDispatchGrid(\s*\w\+\s*,\s*\w\+\s*,\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeMaxRecursionDepth(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /^\s*\[NodeMaxInputRecordsPerGraphEntryRecord(\s*\w\+\s*,\s*\(true\|false\)\s*)\]/
+
+" Work graph record attributes
+syn match shaderslangAttribute /\[NodeTrackRWInputSharing\]/
+syn match shaderslangAttribute /\[MaxRecords(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /\[NodeID(\s*"\w\+"\(\s*,\s*\w\+\)\?\s*)\]/
+syn match shaderslangAttribute /\[MaxRecordsSharedWith(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /\[AllowSparseNodes\]/
+syn match shaderslangAttribute /\[NodeArraySize(\s*\w\+\s*)\]/
+syn match shaderslangAttribute /\[UnboundedSparseNodes\]/
+
+" Intrinsic functions
+syn keyword shaderslangFunc abs acos acosh asin asinh atan atanh cos cosh exp exp2 floor log log10 log2 round rsqrt sin sincos sinh sqrt tan tanh trunc
+syn keyword shaderslangFunc AllMemoryBarrier AllMemoryBarrierWithGroupSync DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync GroupMemoryBarrier GroupMemoryBarrierWithGroupSync
+syn keyword shaderslangFunc abort clip errorf printf
+syn keyword shaderslangFunc all any countbits faceforward firstbithigh firstbitlow isfinite isinf isnan max min noise pow reversebits sign
+syn keyword shaderslangFunc asdouble asfloat asint asuint D3DCOLORtoUBYTE4 f16tof32 f32tof16
+syn keyword shaderslangFunc ceil clamp degrees fma fmod frac frexp ldexp lerp mad modf radiants saturate smoothstep step
+syn keyword shaderslangFunc cross determinant distance dot dst length lit msad4 mul normalize rcp reflect refract transpose
+syn keyword shaderslangFunc ddx ddx_coarse ddx_fine ddy ddy_coarse ddy_fine fwidth
+syn keyword shaderslangFunc EvaluateAttributeAtCentroid EvaluateAttributeAtSample EvaluateAttributeSnapped
+syn keyword shaderslangFunc GetRenderTargetSampleCount GetRenderTargetSamplePosition
+syn keyword shaderslangFunc InterlockedAdd InterlockedAnd InterlockedCompareExchange InterlockedCompareStore InterlockedExchange InterlockedMax InterlockedMin InterlockedOr InterlockedXor
+syn keyword shaderslangFunc InterlockedCompareStoreFloatBitwise InterlockedCompareExchangeFloatBitwise
+syn keyword shaderslangFunc Process2DQuadTessFactorsAvg Process2DQuadTessFactorsMax Process2DQuadTessFactorsMin ProcessIsolineTessFactors
+syn keyword shaderslangFunc ProcessQuadTessFactorsAvg ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin ProcessTriTessFactorsAvg ProcessTriTessFactorsMax ProcessTriTessFactorsMin
+syn keyword shaderslangFunc tex1D tex1Dbias tex1Dgrad tex1Dlod tex1Dproj
+syn keyword shaderslangFunc tex2D tex2Dbias tex2Dgrad tex2Dlod tex2Dproj
+syn keyword shaderslangFunc tex3D tex3Dbias tex3Dgrad tex3Dlod tex3Dproj
+syn keyword shaderslangFunc texCUBE texCUBEbias texCUBEgrad texCUBElod texCUBEproj
+syn keyword shaderslangFunc WaveIsFirstLane WaveGetLaneCount WaveGetLaneIndex
+syn keyword shaderslangFunc IsHelperLane
+syn keyword shaderslangFunc WaveActiveAnyTrue WaveActiveAllTrue WaveActiveBallot
+syn keyword shaderslangFunc WaveReadLaneFirst WaveReadLaneAt
+syn keyword shaderslangFunc WaveActiveAllEqual WaveActiveAllEqualBool WaveActiveCountBits
+syn keyword shaderslangFunc WaveActiveSum WaveActiveProduct WaveActiveBitAnd WaveActiveBitOr WaveActiveBitXor WaveActiveMin WaveActiveMax
+syn keyword shaderslangFunc WavePrefixCountBits WavePrefixProduct WavePrefixSum
+syn keyword shaderslangFunc QuadReadAcrossX QuadReadAcrossY QuadReadAcrossDiagonal QuadReadLaneAt
+syn keyword shaderslangFunc QuadAny QuadAll
+syn keyword shaderslangFunc WaveMatch WaveMultiPrefixSum WaveMultiPrefixProduct WaveMultiPrefixCountBits WaveMultiPrefixAnd WaveMultiPrefixOr WaveMultiPrefixXor
+syn keyword shaderslangFunc NonUniformResourceIndex
+syn keyword shaderslangFunc DispatchMesh SetMeshOutputCounts
+syn keyword shaderslangFunc dot4add_u8packed dot4add_i8packed dot2add
+
+syn keyword shaderslangFunc RestartStrip
+syn keyword shaderslangFunc CalculateLevelOfDetail CalculateLevelOfDetailUnclamped Gather GetDimensions GetSamplePosition Load Sample SampleBias SampleCmp SampleCmpLevelZero SampleGrad SampleLevel GatherRaw SampleCmpLevel
+syn keyword shaderslangFunc SampleCmpBias SampleCmpGrad
+syn keyword shaderslangFunc WriteSamplerFeedback WriteSamplerFeedbackBias WriteSamplerFeedbackGrad WriteSamplerFeedbackLevel
+syn keyword shaderslangFunc Append Consume DecrementCounter IncrementCounter
+syn keyword shaderslangFunc Load2 Load3 Load4 Store Store2 Store3 Store4
+syn keyword shaderslangFunc GatherRed GatherGreen GatherBlue GatherAlpha GatherCmp GatherCmpRed GatherCmpGreen GatherCmpBlue GatherCmpAlpha
+syn match shaderslangFunc /\.mips\[\d\+\]\[\d\+\]/
+syn match shaderslangFunc /\.sample\[\d\+\]\[\d\+\]/
+
+" Ray intrinsics
+syn keyword shaderslangFunc AcceptHitAndEndSearch CallShader IgnoreHit ReportHit TraceRay
+syn keyword shaderslangFunc DispatchRaysIndex DispatchRaysDimensions
+syn keyword shaderslangFunc WorldRayOrigin WorldRayDirection RayTMin RayTCurrent RayFlags
+syn keyword shaderslangFunc InstanceIndex InstanceID GeometryIndex PrimitiveIndex ObjectRayOrigin ObjectRayDirection ObjectToWorld3x4 ObjectToWorld4x3 WorldToObject3x4 WorldToObject4x3
+syn keyword shaderslangFunc HitKind
+
+" RayQuery intrinsics
+syn keyword shaderslangFunc TraceRayInline Proceed Abort CommittedStatus
+syn keyword shaderslangFunc CandidateType CandidateProceduralPrimitiveNonOpaque CandidateTriangleRayT CandidateInstanceIndex CandidateInstanceID CandidateInstanceContributionToHitGroupIndex CandidateGeometryIndex
+syn keyword shaderslangFunc CandidatePrimitiveIndex CandidateObjectRayOrigin CandidateObjectRayDirection CandidateObjectToWorld3x4 CandidateObjectToWorld4x3 CandidateWorldToObject3x4 CandidateWorldToObject4x3
+syn keyword shaderslangFunc CommitNonOpaqueTriangleHit CommitProceduralPrimitiveHit CommittedStatus CommittedRayT CommittedInstanceIndex CommittedInstanceID CommittedInstanceContributionToHitGroupIndex
+syn keyword shaderslangFunc CommittedGeometryIndex CommittedPrimitiveIndex CommittedObjectRayOrigin CommittedObjectRayDirection CommittedObjectToWorld3x4 CommittedObjectToWorld4x3 CommittedWorldToObject3x4
+syn keyword shaderslangFunc CommittedWorldToObject4x3 CandidateTriangleBarycentrics CandidateTriangleFrontFace CommittedTriangleBarycentrics CommittedTriangleFrontFace
+
+" Pack/unpack math intrinsics
+syn keyword shaderslangFunc unpack_s8s16 unpack_u8u16 unpack_s8s32 unpack_u8u32
+syn keyword shaderslangFunc pack_u8 pack_s8 pack_clamp_u8 pack_clamp_s8
+
+" Work graph object methods
+syn keyword shaderslangFunc Get FinishedCrossGroupSharing Count GetThreadNodeOutputRecords GetGroupNodeOutputRecords IsValid GroupIncrementOutputCount ThreadIncrementOutputCount OutputComplete
+
+" Work graph free intrinsics
+syn keyword shaderslangFunc GetRemainingRecursionLevels Barrier
+
+" Layout Qualifiers
+syn keyword shaderslangLayoutQual const row_major column_major
+syn keyword shaderslangLayoutQual point line triangle lineadj triangleadj
+syn keyword shaderslangLayoutQual InputPatch OutputPatch
+syn match shaderslangLayoutQual /PointStream<\s*\w\+\s*>/
+syn match shaderslangLayoutQual /LineStream<\s*\w\+\s*>/
+syn match shaderslangLayoutQual /TriangleStream<\s*\w\+\s*>/
+
+" User defined Semantics
+syn match shaderslangSemantic /:\s*[A-Z]\w*/
+syn match shaderslangSemantic /:\s*packoffset(\s*c\d\+\(\.[xyzw]\)\?\s*)/ " packoffset
+syn match shaderslangSemantic /:\s*register(\s*\(r\|x\|v\|t\|s\|cb\|icb\|b\|c\|u\)\d\+\s*)/ " register
+syn match shaderslangSemantic /:\s*read(\s*\(\(anyhit\|closesthit\|miss\|caller\)\s*,\s*\)*\(anyhit\|closesthit\|miss\|caller\)\?\s*)/ " read
+syn match shaderslangSemantic /:\s*write(\s*\(\(anyhit\|closesthit\|miss\|caller\)\s*,\s*\)*\(anyhit\|closesthit\|miss\|caller\)\?\s*)/ " write
+
+" System-Value Semantics
+" Vertex Shader
+syn match shaderslangSemantic /SV_ClipDistance\d\+/
+syn match shaderslangSemantic /SV_CullDistance\d\+/
+syn keyword shaderslangSemantic SV_Position SV_InstanceID SV_PrimitiveID SV_VertexID
+syn keyword shaderslangSemantic SV_StartVertexLocation SV_StartInstanceLocation
+" Tessellation pipeline
+syn keyword shaderslangSemantic SV_DomainLocation SV_InsideTessFactor SV_OutputControlPointID SV_TessFactor
+" Geometry Shader
+syn keyword shaderslangSemantic SV_GSInstanceID SV_RenderTargetArrayIndex
+" Pixel Shader - MSAA
+syn keyword shaderslangSemantic SV_Coverage SV_Depth SV_IsFrontFace SV_SampleIndex
+syn match shaderslangSemantic /SV_Target[0-7]/
+syn keyword shaderslangSemantic SV_ShadingRate SV_ViewID
+syn match shaderslangSemantic /SV_Barycentrics[0-1]/
+" Compute Shader
+syn keyword shaderslangSemantic SV_DispatchThreadID SV_GroupID SV_GroupIndex SV_GroupThreadID
+" Mesh shading pipeline
+syn keyword shaderslangSemantic SV_CullPrimitive
+" Work graph record system values
+syn keyword shaderslangSemantic SV_DispatchGrid
+
+" slang structures
+syn keyword shaderslangStructure cbuffer
+
+" Shader profiles
+" Cg profiles
+syn keyword shaderslangProfile arbfp1 arbvp1 fp20 vp20 fp30 vp30 ps_1_1 ps_1_2 ps_1_3
+" Shader Model 1
+syn keyword shaderslangProfile vs_1_1
+" Shader Model 2
+syn keyword shaderslangProfile ps_2_0 ps_2_x vs_2_0 vs_2_x
+" Shader Model 3
+syn keyword shaderslangProfile ps_3_0 vs_3_0
+" Shader Model 4
+syn keyword shaderslangProfile gs_4_0 ps_4_0 vs_4_0 gs_4_1 ps_4_1 vs_4_1
+" Shader Model 5
+syn keyword shaderslangProfile cs_4_0 cs_4_1 cs_5_0 ds_5_0 gs_5_0 hs_5_0 ps_5_0 vs_5_0
+" Shader Model 6
+syn keyword shaderslangProfile cs_6_0 ds_6_0 gs_6_0 hs_6_0 ps_6_0 vs_6_0 lib_6_0
+
+" Swizzling
+syn match shaderslangSwizzle /\.[xyzw]\{1,4\}\>/
+syn match shaderslangSwizzle /\.[rgba]\{1,4\}\>/
+syn match shaderslangSwizzle /\.\(_m[0-3]\{2}\)\{1,4\}/
+syn match shaderslangSwizzle /\.\(_[1-4]\{2}\)\{1,4\}/
+
+" Other Statements
+syn keyword shaderslangStatement discard
+
+" Storage class
+syn match shaderslangStorageClass /\<in\(\s+pipeline\)\?\>/
+syn match shaderslangStorageClass /\<out\(\s\+indices\|\s\+vertices\|\s\+primitives\)\?\>/
+syn keyword shaderslangStorageClass inout
+syn keyword shaderslangStorageClass extern nointerpolation precise shared groupshared static uniform volatile
+syn keyword shaderslangStorageClass snorm unorm
+syn keyword shaderslangStorageClass linear centroid nointerpolation noperspective sample
+syn keyword shaderslangStorageClass globallycoherent
+
+" Types
+" Buffer types
+syn keyword shaderslangType ConstantBuffer Buffer ByteAddressBuffer ConsumeStructuredBuffer StructuredBuffer
+syn keyword shaderslangType AppendStructuredBuffer RWBuffer RWByteAddressBuffer RWStructuredBuffer
+syn keyword shaderslangType RasterizerOrderedBuffer RasterizerOrderedByteAddressBuffer RasterizerOrderedStructuredBuffer
+
+" Scalar types
+syn keyword shaderslangType bool int uint dword half float double
+syn keyword shaderslangType min16float min10float min16int min12int min16uint
+syn keyword shaderslangType float16_t float32_t float64_t
+
+" Vector types
+syn match shaderslangType /vector<\s*\w\+,\s*[1-4]\s*>/
+syn keyword shaderslangType bool1 bool2 bool3 bool4
+syn keyword shaderslangType int1 int2 int3 int4
+syn keyword shaderslangType uint1 uint2 uint3 uint4
+syn keyword shaderslangType dword1 dword2 dword3 dword4
+syn keyword shaderslangType half1 half2 half3 half4
+syn keyword shaderslangType float1 float2 float3 float4
+syn keyword shaderslangType double1 double2 double3 double4
+syn keyword shaderslangType min16float1 min16float2 min16float3 min16float4
+syn keyword shaderslangType min10float1 min10float2 min10float3 min10float4
+syn keyword shaderslangType min16int1 min16int2 min16int3 min16int4
+syn keyword shaderslangType min12int1 min12int2 min12int3 min12int4
+syn keyword shaderslangType min16uint1 min16uint2 min16uint3 min16uint4
+syn keyword shaderslangType float16_t1 float16_t2 float16_t3 float16_t4
+syn keyword shaderslangType float32_t1 float32_t2 float32_t3 float32_t4
+syn keyword shaderslangType float64_t1 float64_t2 float64_t3 float64_t4
+syn keyword shaderslangType int16_t1 int16_t2 int16_t3 int16_t4
+syn keyword shaderslangType int32_t1 int32_t2 int32_t3 int32_t4
+syn keyword shaderslangType int64_t1 int64_t2 int64_t3 int64_t4
+syn keyword shaderslangType uint16_t1 uint16_t2 uint16_t3 uint16_t4
+syn keyword shaderslangType uint32_t1 uint32_t2 uint32_t3 uint32_t4
+syn keyword shaderslangType uint64_t1 uint64_t2 uint64_t3 uint64_t4
+
+" Packed types
+syn keyword shaderslangType uint8_t4_packed int8_t4_packed
+
+" Matrix types
+syn match shaderslangType /matrix<\s*\w\+\s*,\s*[1-4]\s*,\s*[1-4]\s*>/
+syn keyword shaderslangType bool1x1 bool2x1 bool3x1 bool4x1 bool1x2 bool2x2 bool3x2 bool4x2 bool1x3 bool2x3 bool3x3 bool4x3 bool1x4 bool2x4 bool3x4 bool4x4
+syn keyword shaderslangType int1x1 int2x1 int3x1 int4x1 int1x2 int2x2 int3x2 int4x2 int1x3 int2x3 int3x3 int4x3 int1x4 int2x4 int3x4 int4x4
+syn keyword shaderslangType uint1x1 uint2x1 uint3x1 uint4x1 uint1x2 uint2x2 uint3x2 uint4x2 uint1x3 uint2x3 uint3x3 uint4x3 uint1x4 uint2x4 uint3x4 uint4x4
+syn keyword shaderslangType dword1x1 dword2x1 dword3x1 dword4x1 dword1x2 dword2x2 dword3x2 dword4x2 dword1x3 dword2x3 dword3x3 dword4x3 dword1x4 dword2x4 dword3x4 dword4x4
+syn keyword shaderslangType half1x1 half2x1 half3x1 half4x1 half1x2 half2x2 half3x2 half4x2 half1x3 half2x3 half3x3 half4x3 half1x4 half2x4 half3x4 half4x4
+syn keyword shaderslangType float1x1 float2x1 float3x1 float4x1 float1x2 float2x2 float3x2 float4x2 float1x3 float2x3 float3x3 float4x3 float1x4 float2x4 float3x4 float4x4
+syn keyword shaderslangType double1x1 double2x1 double3x1 double4x1 double1x2 double2x2 double3x2 double4x2 double1x3 double2x3 double3x3 double4x3 double1x4 double2x4 double3x4 double4x4
+syn keyword shaderslangType min16float1x1 min16float2x1 min16float3x1 min16float4x1 min16float1x2 min16float2x2 min16float3x2 min16float4x2 min16float1x3 min16float2x3 min16float3x3 min16float4x3 min16float1x4 min16float2x4 min16float3x4 min16float4x4
+syn keyword shaderslangType min10float1x1 min10float2x1 min10float3x1 min10float4x1 min10float1x2 min10float2x2 min10float3x2 min10float4x2 min10float1x3 min10float2x3 min10float3x3 min10float4x3 min10float1x4 min10float2x4 min10float3x4 min10float4x4
+syn keyword shaderslangType min16int1x1 min16int2x1 min16int3x1 min16int4x1 min16int1x2 min16int2x2 min16int3x2 min16int4x2 min16int1x3 min16int2x3 min16int3x3 min16int4x3 min16int1x4 min16int2x4 min16int3x4 min16int4x4
+syn keyword shaderslangType min12int1x1 min12int2x1 min12int3x1 min12int4x1 min12int1x2 min12int2x2 min12int3x2 min12int4x2 min12int1x3 min12int2x3 min12int3x3 min12int4x3 min12int1x4 min12int2x4 min12int3x4 min12int4x4
+syn keyword shaderslangType min16uint1x1 min16uint2x1 min16uint3x1 min16uint4x1 min16uint1x2 min16uint2x2 min16uint3x2 min16uint4x2 min16uint1x3 min16uint2x3 min16uint3x3 min16uint4x3 min16uint1x4 min16uint2x4 min16uint3x4 min16uint4x4
+syn keyword shaderslangType float16_t1x1 float16_t2x1 float16_t3x1 float16_t4x1 float16_t1x2 float16_t2x2 float16_t3x2 float16_t4x2 float16_t1x3 float16_t2x3 float16_t3x3 float16_t4x3 float16_t1x4 float16_t2x4 float16_t3x4 float16_t4x4
+syn keyword shaderslangType float32_t1x1 float32_t2x1 float32_t3x1 float32_t4x1 float32_t1x2 float32_t2x2 float32_t3x2 float32_t4x2 float32_t1x3 float32_t2x3 float32_t3x3 float32_t4x3 float32_t1x4 float32_t2x4 float32_t3x4 float32_t4x4
+syn keyword shaderslangType float64_t1x1 float64_t2x1 float64_t3x1 float64_t4x1 float64_t1x2 float64_t2x2 float64_t3x2 float64_t4x2 float64_t1x3 float64_t2x3 float64_t3x3 float64_t4x3 float64_t1x4 float64_t2x4 float64_t3x4 float64_t4x4
+syn keyword shaderslangType int16_t1x1 int16_t2x1 int16_t3x1 int16_t4x1 int16_t1x2 int16_t2x2 int16_t3x2 int16_t4x2 int16_t1x3 int16_t2x3 int16_t3x3 int16_t4x3 int16_t1x4 int16_t2x4 int16_t3x4 int16_t4x4
+syn keyword shaderslangType int32_t1x1 int32_t2x1 int32_t3x1 int32_t4x1 int32_t1x2 int32_t2x2 int32_t3x2 int32_t4x2 int32_t1x3 int32_t2x3 int32_t3x3 int32_t4x3 int32_t1x4 int32_t2x4 int32_t3x4 int32_t4x4
+syn keyword shaderslangType int64_t1x1 int64_t2x1 int64_t3x1 int64_t4x1 int64_t1x2 int64_t2x2 int64_t3x2 int64_t4x2 int64_t1x3 int64_t2x3 int64_t3x3 int64_t4x3 int64_t1x4 int64_t2x4 int64_t3x4 int64_t4x4
+syn keyword shaderslangType uint16_t1x1 uint16_t2x1 uint16_t3x1 uint16_t4x1 uint16_t1x2 uint16_t2x2 uint16_t3x2 uint16_t4x2 uint16_t1x3 uint16_t2x3 uint16_t3x3 uint16_t4x3 uint16_t1x4 uint16_t2x4 uint16_t3x4 uint16_t4x4
+syn keyword shaderslangType uint32_t1x1 uint32_t2x1 uint32_t3x1 uint32_t4x1 uint32_t1x2 uint32_t2x2 uint32_t3x2 uint32_t4x2 uint32_t1x3 uint32_t2x3 uint32_t3x3 uint32_t4x3 uint32_t1x4 uint32_t2x4 uint32_t3x4 uint32_t4x4
+syn keyword shaderslangType uint64_t1x1 uint64_t2x1 uint64_t3x1 uint64_t4x1 uint64_t1x2 uint64_t2x2 uint64_t3x2 uint64_t4x2 uint64_t1x3 uint64_t2x3 uint64_t3x3 uint64_t4x3 uint64_t1x4 uint64_t2x4 uint64_t3x4 uint64_t4x4
+
+" Sampler types
+syn keyword shaderslangType SamplerState SamplerComparisonState
+syn keyword shaderslangType sampler sampler1D sampler2D sampler3D samplerCUBE sampler_state
+
+" Texture types
+syn keyword shaderslangType Texture1D Texture1DArray Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D TextureCube TextureCubeArray
+syn keyword shaderslangType RWTexture1D RWTexture2D RWTexture2DArray RWTexture3D RWTextureCubeArray RWTexture2DMS RWTexture2DMSArray
+syn keyword shaderslangType FeedbackTexture2D FeedbackTexture2DArray
+syn keyword shaderslangType RasterizerOrderedTexture1D RasterizerOrderedTexture1DArray RasterizerOrderedTexture2D RasterizerOrderedTexture2DArray RasterizerOrderedTexture3D
+syn keyword shaderslangTypeDeprec texture texture1D texture2D texture3D
+
+" Raytracing types
+syn keyword shaderslangType RaytracingAccelerationStructure RayDesc RayQuery BuiltInTriangleIntersectionAttributes
+
+" Work graph input record objects
+syn keyword shaderslangType DispatchNodeInputRecord RWDispatchNodeInputRecord GroupNodeInputRecords RWGroupNodeInputRecords ThreadNodeInputRecord RWThreadNodeInputRecord EmptyNodeInput
+
+" Work graph output node objects
+syn keyword shaderslangType NodeOutput NodeOutputArray EmptyNodeOutput EmptyNodeOutputArray
+
+" Work graph output record objects
+syn keyword shaderslangType ThreadNodeOutputRecords GroupNodeOutputRecords
+
+" State Groups args
+syn case ignore " This section case insensitive
+
+" Blend state group
+syn keyword shaderslangStateGroupArg AlphaToCoverageEnable BlendEnable SrcBlend DestBlend BlendOp SrcBlendAlpha DestBlendAlpha BlendOpAlpha RenderTargetWriteMask
+syn keyword shaderslangStateGroupVal ZERO ONE SRC_COLOR INV_SRC_COLOR SRC_ALPHA INV_SRC_ALPHA DEST_ALPHA INV_DEST_ALPHA DEST_COLOR INV_DEST_COLOR SRC_ALPHA_SAT BLEND_FACTOR INV_BLEND_FACTOR SRC1_COLOR INV_SRC1_COLOR SRC1_ALPHA INV_SRC1_ALPHA
+syn keyword shaderslangStateGroupVal ADD SUBSTRACT REV_SUBSTRACT MIN MAX
+
+" Rasterizer state group
+syn keyword shaderslangStateGroupArg FillMode CullMode FrontCounterClockwise DepthBias DepthBiasClamp SlopeScaledDepthBias ZClipEnable DepthClipEnable ScissorEnable MultisampleEnable AntialiasedLineEnable
+syn keyword shaderslangStateGroupVal SOLID WIREFRAME
+syn keyword shaderslangStateGroupVal NONE FRONT BACK
+
+" Sampler state group
+syn keyword shaderslangStateGroupArg Filter AddressU AddressV AddressW MipLODBias MaxAnisotropy ComparisonFunc BorderColor MinLOD MaxLOD ComparisonFilter
+syn keyword shaderslangStateGroupVal MIN_MAG_MIP_POINT MIN_MAG_POINT_MIP_LINEAR MIN_POINT_MAG_LINEAR_MIP_POINT MIN_POINT_MAG_MIP_LINEAR MIN_LINEAR_MAG_MIP_POINT MIN_LINEAR_MAG_POINT_MIP_LINEAR MIN_MAG_LINEAR_MIP_POINT MIN_MAG_MIP_LINEAR ANISOTROPIC
+syn keyword shaderslangStateGroupVal COMPARISON_MIN_MAG_MIP_POINT COMPARISON_MIN_MAG_POINT_MIP_LINEAR COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT COMPARISON_MIN_POINT_MAG_MIP_LINEAR COMPARISON_MIN_LINEAR_MAG_MIP_POINT
+syn keyword shaderslangStateGroupVal COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR COMPARISON_MIN_MAG_LINEAR_MIP_POINT COMPARISON_MIN_MAG_MIP_LINEAR COMPARISON_ANISOTROPIC
+syn keyword shaderslangStateGroupVal COMPARISON_NEVER COMPARISON_LESS COMPARISON_EQUAL COMPARISON_LESS_EQUAL COMPARISON_GREATER COMPARISON_NOT_EQUAL COMPARISON_GREATER_EQUAL COMPARISON_ALWAYS
+syn keyword shaderslangStateGroupVal WRAP MIRROR CLAMP BORDER MIRROR_ONCE
+syn keyword shaderslangStateGroupVal SAMPLER_FEEDBACK_MIN_MIP SAMPLER_FEEDBACK_MIP_REGION_USED
+
+" Ray flags
+syn keyword shaderslangStateGroupVal RAY_FLAG_NONE RAY_FLAG_FORCE_OPAQUE RAY_FLAG_FORCE_NON_OPAQUE RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH RAY_FLAG_SKIP_CLOSEST_HIT_SHADER
+syn keyword shaderslangStateGroupVal RAY_FLAG_CULL_BACK_FACING_TRIANGLES RAY_FLAG_CULL_FRONT_FACING_TRIANGLES RAY_FLAG_CULL_OPAQUE RAY_FLAG_CULL_NON_OPAQUE
+syn keyword shaderslangStateGroupVal RAY_FLAG_SKIP_TRIANGLES RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES
+
+" HitKind enum
+syn keyword shaderslangStateGroupVal HIT_KIND_TRIANGLE_FRONT_FACE HIT_KIND_TRIANGLE_BACK_FACE
+
+" RayQuery enums
+syn keyword shaderslangStateGroupVal COMMITTED_NOTHING COMMITTED_TRIANGLE_HIT COMMITTED_PROCEDURAL_PRIMITIVE_HIT
+syn keyword shaderslangStateGroupVal CANDIDATE_NON_OPAQUE_TRIANGLE CANDIDATE_PROCEDURAL_PRIMITIVE
+
+" Heap objects
+syn keyword shaderslangStateGroupVal ResourceDescriptorHeap SamplerDescriptorHeap
+
+" Work graph constants
+syn keyword shaderslangStateGroupVal UAV_MEMORY GROUP_SHARED_MEMORY NODE_INPUT_MEMORY NODE_OUTPUT_MEMORY ALL_MEMORY GROUP_SYNC GROUP_SCOPE DEVICE_SCOPE
+
+syn case match " Case sensitive from now on
+
+" Effect files declarations and functions
+" Effect groups, techniques passes
+syn keyword shaderslangEffectGroup fxgroup technique11 pass
+" Effect functions
+syn keyword shaderslangEffectFunc SetBlendState SetDepthStencilState SetRasterizerState SetVertexShader SetHullShader SetDomainShader SetGeometryShader SetPixelShader SetComputeShader CompileShader ConstructGSWithSO SetRenderTargets
+
+" Default highlighting
+hi def link shaderslangProfile shaderslangStatement
+hi def link shaderslangStateGroupArg shaderslangStatement
+hi def link shaderslangStateGroupVal Number
+hi def link shaderslangStatement Statement
+hi def link shaderslangType Type
+hi def link shaderslangTypeDeprec WarningMsg
+hi def link shaderslangStorageClass StorageClass
+hi def link shaderslangSemantic PreProc
+hi def link shaderslangFunc shaderslangStatement
+hi def link shaderslangLayoutQual shaderslangFunc
+hi def link shaderslangAnnotation PreProc
+hi def link shaderslangStructure Structure
+hi def link shaderslangSwizzle SpecialChar
+hi def link shaderslangAttribute Statement
+
+hi def link shaderslangEffectGroup Type
+hi def link shaderslangEffectFunc Statement
+
+let b:current_syntax = "shaderslang"
diff --git a/runtime/syntax/tiasm.vim b/runtime/syntax/tiasm.vim
new file mode 100644
index 0000000000..bdadc4a0a7
--- /dev/null
+++ b/runtime/syntax/tiasm.vim
@@ -0,0 +1,102 @@
+" Vim syntax file
+" Language: TI linear assembly language
+" Document: https://downloads.ti.com/docs/esd/SPRUI03B/#SPRUI03B_HTML/assembler-description.html
+" Maintainer: Wu, Zhenyu <wuzhenyu@ustc.edu>
+" Last Change: 2025 Jan 08
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn case ignore
+
+" storage types
+syn match tiasmType "\.bits"
+syn match tiasmType "\.byte"
+syn match tiasmType "\.char"
+syn match tiasmType "\.cstring"
+syn match tiasmType "\.double"
+syn match tiasmType "\.field"
+syn match tiasmType "\.float"
+syn match tiasmType "\.half"
+syn match tiasmType "\.int"
+syn match tiasmType "\.long"
+syn match tiasmType "\.short"
+syn match tiasmType "\.string"
+syn match tiasmType "\.ubyte"
+syn match tiasmType "\.uchar"
+syn match tiasmType "\.uhalf"
+syn match tiasmType "\.uint"
+syn match tiasmType "\.ulong"
+syn match tiasmType "\.ushort"
+syn match tiasmType "\.uword"
+syn match tiasmType "\.word"
+
+syn match tiasmIdentifier "[a-z_][a-z0-9_]*"
+
+syn match tiasmDecimal "\<[1-9]\d*\>" display
+syn match tiasmOctal "\<0[0-7][0-7]\+\>\|\<[0-7]\+[oO]\>" display
+syn match tiasmHexadecimal "\<0[xX][0-9a-fA-F]\+\>\|\<[0-9][0-9a-fA-F]*[hH]\>" display
+syn match tiasmBinary "\<0[bB][0-1]\+\>\|\<[01]\+[bB]\>" display
+
+syn match tiasmFloat "\<\d\+\.\d*\%(e[+-]\=\d\+\)\=\>" display
+syn match tiasmFloat "\<\d\%(e[+-]\=\d\+\)\>" display
+
+syn match tiasmCharacter "'.'\|''\|'[^']'"
+
+syn region tiasmString start="\"" end="\"" skip="\"\""
+
+syn match tiasmFunction "\$[a-zA-Z_][a-zA-Z_0-9]*\ze("
+
+syn keyword tiasmTodo contained TODO FIXME XXX NOTE
+syn region tiasmComment start=";" end="$" keepend contains=tiasmTodo,@Spell
+syn match tiasmComment "^[*!].*" contains=tiasmTodo,@Spell
+syn match tiasmLabel "^[^ *!;][^ :]*"
+
+syn match tiasmInclude "\.include"
+syn match tiasmCond "\.if"
+syn match tiasmCond "\.else"
+syn match tiasmCond "\.endif"
+syn match tiasmMacro "\.macro"
+syn match tiasmMacro "\.endm"
+
+syn match tiasmDirective "\.[A-Za-z][0-9A-Za-z-_]*"
+
+syn case match
+
+hi def link tiasmLabel Label
+hi def link tiasmComment Comment
+hi def link tiasmTodo Todo
+hi def link tiasmDirective Statement
+
+hi def link tiasmInclude Include
+hi def link tiasmCond PreCondit
+hi def link tiasmMacro Macro
+
+if exists('g:tiasm_legacy_syntax_groups')
+ hi def link hexNumber Number
+ hi def link decNumber Number
+ hi def link octNumber Number
+ hi def link binNumber Number
+ hi def link tiasmHexadecimal hexNumber
+ hi def link tiasmDecimal decNumber
+ hi def link tiasmOctal octNumber
+ hi def link tiasmBinary binNumber
+else
+ hi def link tiasmHexadecimal Number
+ hi def link tiasmDecimal Number
+ hi def link tiasmOctal Number
+ hi def link tiasmBinary Number
+endif
+hi def link tiasmFloat Float
+
+hi def link tiasmString String
+hi def link tiasmStringEscape Special
+hi def link tiasmCharacter Character
+hi def link tiasmCharacterEscape Special
+
+hi def link tiasmIdentifier Identifier
+hi def link tiasmType Type
+hi def link tiasmFunction Function
+
+let b:current_syntax = "lineartiasm"
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 361bf6369d..12798201e2 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -60,7 +60,7 @@ syn case ignore
syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo
" Default highlighting groups {{{2
-syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuMatch PmenuMatchSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen StatusLineTerm StatusLineTermNC CursorIM LineNrAbove LineNrBelow
+syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuMatch PmenuMatchSel PmenuExtra PmenuExtraSel ComplMatchIns Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen StatusLineTerm StatusLineTermNC CursorIM LineNrAbove LineNrBelow
syn match vimHLGroup contained "\<Conceal\>"
syn keyword vimOnlyHLGroup contained Menu Scrollbar ToolbarButton ToolbarLine Tooltip VisualNOS
syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor VisualNC Whitespace WinBar WinBarNC WinSeparator
@@ -196,9 +196,9 @@ syn case match
" All vimCommands are contained by vimIsCommand. {{{2
syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimCall,vimCatch,vimConst,vimDef,vimDefFold,vimDelcommand,@vimEcho,vimEnddef,vimEndfunction,vimExecute,vimIsCommand,vimExtCmd,vimFor,vimFunction,vimFuncFold,vimGlobal,vimHighlight,vimLet,vimLoadkeymap,vimMap,vimMark,vimMatch,vimNotFunc,vimNormal,vimSet,vimSleep,vimSyntax,vimThrow,vimUnlet,vimUnmap,vimUserCmd,vimMenu,vimMenutranslate,@vim9CmdList
-syn cluster vim9CmdList contains=vim9Class,vim9Const,vim9Enum,vim9Export,vim9Final,vim9For,vim9Interface,vim9Type,vim9Var
+syn cluster vim9CmdList contains=vim9Abstract,vim9Class,vim9Const,vim9Enum,vim9Export,vim9Final,vim9For,vim9Interface,vim9Type,vim9Var
syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1
-syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
+syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" nextgroup=vimBang contains=vimCommand
syn match vimBang contained "!"
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
@@ -207,7 +207,6 @@ syn match vimVar "\s\zs&t_\S[a-zA-Z0-9]\>"
syn match vimVar "\s\zs&t_k;"
syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
syn keyword vimCommand contained in
-syn match vimBang contained "!"
syn cluster vimExprList contains=vimEnvvar,vimFunc,vimNumber,vimOper,vimOperParen,vimLetRegister,vimString,vimVar,@vim9ExprList
syn cluster vim9ExprList contains=vim9Boolean,vim9Null
@@ -275,7 +274,8 @@ syn keyword vimAugroupKey contained aug[roup] skipwhite nextgroup=vimAugroupBan
" Operators: {{{2
" =========
syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimRegister,@vimContinue,vim9Comment,vimVar,vimBoolean,vimNull
-syn match vimOper "||\|&&\|[-+*/%.!]" skipwhite nextgroup=vimString,vimSpecFile
+syn match vimOper "\a\@<!!" skipwhite nextgroup=vimString,vimSpecFile
+syn match vimOper "||\|&&\|[-+*/%.]" skipwhite nextgroup=vimString,vimSpecFile
syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile
syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile
syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=@vimOperGroup
@@ -553,8 +553,8 @@ syn region vimPatSepZone oneline contained matchgroup=vimPatSepZ start="\\%\
syn region vimPatRegion contained transparent matchgroup=vimPatSepR start="\\[z%]\=(" end="\\)" contains=@vimSubstList oneline
syn match vimNotPatSep contained "\\\\"
syn cluster vimStringGroup contains=vimEscape,vimEscapeBrace,vimPatSep,vimNotPatSep,vimPatSepErr,vimPatSepZone,@Spell
-syn region vimString oneline keepend start=+[^a-zA-Z>!\\@]"+lc=1 skip=+\\\\\|\\"+ matchgroup=vimStringEnd end=+"+ contains=@vimStringGroup extend
-syn region vimString oneline keepend start=+[^a-zA-Z>!\\@]'+lc=1 end=+'+ extend
+syn region vimString oneline keepend start=+[^a-zA-Z>\\@]"+lc=1 skip=+\\\\\|\\"+ matchgroup=vimStringEnd end=+"+ contains=@vimStringGroup extend
+syn region vimString oneline keepend start=+[^a-zA-Z>\\@]'+lc=1 end=+'+ 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 +\(\\\\\|.\)\{-}[^\\]"+
@@ -678,10 +678,12 @@ syn keyword vimAbb abc[lear] cabc[lear] iabc[lear] skipwhite nextgroup=vimMapMod
" Autocmd: {{{2
" =======
-syn match vimAutoEventList contained "\(!\s\+\)\=\(\a\+,\)*\a\+" contains=vimAutoEvent,nvimAutoEvent nextgroup=vimAutoCmdSpace
+syn match vimAutoCmdBang contained "\a\@1<=!" skipwhite nextgroup=vimAutoEventList
+syn match vimAutoEventList contained "\%(\a\+,\)*\a\+" contains=vimAutoEvent,nvimAutoEvent nextgroup=vimAutoCmdSpace
syn match vimAutoCmdSpace contained "\s\+" nextgroup=vimAutoCmdSfxList
syn match vimAutoCmdSfxList contained "\S*" skipwhite nextgroup=vimAutoCmdMod,vimAutoCmdBlock
-syn keyword vimAutoCmd au[tocmd] do[autocmd] doautoa[ll] skipwhite nextgroup=vimAutoEventList
+syn keyword vimAutoCmd au[tocmd] skipwhite nextgroup=vimAutoCmdBang,vimAutoEventList
+syn keyword vimAutoCmd do[autocmd] doautoa[ll] skipwhite nextgroup=vimAutoEventList
syn match vimAutoCmdMod "\(++\)\=\(once\|nested\)" skipwhite nextgroup=vimAutoCmdBlock
syn region vimAutoCmdBlock contained matchgroup=vimSep start="{" end="}" contains=@vimDefBodyList
@@ -1275,6 +1277,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimAugroupError vimError
hi def link vimAugroupKey vimCommand
hi def link vimAutoCmd vimCommand
+ hi def link vimAutoCmdBang vimBang
hi def link vimAutoEvent Type
hi def link vimAutoCmdMod Special
hi def link vimBang vimOper
diff --git a/runtime/syntax/xf86conf.vim b/runtime/syntax/xf86conf.vim
index e8162f3a35..0f4e5036ff 100644
--- a/runtime/syntax/xf86conf.vim
+++ b/runtime/syntax/xf86conf.vim
@@ -1,9 +1,9 @@
" Vim syntax file
" Language: XF86Config (XFree86 configuration file)
+" Maintainer: This runtime file is looking for a new maintainer.
+" Last Change: 2025 Jan 06 by Jan-Arvid Harrach (#16397)
" Former Maintainer: David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
" Last Change By David: 2010 Nov 01
-" Last Change: 2023 Jan 23
-" Required Vim Version: 6.0
"
" Options: let xf86conf_xfree86_version = 3 or 4
" to force XFree86 3.x or 4.x XF86Config syntax
@@ -58,7 +58,7 @@ syn match xf86confModeLineValue "\"[^\"]\+\"\(\_s\+[0-9.]\+\)\{9}" nextgroup=xf8
" Sections and subsections
if b:xf86conf_xfree86_version >= 4
- syn region xf86confSection matchgroup=xf86confSectionDelim start="^\s*Section\s\+\"\(Files\|Server[_ ]*Flags\|Input[_ ]*Device\|Device\|Video[_ ]*Adaptor\|Server[_ ]*Layout\|DRI\|Extensions\|Vendor\|Keyboard\|Pointer\|InputClass\)\"" end="^\s*EndSection\>" skip="#.*$\|\"[^\"]*\"" contains=xf86confComment,xf86confOption,xf86confKeyword,xf86confSectionError
+ syn region xf86confSection matchgroup=xf86confSectionDelim start="^\s*Section\s\+\"\(Files\|Server[_ ]*Flags\|Input[_ ]*Device\|Device\|Video[_ ]*Adaptor\|Server[_ ]*Layout\|DRI\|Extensions\|Vendor\|Keyboard\|Pointer\|InputClass\|OutputClass\)\"" end="^\s*EndSection\>" skip="#.*$\|\"[^\"]*\"" contains=xf86confComment,xf86confOption,xf86confKeyword,xf86confSectionError
syn region xf86confSectionModule matchgroup=xf86confSectionDelim start="^\s*Section\s\+\"Module\"" end="^\s*EndSection\>" skip="#.*$\|\"[^\"]*\"" contains=xf86confSubsectionAny,xf86confComment,xf86confOption,xf86confKeyword
syn region xf86confSectionMonitor matchgroup=xf86confSectionDelim start="^\s*Section\s\+\"Monitor\"" end="^\s*EndSection\>" skip="#.*$\|\"[^\"]*\"" contains=xf86confSubsectionMode,xf86confModeLine,xf86confComment,xf86confOption,xf86confKeyword
syn region xf86confSectionModes matchgroup=xf86confSectionDelim start="^\s*Section\s\+\"Modes\"" end="^\s*EndSection\>" skip="#.*$\|\"[^\"]*\"" contains=xf86confSubsectionMode,xf86confModeLine,xf86confComment
@@ -162,7 +162,7 @@ syn match xf86confSync "\(\s\+[+-][CHV]_*Sync\)\+" contained
" Synchronization
if b:xf86conf_xfree86_version >= 4
- syn sync match xf86confSyncSection grouphere xf86confSection "^\s*Section\s\+\"\(Files\|Server[_ ]*Flags\|Input[_ ]*Device\|Device\|Video[_ ]*Adaptor\|Server[_ ]*Layout\|DRI\|Extensions\|Vendor\|Keyboard\|Pointer\|InputClass\)\""
+ syn sync match xf86confSyncSection grouphere xf86confSection "^\s*Section\s\+\"\(Files\|Server[_ ]*Flags\|Input[_ ]*Device\|Device\|Video[_ ]*Adaptor\|Server[_ ]*Layout\|DRI\|Extensions\|Vendor\|Keyboard\|Pointer\|InputClass\|OutputClass\)\""
syn sync match xf86confSyncSectionModule grouphere xf86confSectionModule "^\s*Section\s\+\"Module\""
syn sync match xf86confSyncSectionModes groupthere xf86confSectionModes "^\s*Section\s\+\"Modes\""
else
diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim
index 084f8cdb41..04b39aeac0 100644
--- a/runtime/syntax/zsh.vim
+++ b/runtime/syntax/zsh.vim
@@ -2,7 +2,7 @@
" Language: Zsh shell script
" Maintainer: Christian Brabandt <cb@256bit.org>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2022-07-26
+" Latest Revision: 2024 Jan 04
" License: Vim (see :h license)
" Repository: https://github.com/chrisbra/vim-zsh
@@ -48,8 +48,9 @@ syn match zshPOSIXQuoted '\\u[0-9a-fA-F]\{1,4}'
syn match zshPOSIXQuoted '\\U[1-9a-fA-F]\{1,8}'
syn region zshString matchgroup=zshStringDelimiter start=+"+ end=+"+
- \ contains=zshQuoted,@zshDerefs,@zshSubstQuoted fold
+ \ contains=@Spell,zshQuoted,@zshDerefs,@zshSubstQuoted fold
syn region zshString matchgroup=zshStringDelimiter start=+'+ end=+'+ fold
+ \ contains=@Spell
syn region zshPOSIXString matchgroup=zshStringDelimiter start=+\$'+
\ skip=+\\[\\']+ end=+'+ contains=zshPOSIXQuoted,zshQuoted
syn match zshJobSpec '%\(\d\+\|?\=\w\+\|[%+-]\)'
@@ -68,7 +69,7 @@ syn keyword zshConditional if then elif else fi esac select
syn keyword zshCase case nextgroup=zshCaseWord skipwhite
syn match zshCaseWord /\S\+/ nextgroup=zshCaseIn skipwhite contained transparent
-syn keyword zshCaseIn in nextgroup=zshCasePattern skipwhite skipnl contained
+syn keyword zshCaseIn in nextgroup=zshComment,zshCasePattern skipwhite skipnl contained
syn match zshCasePattern /\S[^)]*)/ contained
syn keyword zshRepeat while until repeat
@@ -94,22 +95,24 @@ syn match zshRedir '|\@1<!|&\=|\@!'
syn region zshHereDoc matchgroup=zshRedir
\ start='<\@<!<<\s*\z([^<]\S*\)'
- \ end='^\z1\>'
- \ contains=@zshSubst,@zshDerefs,zshQuoted,zshPOSIXString
+ \ end='^\z1$'
+ \ contains=@Spell,@zshSubst,@zshDerefs,zshQuoted,zshPOSIXString
syn region zshHereDoc matchgroup=zshRedir
\ start='<\@<!<<\s*\\\z(\S\+\)'
- \ end='^\z1\>'
- \ contains=@zshSubst,@zshDerefs,zshQuoted,zshPOSIXString
+ \ end='^\z1$'
+ \ contains=@Spell
syn region zshHereDoc matchgroup=zshRedir
\ start='<\@<!<<-\s*\\\=\z(\S\+\)'
- \ end='^\s*\z1\>'
- \ contains=@zshSubst,@zshDerefs,zshQuoted,zshPOSIXString
+ \ end='^\t*\z1$'
+ \ contains=@Spell
syn region zshHereDoc matchgroup=zshRedir
\ start=+<\@<!<<\s*\(["']\)\z(\S\+\)\1+
- \ end='^\z1\>'
+ \ end='^\z1$'
+ \ contains=@Spell
syn region zshHereDoc matchgroup=zshRedir
\ start=+<\@<!<<-\s*\(["']\)\z(\S\+\)\1+
- \ end='^\s*\z1\>'
+ \ end='^\t*\z1$'
+ \ contains=@Spell
syn match zshVariable '\<\h\w*' contained