:h treesitter-highlight.
Your color scheme needs to define (or link) these captures as highlight groups. Use Neovim’s built-in
:Inspect function to see which highlight groups are applied at a given position.Basic Structure
Highlight queries use pattern matching to capture nodes:Valid Captures
Identifiers
Various variable names
Built-in variable names (e.g.
this, self)Parameters of a function
Special parameters (e.g.
_, it)Object and struct fields
Constant identifiers
Built-in constant values
Constants defined by the preprocessor
Modules or namespaces
Built-in modules or namespaces
GOTO and other labels (e.g.
label: in C), including heredoc labelsLiterals
String literals
String documenting code (e.g. Python docstrings)
Regular expressions
Escape sequences
Other special strings (e.g. dates)
Symbols or atoms
URIs (e.g. hyperlinks)
Filenames
Character literals
Special characters (e.g. wildcards)
Boolean literals
Numeric literals
Floating-point number literals
Types
Type or class definitions and annotations
Built-in types
Identifiers in type definitions (e.g.
typedef <type> <identifier> in C)Attribute annotations (e.g. Python decorators, Rust lifetimes)
Builtin annotations (e.g.
@property in Python)The key in key/value pairs
Functions
Function definitions
Built-in functions
Function calls
Preprocessor macros
Method definitions
Method calls
Constructor calls and definitions
Symbolic operators (e.g.
+ / *)Keywords
Keywords not fitting into specific categories
Keywords related to coroutines (e.g.
go in Go, async/await in Python)Keywords that define a function (e.g.
func in Go, def in Python)Operators that are English words (e.g.
and / or)Keywords for including or exporting modules (e.g.
import / from in Python)Keywords describing namespaces and composite types (e.g.
struct, enum)Keywords modifying other constructs (e.g.
const, static, public)Keywords related to loops (e.g.
for / while)Keywords like
return and yieldKeywords related to debugging
Keywords related to exceptions (e.g.
throw / catch)Keywords related to conditionals (e.g.
if / else)Ternary operator (e.g.
? / :)Various preprocessor directives & shebangs
Preprocessor definition directives
Punctuation
Delimiters (e.g.
; / . / ,)Brackets (e.g.
() / {} / [])Special symbols (e.g.
{} in string interpolation)Comments
Line and block comments
Comments documenting code
Error-type comments (e.g.
ERROR, FIXME, DEPRECATED)Warning-type comments (e.g.
WARNING, FIX, HACK)Todo-type comments (e.g.
TODO, WIP)Note-type comments (e.g.
NOTE, INFO, XXX)Markup
Mainly for markup languages.Bold text
Italic text
Struck-through text
Underlined text (only for literal underline markup!)
Headings, titles (including markers)
Top-level heading
Section heading
Subsection heading
Fourth-level heading
Fifth-level heading
Sixth-level heading
Block quotes
Math environments (e.g.
$ ... $ in LaTeX)Text references, footnotes, citations, etc.
Link, reference descriptions
URL-style links
Literal or verbatim text (e.g. inline code)
Literal or verbatim text as a stand-alone block (use priority 90 for blocks with injections)
List markers
Checked todo-style list markers
Unchecked todo-style list markers
Added text (for diff files)
Deleted text (for diff files)
Changed text (for diff files)
XML-style tag names (and similar)
Builtin tag names (e.g. HTML5 tags)
XML-style tag attributes
XML-style tag delimiters
Non-highlighting Captures
Captures that are only meant to be concealed
See
:h tree-sitter-highlight-conceal. The capture should be meaningful to allow proper highlighting when set conceallevel=0. A conceal can be restricted to part of the capture via the #offset! directive.For defining regions to be spellchecked
For defining regions that should NOT be spellchecked
The main types of nodes that should be spell checked are:
- Comments
- Strings; where it makes sense. Strings that have interpolation or are typically used for non-text purposes are not spell checked (e.g. bash).
Predicates
Captures can be restricted according to node contents using predicates.For performance reasons, prefer predicates in this order:
#eq?(literal match)#any-of?(one of several literal matches)#lua-match?(match against a Lua pattern)#match?/#vim-match?(match against a Vim regular expression)
Examples
Directives
Nodes contain metadata that can be modified via directives.Priority
Captures can be assigned a priority to control precedence of highlights via the#set! priority <number> directive (see :h treesitter-highlight-priority).
The default priority for treesitter highlights is
100. Queries should only set priorities between 90 and 120, to avoid conflict with other sources of highlighting (such as diagnostics or LSP semantic tokens).Precedence is also influenced by pattern order in a query file. If possible, try to achieve the correct result by reordering patterns before resorting to explicit priorities.
Example
Inheriting Languages
If your language is an extension of another language (TypeScript extends JavaScript, for example), you can include queries from your base language by adding this as the first line:Real-World Examples
Python Function Highlighting
Rust Variable Conventions
Tools
The following tools can help when writing highlight queries:- ts_query_ls - A language server for treesitter queries with validation, autocomplete, and formatting
:InspectTree- Shows the parsed tree for a buffer and highlights corresponding text:EditQuery- Opens a playground to write query patterns and see captures in real-timemake lintquery- Validates that all captures are valid for Neovimmake checkquery- Verifies patterns are valid for the parsermake formatquery- Automatically formats queries to standard style