Regenerate nvim config
This commit is contained in:
@ -0,0 +1,721 @@
|
||||
*rainbow-delimiters.txt* Alternating highlight for delimiters in code
|
||||
|
||||
*rainbow-delimiters*
|
||||
*rb-delimiters*
|
||||
|
||||
Author: Alejandro "HiPhish" Sanchez
|
||||
License: Apache-2.0
|
||||
Version: 0.4.0
|
||||
|
||||
|
||||
==============================================================================
|
||||
TABLE OF CONTENTS *rb-delimiters-contents*
|
||||
|
||||
1. Introduction .............................. |rb-delimiters-intro|
|
||||
2. Setup and configuration ................... |rb-delimiters-setup|
|
||||
2.1 Highlight colors ...................... |rb-delimiters-colors|
|
||||
2.2 Strategies ............................ |rb-delimiters-strategy|
|
||||
2.3 Queries ............................... |rb-delimiters-query|
|
||||
2.4 Logging ............................... |rb-delimiters-logging|
|
||||
3. Extending ................................. |rb-delimiters-extending|
|
||||
3.1 The library ........................... |rb-delimiters-api|
|
||||
3.2 Custom queries ........................ |rb-delimiters-custom-query|
|
||||
3.3 Custom strategies ..................... |rb-delimiters-custom-strategy|
|
||||
3.4 Adding new languages .................. |rb-delimiters-custom-lang|
|
||||
4. Acknowledgements .......................... |rb-delimiters-credit|
|
||||
5. Further reading ........................... |rb-delimiters-reading|
|
||||
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *rb-delimiters-intro*
|
||||
|
||||
This plugin provides alternating highlighting for delimiters in Neovim, also
|
||||
known as "rainbow parentheses". Thanks to the built-in |treesitter| support
|
||||
we are not limited to just parentheses. We can match any part of the document
|
||||
tree, such as HTML tags or `do` / `end` pairs in Lua. We can define new
|
||||
patterns for existing languages, add support for new languages and even change
|
||||
the strategy used for highlighting.
|
||||
|
||||
|
||||
==============================================================================
|
||||
SETUP AND CONFIGURATION *rb-delimiters-setup*
|
||||
|
||||
Install Rainbow-Delimiters like any other Neovim plugin. You also need a
|
||||
Tree-sitter parser for each language to want to support.
|
||||
|
||||
*g:rainbow_delimiters*
|
||||
Configuration is done through the variable `g:rainbow_delimiters`. It is a
|
||||
dictionary which can be defined both in Vim script and in Lua. The following
|
||||
keys are recognized:
|
||||
|
||||
`strategy`
|
||||
Dictionary mapping Tree-sitter language names to strategies. The empty
|
||||
string is the key for the default strategy. See |rb-delimiters-strategy|
|
||||
for more information about strategies.
|
||||
|
||||
`query`
|
||||
Dictionary mapping Tree-sitter language names to queries. The empty string
|
||||
is the key for the default query. See |rb-delimiters-query| for more
|
||||
information about queries.
|
||||
|
||||
`priority`
|
||||
Dictionary mapping Tree-sitter language names to highlight priority values.
|
||||
The empty string is the key for the default priority. See
|
||||
|vim.highlight.priorities| and |treesitter-highlight-priority| for more
|
||||
information on priorities.
|
||||
|
||||
`highlight`
|
||||
List of names of the highlight groups to use for highlighting, for more
|
||||
information see |rb-delimiters-colors|.
|
||||
|
||||
`whitelist`
|
||||
List of Tree-sitter languages for which to enabled rainbow delimiters.
|
||||
Rainbow delimiters will be disabled for all other languages.
|
||||
|
||||
`blacklist`
|
||||
List of Tree-sitter languages for which to disabled rainbow delimiters.
|
||||
Rainbow delimiters will be enabled for all other languages.
|
||||
|
||||
`log`
|
||||
Settings for logging information. This is a dictionary which contains
|
||||
further settings. See |rb-delimiters-logging| for details.
|
||||
|
||||
If neither the white- nor the blacklist are set rainbow delimiters will be
|
||||
enabled for all languages. If both lists are set it is undefined which will
|
||||
take precedence.
|
||||
|
||||
|
||||
Here is an example configuration:
|
||||
>vim
|
||||
let g:rainbow_delimiters = {
|
||||
\ 'strategy': {
|
||||
\ '': rainbow_delimiters#strategy.global,
|
||||
\ 'vim': rainbow_delimiters#strategy.local,
|
||||
\ },
|
||||
\ 'query': {
|
||||
\ '': 'rainbow-delimiters',
|
||||
\ 'lua': 'rainbow-blocks',
|
||||
\ },
|
||||
\ 'priority': {
|
||||
\ '': 110,
|
||||
\ 'lua': 210,
|
||||
\ },
|
||||
\ 'highlight': [
|
||||
\ 'RainbowDelimiterRed',
|
||||
\ 'RainbowDelimiterYellow',
|
||||
\ 'RainbowDelimiterBlue',
|
||||
\ 'RainbowDelimiterOrange',
|
||||
\ 'RainbowDelimiterGreen',
|
||||
\ 'RainbowDelimiterViolet',
|
||||
\ 'RainbowDelimiterCyan',
|
||||
\ ],
|
||||
\ 'blacklist': ['c', 'cpp'],
|
||||
\ }
|
||||
<
|
||||
|
||||
Alternatively, the same configuration in Lua:
|
||||
>lua
|
||||
-- This module contains a number of default definitions
|
||||
local rainbow_delimiters = require 'rainbow-delimiters'
|
||||
|
||||
---@type rainbow_delimiters.config
|
||||
vim.g.rainbow_delimiters = {
|
||||
strategy = {
|
||||
[''] = rainbow_delimiters.strategy['global'],
|
||||
commonlisp = rainbow_delimiters.strategy['local'],
|
||||
},
|
||||
query = {
|
||||
[''] = 'rainbow-delimiters',
|
||||
lua = 'rainbow-blocks',
|
||||
},
|
||||
priority = {
|
||||
[''] = 110,
|
||||
lua = 210,
|
||||
},
|
||||
highlight = {
|
||||
'RainbowDelimiterRed',
|
||||
'RainbowDelimiterYellow',
|
||||
'RainbowDelimiterBlue',
|
||||
'RainbowDelimiterOrange',
|
||||
'RainbowDelimiterGreen',
|
||||
'RainbowDelimiterViolet',
|
||||
'RainbowDelimiterCyan',
|
||||
},
|
||||
blacklist = {'c', 'cpp'},
|
||||
}
|
||||
<
|
||||
|
||||
*rainbow-delimiters.setup*
|
||||
'rainbow-delimiters.setup'.setup({config})
|
||||
|
||||
Some people prefer to call a Lua `setup` function, so a setup function is
|
||||
available as part of a Lua module.
|
||||
>lua
|
||||
require 'rainbow-delimiters.setup'.setup {
|
||||
strategy = {
|
||||
[''] = rainbow_delimiters.strategy['global'],
|
||||
commonlisp = rainbow_delimiters.strategy['local'],
|
||||
},
|
||||
query = {
|
||||
[''] = 'rainbow-delimiters',
|
||||
latex = 'rainbow-blocks',
|
||||
},
|
||||
highlight = {
|
||||
'RainbowDelimiterRed',
|
||||
'RainbowDelimiterYellow',
|
||||
'RainbowDelimiterBlue',
|
||||
'RainbowDelimiterOrange',
|
||||
'RainbowDelimiterGreen',
|
||||
'RainbowDelimiterViolet',
|
||||
'RainbowDelimiterCyan',
|
||||
},
|
||||
blacklist = {'c', 'cpp'},
|
||||
}
|
||||
<
|
||||
The keys are exactly the same as for |g:rainbow_delimiters|. In fact, this
|
||||
function does the same as setting the variable directly.
|
||||
|
||||
As an aside, this is a bad practice carried over from a time when Lua support
|
||||
in Neovim still had issues with Vim script interoperability, but it has
|
||||
persisted through cargo-culting. You are better off not using this function.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
HIGHLIGHT COLORS *rb-delimiters-colors*
|
||||
|
||||
The `highlight` setting controls which highlight group to apply. It is a list
|
||||
of any number of highlight group names as strings. The default values are in
|
||||
this order:
|
||||
|
||||
- `RainbowDelimiterRed`
|
||||
- `RainbowDelimiterYellow`
|
||||
- `RainbowDelimiterBlue`
|
||||
- `RainbowDelimiterOrange`
|
||||
- `RainbowDelimiterGreen`
|
||||
- `RainbowDelimiterViolet`
|
||||
- `RainbowDelimiterCyan`
|
||||
|
||||
These are non-standard highlight groups and I have tried to find reasonable
|
||||
default values for most uses. Nevertheless, you probably want to redefine
|
||||
them for your colour scheme or link them to some existing group.
|
||||
|
||||
The colors are intentionally not in the order of the rainbow to help make the
|
||||
contrast between adjacent delimiters more noticeable. Re-order the groups in
|
||||
your settings if you prefer a different order.
|
||||
|
||||
Example highlight group definitions:
|
||||
>vim
|
||||
" Link to an existing highlight group
|
||||
highlight link RainbowDelimiterRed WarningMsg
|
||||
|
||||
" Define the highlight from scratch
|
||||
highlight RainbowDelimiterOrange guifg=#d65d0e ctermfg=White
|
||||
<
|
||||
You will probably want to have different colours per theme. Since most themes
|
||||
will lack definitions for the above groups you will need to hook in somehow.
|
||||
A simple solution is to use an autocommand.
|
||||
>vim
|
||||
au ColorSchemePre MyTheme highlight link RainbowDelimiter MyThemeRed
|
||||
au ColorSchemePre MyTheme highlight link RainbowDelimiter MyThemeYellow
|
||||
" and so on...
|
||||
<
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
STRATEGIES *rb-delimiters-strategy*
|
||||
|
||||
A strategy defines how to perform the highlighting of delimiters. For
|
||||
example, the included global strategy highlights every delimiter in a buffer
|
||||
and updates the highlights when the document tree changes. On the other hand,
|
||||
the included local strategy highlights only the sub-tree of the document which
|
||||
contains the cursor and is updated whenever the cursor moves.
|
||||
|
||||
The strategy is set globally with per-language overrides. The setting is a
|
||||
dictionary where the empty string is the key for the default strategy and the
|
||||
overrides use the name of the language as keys.
|
||||
|
||||
Each value can be either a strategy or a function which evaluates to a
|
||||
strategy. A function can be used to defer the decision to a later point in
|
||||
time.
|
||||
|
||||
The function has the following signature:
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} Number of the buffer to highlight
|
||||
|
||||
Return: ~
|
||||
Either a strategy or `nil` (or |v:null|). If `nil`, rainbow delimiters
|
||||
will be disabled for that buffer.
|
||||
|
||||
NOTE
|
||||
Functions can only be used from Lua.
|
||||
|
||||
>lua
|
||||
local rainbow = require 'rainbow-delimiters'
|
||||
|
||||
strategy = {
|
||||
-- Use global strategy by default
|
||||
[''] = rainbow.strategy['global'],
|
||||
-- Use local for HTML
|
||||
html = rainbow.strategy['local'],
|
||||
-- Pick the strategy for LaTeX dynamically based on the buffer size
|
||||
latex = function(bufnr)
|
||||
-- Disabled for very large files, global strategy for large files,
|
||||
-- local strategy otherwise
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
if line_count > 10000 then
|
||||
return nil
|
||||
elseif line_count > 1000 then
|
||||
return rainbow.strategy['global']
|
||||
end
|
||||
return rainbow.strategy['local']
|
||||
end
|
||||
}
|
||||
<
|
||||
|
||||
A strategy is a table which must contain specific fields. It is possible to
|
||||
define your own strategy, see |rb-delimiters-custom-strategy|. The following
|
||||
strategies are included:
|
||||
|
||||
*rb-delimiters.strategy.global*
|
||||
Global~
|
||||
'rainbow-delimiters'.strategy['global']
|
||||
|
||||
The default strategy, highlights the entire buffer. Has very simple logic.
|
||||
|
||||
|
||||
*rb-delimiters.strategy.local*
|
||||
Local~
|
||||
'rainbow-delimiters'.strategy['local']
|
||||
|
||||
Based on the cursor position highlights only the sub-tree which contains the
|
||||
cursor. Updated every time the cursor moves and uses more complex logic than
|
||||
the global strategy to figure out which nodes exactly to highlight.
|
||||
|
||||
|
||||
*rb-delimiters.strategy.noop*
|
||||
No-op~
|
||||
'rainbow-delimiters'.strategy['noop']
|
||||
|
||||
A dummy strategy which does nothing. This is only useful in testing or if you
|
||||
really want an empty strategy.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
QUERIES *rb-delimiters-query*
|
||||
|
||||
A query defines what to match. Every language needs its own custom query.
|
||||
The query setting is a table where each entry maps a language name to a query
|
||||
name. The empty string is the key for the default query.
|
||||
|
||||
Each value in the table can be either the name of a query file or a function
|
||||
which evaluates to the name of a query file. A function can be used to defer
|
||||
the decision to a later point in time.
|
||||
|
||||
The function has the following signature:
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} Number of the buffer to highlight
|
||||
|
||||
Return: ~
|
||||
The name of the query as a string.
|
||||
|
||||
|
||||
NOTE
|
||||
Functions can only be used from Lua.
|
||||
|
||||
>lua
|
||||
query = {
|
||||
-- Use parentheses by default
|
||||
[''] = 'rainbow-delimiters',
|
||||
-- Use blocks for Lua
|
||||
lua = 'rainbow-blocks',
|
||||
-- Determine the query dynamically
|
||||
query = function(bufnr)
|
||||
-- Use blocks for read-only buffers like in `:InspectTree`
|
||||
local is_nofile = vim.bo[bufnr].buftype == 'nofile'
|
||||
return is_nofile and 'rainbow-blocks' or 'rainbow-delimiters'
|
||||
end
|
||||
}
|
||||
<
|
||||
If you wish to define your own custom query or add support for a new language,
|
||||
consult |rb-delimiters-custom-query| for details.
|
||||
|
||||
For every language the query `rainbow-delimiters` is defined, which matches a
|
||||
reasonable set of parentheses and similar delimiters for each language. In
|
||||
addition there are the following extra queries for certain languages:
|
||||
|
||||
- `latex`
|
||||
- `rainbow-blocks` Matches `\begin` and `\end` instructions
|
||||
- `lua`
|
||||
- `rainbow-blocks` Matches keyword delimiters like like `function` and
|
||||
`end`, in addition to parentheses
|
||||
- `javascript`
|
||||
- `rainbow-delimiters-react` Includes React support, set by default for
|
||||
Javascript files
|
||||
- `rainbow-parens` Only parentheses without React tags
|
||||
- `rainbow-tags-react` Only React tags without parentheses
|
||||
- `query`
|
||||
- `rainbow-blocks` Highlight named nodes and identifiers in addition to
|
||||
parentheses (useful for |:InspectTree|)
|
||||
- `tsx`
|
||||
- `rainbow-parens` Just Typescript highlighting without React tags
|
||||
- `rainbow-tags-react` Only React tags without Typescript highlighting
|
||||
- `typescript`
|
||||
- `rainbow-parens` Just Typescript highlighting without React tags
|
||||
- `verilog`
|
||||
- `rainbow-blocks` Matches keyword delimiters like `begin` and `end`, in
|
||||
addition to parentheses
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
LOGGING *rb-delimiters-logging*
|
||||
|
||||
By default only errors are logged. You can adjust what and how to log by
|
||||
adjusting the values of the `log` entry in the settings. For information how
|
||||
to change settings. see |rb-delimiters-setup|.
|
||||
|
||||
The following settings are supported:
|
||||
|
||||
`file`
|
||||
Path to the log file, default is `rainbow-delimiters.log` in your standard
|
||||
log path (see |standard-path|).
|
||||
|
||||
`level`
|
||||
Only messages equal to or above this value will be logged. The default is
|
||||
to log warnings or above. See |log_levels| for possible values.
|
||||
|
||||
The log file format is a CSV file which uses the `TAB` character (ASCII
|
||||
`0x09`) as the field separator and a `NL` (ASCII `0x0A`) as the record
|
||||
separator.
|
||||
|
||||
The fields are in this order:
|
||||
|
||||
- Time stamp of when the message was logged in ISO 8601 format with time zone
|
||||
- Log level as string
|
||||
- Lua module from which the message was logged, or the empty string if outside
|
||||
a module
|
||||
- The logged message
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
EXTENDING RAINBOW DELIMITERS
|
||||
|
||||
Rainbow delimiters are hackable, you can add your own strategies, queries for
|
||||
existing languages or even queries for new languages. Strategies and queries
|
||||
are split up to be independent and can be mixed arbitrarily, but there are
|
||||
some rules which need to be followed.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
THE LIBRARY *rb-delimiters-api*
|
||||
|
||||
There is a utility library provided for people writing their own strategies.
|
||||
It is available as a table under the Lua module `'rainbow-delimiters'`.
|
||||
|
||||
|
||||
*rb-delimiters.enable*
|
||||
*rb_delimiters#enable*
|
||||
'rainbow-delimiters'.enable({bufnr})
|
||||
Re-enable rainbow delimiters for the buffer {bufnr} (or the current buffer
|
||||
if {bufnr} is `0`) after it has been disabled.
|
||||
|
||||
rainbow_delimiters#enable({bufnr})
|
||||
Vim script binding for the above function.
|
||||
|
||||
|
||||
*rb-delimiters.disable*
|
||||
*rb_delimiters#disable*
|
||||
'rainbow-delimiters'.disable({bufnr})
|
||||
Disable rainbow delimiters for the buffer {bufnr} (or the current buffer
|
||||
if {bufnr} is `0`).
|
||||
|
||||
rainbow_delimiters#disable({bufnr})
|
||||
Vim script binding for the above function.
|
||||
|
||||
|
||||
*rb-delimiters.toggle*
|
||||
*rb_delimiters#toggle*
|
||||
'rainbow-delimiters'.toggle({bufnr})
|
||||
Toggle rainbow delimiters for the buffer {bufnr} (or the current buffer
|
||||
if {bufnr} is `0`).
|
||||
|
||||
rainbow_delimiters#toggle({bufnr})
|
||||
Vim script binding for the above function.
|
||||
|
||||
|
||||
*rb-delimiters.is_enabled*
|
||||
*rb_delimiters#is_enabled*
|
||||
'rainbow-delimiters'.is_enabled({bufnr})
|
||||
Check if rainbow delimiters are enabled for the buffer {bufnr} (or the
|
||||
current buffer if {bufnr} is `0`).
|
||||
|
||||
rainbow_delimiters#is_enabled({bufnr})
|
||||
Vim script binding for the above function.
|
||||
|
||||
|
||||
*rb-delimiters.hlgroup_at*
|
||||
*rainbow-delimiters#hlgroup_at*
|
||||
'rainbow-delimiters'.hlgroup_at({nesting_level})
|
||||
Gets the name of the highlight group set up at the given nesting level.
|
||||
This function will properly roll over, meaning that if there are seven
|
||||
highlight groups defined and the {nesting_level} is nine, you will get the
|
||||
second highlight group.
|
||||
|
||||
rainbow-delimiters#hlgroup_at({nesting_level})
|
||||
Vim script binding for the above function.
|
||||
|
||||
|
||||
*rb-delimiters.strategy*
|
||||
*g:rainbow_delimiters#strategy*
|
||||
'rainbow-delimiters'.strategy
|
||||
Table of included strategies. For more information about strategies see
|
||||
|rb-delimiters-strategy|. The included ones are:
|
||||
|
||||
- `global` |rb-delimiters.strategy.global|
|
||||
- `local` |rb-delimiters.strategy.local|
|
||||
- `noop` |rb-delimiters.strategy.noop|
|
||||
|
||||
Do not add your own strategies to this table.
|
||||
|
||||
g:rainbow_delimiters#strategy
|
||||
Vim script dictionary, equivalent of the above table with the same keys.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CUSTOM STRATEGIES *rb-delimiters-custom-strategy*
|
||||
|
||||
A strategy is a table which must contain a certain set of fields. In
|
||||
object-oriented terminology we would say that a strategy table must implement
|
||||
the strategy protocol.
|
||||
>
|
||||
strategy = {
|
||||
on_attach = function(bufnr: integer, settings: table),
|
||||
on_detach = function(bufnr: integer),
|
||||
on_reset = function(bufnr: integer, settings: table),
|
||||
}
|
||||
<
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
on_attach({bufnr}, {settings})
|
||||
|
||||
This function takes two arguments: the number of the buffer and the table of
|
||||
settings used by the buffer. This function is generally used to set up
|
||||
autocommands or other callbacks for events when the highlighting needs to be
|
||||
updated.
|
||||
|
||||
The settings table contains the following entries:
|
||||
|
||||
- `strategy` Strategy in use
|
||||
- `parser` Reference to the buffer parser (|treesitter-languagetree|)
|
||||
- `lang` Language of the current parser
|
||||
|
||||
A strategy should pick the settings it needs and either cache them in an
|
||||
internal table, or construct closures (e.g. for callback functions) around
|
||||
them.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
on_detach({bufnr})
|
||||
|
||||
This function takes one argument: the number of the buffer. This function is
|
||||
generally used to clean up any custom state, autocommands and callbacks set up
|
||||
in the `on_attach` function.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
on_reset({bufnr}, {settings})
|
||||
|
||||
Similar to `on_attach` with the same signature, except that this function is
|
||||
called when the buffer has been reset in some way, for example if the
|
||||
underlying file has been modified by a code formatter. Usually the strategy
|
||||
should highlight the entire buffer from scratch again because we cannot rely
|
||||
on Tree-sitter to tell us what has changed.
|
||||
|
||||
As a rule of thumb, `on_reset` should do the work of `on_attach`, minus all
|
||||
the initial setup.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
The logic within the strategy can vary wildly between strategies. Usually you
|
||||
will want to install some callback in the `on_attach` function. That callback
|
||||
can then use the Tree-sitter API and the utility library (see
|
||||
|rb-delimiters-api|) to select which nodes to highlight and what highlight
|
||||
group to apply.
|
||||
|
||||
See |rb-delimiters-custom-query| for the standard capture groups used.
|
||||
Selecting standard capture groups allows your strategy to work with any of the
|
||||
built-in queries as well as user-specified custom queries.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CUSTOM QUERIES *rb-delimiters-custom-query*
|
||||
|
||||
A query defines what exactly needs to be highlighted. Different languages
|
||||
have different document trees, so you need a separate query for each language.
|
||||
The queries need to define the following capture groups:
|
||||
|
||||
- `@container`
|
||||
The entire delimited node.
|
||||
- `@delimiter`
|
||||
Any delimiter you want to highlight in the current `@container`.
|
||||
- `@sentinel`
|
||||
A marker used to signal that you are done with the `@container`. This
|
||||
should almost always be put right after the last `@delimiter` in the given
|
||||
`@container`.
|
||||
- `@_<capture_name>`
|
||||
Delimiters starting with `_` (underscore) are ignored for highlighting
|
||||
purposes, but you can use them for treesitter predicates like
|
||||
`#eq?`, `#any-eq?`, etc. (These are very rarely needed.)
|
||||
|
||||
`@container` and `@sentinel` are mandatory, and `@delimiter` will always be
|
||||
present as well since `@delimiter` is what is highlighted. The captures
|
||||
starting with underscore will be rarely used, since you only need them for
|
||||
predicates in a few special cases.
|
||||
|
||||
|
||||
Let's look at an example first. Here is a snippet of HTML code:
|
||||
>html
|
||||
<a href="https://example.com">
|
||||
Example<br/>link
|
||||
</a>
|
||||
<
|
||||
|
||||
The corresponding document tree including anonymous nodes is as follows:
|
||||
>query
|
||||
(element ; [0, 0] - [2, 4]
|
||||
(start_tag ; [0, 0] - [0, 30]
|
||||
"<" ; [0, 0] - [0, 1]
|
||||
(tag_name) ; [0, 1] - [0, 2]
|
||||
(attribute ; [0, 3] - [0, 29]
|
||||
(attribute_name) ; [0, 3] - [0, 7]
|
||||
"=" ; [0, 7] - [0, 8]
|
||||
(quoted_attribute_value ; [0, 8] - [0, 29]
|
||||
"\"" ; [0, 8] - [0, 9]
|
||||
(attribute_value) ; [0, 9] - [0, 28]
|
||||
"\"")) ; [0, 28] - [0, 29]
|
||||
">") ; [0, 29] - [0, 30]
|
||||
(text) ; [1, 4] - [1, 11]
|
||||
(element ; [1, 11] - [1, 16]
|
||||
(self_closing_tag ; [1, 11] - [1, 16]
|
||||
"<" ; [1, 11] - [1, 12]
|
||||
(tag_name) ; [1, 12] - [1, 14]
|
||||
"/>")) ; [1, 14] - [1, 16]
|
||||
(text) ; [1, 16] - [1, 20]
|
||||
(end_tag ; [2, 0] - [2, 4]
|
||||
"</" ; [2, 0] - [2, 2]
|
||||
(tag_name) ; [2, 2] - [2, 3]
|
||||
">")) ; [2, 3] - [2, 4]
|
||||
<
|
||||
|
||||
As a human I immediately perceive the entire link as one object with two
|
||||
delimiters: the opening `<a>` tag and the closing `</a>` tag. Perhaps the
|
||||
self-closing `<br/>` tag can be seen as an intermediate delimiter because it
|
||||
does not open a new scope. On the other hand, it is part of the content of
|
||||
the entire link, not one of its delimiters.
|
||||
|
||||
As you can see, it is up to interpretation as to what exactly constitutes a
|
||||
delimiter. In this example for the sake of exhaustiveness we will consider
|
||||
the `<br/>` tag a delimiter. The corresponding query is as follows:
|
||||
>query
|
||||
(element
|
||||
(start_tag) @delimiter
|
||||
(element
|
||||
(self_closing_tag) @delimiter)? ; Optional!
|
||||
(end_tag) @delimiter @sentinel) @container
|
||||
<
|
||||
Highlighting the entire tag might be too vibrant though. What if we want to
|
||||
highlight only the opening and closing angle brackets? The query gets
|
||||
slightly more complex because we have to descend deeper into the document
|
||||
tree.
|
||||
>query
|
||||
(element
|
||||
((start_tag
|
||||
["<" ">"] @delimiter)
|
||||
(element
|
||||
(self_closing_tag
|
||||
["<" "/>"] @delimiter))? ;Optional!
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
">" @delimiter @sentinel))) @container
|
||||
<
|
||||
Note that we don't want to put the `@sentinel` on the second to last `@delimiter`
|
||||
`"</"`, we need to be careful to put it on the last `@delimiter`.
|
||||
|
||||
You might now see why we need the `@container` capture group: there is no way
|
||||
to know in general how deeply the delimiter is nested. Even for one language
|
||||
our understanding of what constitutes a delimiter is up for debate. Therefore
|
||||
a human must decide for each query which node is the container and which nodes
|
||||
are the delimiters. Capturing this information makes it available for use in
|
||||
strategies.
|
||||
|
||||
We are not limited to only one opening and one closing delimiter. The
|
||||
included default query captures the angle brackets and the tag name, but not
|
||||
attributes between the tag name and closing angle bracket. This strikes a
|
||||
pleasant middle ground between the two above extremes.
|
||||
>query
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
<
|
||||
Here both opening and closing tag have three delimiters each.
|
||||
|
||||
In HTML the terminating slash in a self-closing tag is optional. Instead of
|
||||
`<br/>` we can write `<br>`. A naïve query would look like this:
|
||||
>query
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter @_tag_name
|
||||
">" @delimiter @sentinel)) @container
|
||||
<
|
||||
However, this query also matches the opening tag of regular tags like `<div>`.
|
||||
This is where the `@_tag_name` capture comes in. The set of self-closing tags
|
||||
is finite, so we can list them explicitly. This way a regular opening tag
|
||||
will not match this particular pattern.
|
||||
>query
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter @_tag_name
|
||||
">" @delimiter @sentinel)
|
||||
;; List abridged for brevity
|
||||
(#any-of? @_tag_name "br" "hr" "input")) @container
|
||||
<
|
||||
We need the `@_tag_name` capture so that it can be used with the `#any-of?`
|
||||
predicate (|treesitter-predicate-any-of?|), but the capture itself is not used
|
||||
for highlighting.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
ADDING SUPPORT FOR NEW LANGUAGES *rb-delimiters-custom-lang*
|
||||
|
||||
Supporting a new new language requires creating one or more queries for the
|
||||
language. If the query is mature enough please consider upstreaming it so
|
||||
everyone can benefit.
|
||||
|
||||
|
||||
==============================================================================
|
||||
ACKNOWLEDGMENTS *rb-delimiters-credit*
|
||||
|
||||
The original version of nvim-ts-rainbow was written by Chinmay "p00f" Dalal,
|
||||
and discontinued in January of 2023. The original repositories can be found
|
||||
under these URLs:
|
||||
|
||||
- https://sr.ht/~p00f/nvim-ts-rainbow/
|
||||
- https://github.com/p00f/nvim-ts-rainbow
|
||||
|
||||
|
||||
==============================================================================
|
||||
FURTHER READING *rb-delimiters-reading*
|
||||
|
||||
- nvim-treesitter plugin https://github.com/nvim-treesitter/nvim-treesitter
|
||||
- Official Tree-sitter website https://tree-sitter.github.io/tree-sitter/
|
||||
- Neovim Tree-sitter documentation: |treesitter.txt|
|
||||
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:sw=4:et:ft=help:norl:
|
||||
Reference in New Issue
Block a user