Regenerate nvim config
This commit is contained in:
@ -0,0 +1,43 @@
|
||||
-- SPDX-License-Identifier: Unlicense
|
||||
|
||||
-- This is free and unencumbered software released into the public domain.
|
||||
--
|
||||
-- Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
-- this software, either in source code form or as a compiled binary, for any
|
||||
-- purpose, commercial or non-commercial, and by any means.
|
||||
--
|
||||
-- In jurisdictions that recognize copyright laws, the author or authors of
|
||||
-- this software dedicate any and all copyright interest in the software to
|
||||
-- the public domain. We make this dedication for the benefit of the public
|
||||
-- at large and to the detriment of our heirs and successors. We intend this
|
||||
-- dedication to be an overt act of relinquishment in perpetuity of all
|
||||
-- present and future rights to this software under copyright law.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
-- THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
-- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
--
|
||||
-- For more information, please refer to <https://unlicense.org/>
|
||||
|
||||
|
||||
return {
|
||||
_all = {
|
||||
coverage = false,
|
||||
lua = './test/nvim-shim'
|
||||
},
|
||||
default = {
|
||||
verbose = true,
|
||||
},
|
||||
unit = {
|
||||
ROOT = {'./test/unit/'},
|
||||
},
|
||||
e2e = {
|
||||
ROOT = {'./test/e2e/'},
|
||||
pattern = '', -- No fancy names for E2E tests
|
||||
},
|
||||
}
|
||||
|
||||
-- vim:ft=lua
|
||||
@ -0,0 +1,15 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_size = tab
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
|
||||
[*.lua]
|
||||
indent_style = tab
|
||||
|
||||
[*.scm]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
34
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
34
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
assignees:
|
||||
- "HiPhish"
|
||||
body:
|
||||
- type: 'input'
|
||||
attributes:
|
||||
label: 'Neovim version'
|
||||
description: 'Version of your Neovim'
|
||||
placeholder: '0.0.0'
|
||||
- type: 'input'
|
||||
attributes:
|
||||
label: 'Language affected'
|
||||
description: 'Leave empty if you experience the issue with any file type.'
|
||||
placeholder: 'Lua'
|
||||
- type: 'input'
|
||||
attributes:
|
||||
label: 'Query'
|
||||
description: 'Leave empty if the issue is not tied to a specific query.'
|
||||
placeholder: 'rainbow-delimiters'
|
||||
- type: 'input'
|
||||
attributes:
|
||||
label: 'Strategy'
|
||||
description: 'Leave empty if the issue is not tied to a specific strategy.'
|
||||
placeholder: 'global'
|
||||
- type: 'textarea'
|
||||
attributes:
|
||||
label: 'Description'
|
||||
description: |
|
||||
Please describe the bug in detail here. If possible provide a minimal
|
||||
code sample which replicates the issue
|
||||
placeholder: 'print((("Hello world!")))'
|
||||
5
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Main repoo
|
||||
url: 'https://gitlab.com/HiPhish/nvim-ts-rainbow2'
|
||||
about: 'Upstream repository; you can also report bugs here on GitHub.'
|
||||
7
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.gitignore
vendored
Normal file
7
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Tag file created by Vim
|
||||
doc/tags
|
||||
|
||||
# Fake user directory structures
|
||||
test/xdg/local/share/nvim/
|
||||
test/xdg/local/state/nvim/
|
||||
!test/xdg/local/share/nvim/site/pack/testing/start/rainbow-delimiters
|
||||
@ -0,0 +1,7 @@
|
||||
- Neovim version:
|
||||
- Language affected:
|
||||
- Query used:
|
||||
- Strategy used:
|
||||
|
||||
Please describe the bug in detail here. If possible provide a minimal code
|
||||
sample which replicates the issue.
|
||||
6
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.gitmodules
vendored
Normal file
6
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "test/xdg/local/share/nvim/site/pack/testing/start/nvim-treesitter"]
|
||||
path = test/xdg/local/share/nvim/site/pack/testing/start/nvim-treesitter
|
||||
url = https://github.com/nvim-treesitter/nvim-treesitter
|
||||
[submodule "test/xdg/local/share/nvim/site/pack/testing/start/yo-dawg"]
|
||||
path = test/xdg/local/share/nvim/site/pack/testing/start/yo-dawg
|
||||
url = https://gitlab.com/HiPhish/yo-dawg.nvim.git
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||
"workspace.ignoreDir": ["test/xdg"]
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
" Use the custom shim as the busted binary for testing
|
||||
let g:bustedprg='./test/busted'
|
||||
@ -0,0 +1,309 @@
|
||||
.. default-role:: code
|
||||
|
||||
###########
|
||||
Changelog
|
||||
###########
|
||||
|
||||
All notable changes to this project will be documented in this file. The format
|
||||
is based on `Keep a Changelog`_ and this project adheres to `Semantic
|
||||
Versioning`_.
|
||||
|
||||
|
||||
Unreleased
|
||||
##########
|
||||
|
||||
Added
|
||||
=====
|
||||
|
||||
- Missing patterns for C++:
|
||||
|
||||
- `condition_clause`
|
||||
- `for_statement`
|
||||
- `cast_expression`
|
||||
- `array_declarator`
|
||||
|
||||
- Missing patterns for Common Lisp:
|
||||
|
||||
- `loop_macro`
|
||||
|
||||
- Missing patterns for Javascript:
|
||||
|
||||
- `array_pattern`
|
||||
- `for_in_statement`
|
||||
- `for_statement`
|
||||
|
||||
- Missing patterns for Typescript:
|
||||
|
||||
- `enum_body`
|
||||
- `interface_body`
|
||||
|
||||
- Missing patterns for Haskell:
|
||||
|
||||
- `children`
|
||||
- `fields`
|
||||
- `list`
|
||||
- `parens`
|
||||
- `prefix_id`
|
||||
- `record`
|
||||
- `tuple`
|
||||
- `unit`
|
||||
|
||||
Changed
|
||||
=======
|
||||
|
||||
- Renamed C# patterns:
|
||||
|
||||
- `for_each_statement` to `foreach_statement`
|
||||
- `type_of_expression` to `typeof_expression`
|
||||
- `size_of_expression` to `sizeof_expression`
|
||||
- `implicit_stack_alloc_array_creation_expression` to `implicit_stackalloc_expression`
|
||||
|
||||
Removed
|
||||
=======
|
||||
|
||||
- Deprecated patterns for C#:
|
||||
|
||||
- `interpolation`
|
||||
|
||||
- Deprecated patterns for Java:
|
||||
|
||||
- `condition`
|
||||
|
||||
- Deprecated patterns for Haskell:
|
||||
|
||||
- `con_list`
|
||||
- `context`
|
||||
- `deriving`
|
||||
- `exp_arithmetic_sequence`
|
||||
- `exp_lambda`
|
||||
- `exp_list_comprehension`
|
||||
- `exp_list`
|
||||
- `exp_name`
|
||||
- `exp_record`
|
||||
- `exp_section_right`
|
||||
- `pat_fields`
|
||||
- `pat_list`
|
||||
- `pat_parens`
|
||||
- `pat_tuple`
|
||||
- `record_fields`
|
||||
- `type_list`
|
||||
- `type_parens`
|
||||
- `type_tuple`
|
||||
- `type_tuple`
|
||||
|
||||
|
||||
[0.4.0] - 2024-05-07
|
||||
####################
|
||||
|
||||
Added
|
||||
=====
|
||||
|
||||
- Public API function `is_enabled`
|
||||
- Rasi support
|
||||
- Svelte support
|
||||
- Teal support
|
||||
- Typst support
|
||||
- XML support
|
||||
- Missing patterns for Java:
|
||||
|
||||
- `array_initializer`
|
||||
- `annotation_argument_list`
|
||||
- `catch_clause`
|
||||
- `condition`
|
||||
- `constructor_body`
|
||||
- `dimensions_expr`
|
||||
- `enhanced_for_statement`
|
||||
- `for_statement`
|
||||
- `inferred_parameters`
|
||||
- `parenthesized_expression`
|
||||
- `resource_specification`
|
||||
- `cast_expression`
|
||||
|
||||
- Missing patterns for Go:
|
||||
|
||||
- `type_assertion_expression`
|
||||
|
||||
- Missing patterns for Julia:
|
||||
|
||||
- `curly_expression`
|
||||
- `tuple_expression`
|
||||
|
||||
- Missing patterns for Lua:
|
||||
|
||||
- `field`
|
||||
|
||||
- Missing patterns for Luadoc:
|
||||
|
||||
- `indexed_field`
|
||||
- `tuple_type`
|
||||
|
||||
- Missing patterns for Python:
|
||||
|
||||
- `dict_pattern`
|
||||
- `import_from_statement`
|
||||
- `interpolation` (literal string interpolation)
|
||||
- `list_pattern`
|
||||
- `tuple_pattern`
|
||||
|
||||
- Missing patterns for R:
|
||||
|
||||
- `for`
|
||||
- `while`
|
||||
- `switch`
|
||||
- `function_definition`
|
||||
|
||||
- Missing patterns for Rust:
|
||||
|
||||
- `array_type`
|
||||
|
||||
- Missing patterns for Starlark:
|
||||
|
||||
- `tuple_pattern`
|
||||
|
||||
Fixed
|
||||
=====
|
||||
|
||||
- Default configuration settings override custom settings if the configuration
|
||||
value was used before setting the custom value
|
||||
- Switched Fennel queries to new upstream grammar (`#6132`_)
|
||||
- Deleted obsolete Julia pattern `parameter_list`
|
||||
|
||||
.. _#6132: https://github.com/nvim-treesitter/nvim-treesitter/pull/6132
|
||||
|
||||
|
||||
[0.3.0] 2023-12-24
|
||||
##################
|
||||
|
||||
This release brings a plethora of missing patterns to existing queries and lets
|
||||
you specify priorities and queries dynamically at runtime. This means that it
|
||||
is possible to set different queries for the same language depending on
|
||||
external conditions, such as whether a buffer is read-only.
|
||||
|
||||
And as a little extra given the date of this release, there is a new Christmas
|
||||
strategy module. This will let you decorate your syntax tree in an especially
|
||||
festive mood. The module is just a joke, so it will not be loaded by default
|
||||
and you will have to figure out yourself how to set it up.
|
||||
|
||||
Added
|
||||
=====
|
||||
|
||||
- Starlark support
|
||||
- Missing patterns for Bash:
|
||||
|
||||
- `array`
|
||||
- `function_definition`
|
||||
- `arithmetic_expansion`
|
||||
- `compound_statement`
|
||||
- `subscript`
|
||||
|
||||
- Missing patterns for C:
|
||||
|
||||
- `enumerator_list`
|
||||
- `macro_type_specifier`
|
||||
- `preproc_params`
|
||||
- `compound_literal_expression`
|
||||
- `parenthesized_declarator`
|
||||
|
||||
- Missing patterns for Elixir:
|
||||
|
||||
- `access_call`
|
||||
|
||||
- Missing patterns for Fennel:
|
||||
|
||||
- `table_binding`
|
||||
|
||||
- New query for language `query`:
|
||||
|
||||
- `rainbow-blocks`
|
||||
|
||||
- New query for language `javascript`:
|
||||
|
||||
- `rainbow-tags-react`
|
||||
|
||||
- New query for language `tsx`:
|
||||
|
||||
- `rainbow-tags-react`
|
||||
|
||||
- New Christmas strategy module `rainbow-delimiters.strategy.christmas` (not
|
||||
loaded by default)
|
||||
|
||||
Fixed
|
||||
=====
|
||||
|
||||
- Query can be a function in configuration
|
||||
- Priority can be a function in configuration
|
||||
- Functions in configuration take buffer number as argument
|
||||
- Updated Nim queries
|
||||
|
||||
|
||||
[0.2.0] - 2023-11-26
|
||||
####################
|
||||
|
||||
Added
|
||||
=====
|
||||
|
||||
- Ability to set highlight priority
|
||||
- Cue support
|
||||
- Luadoc support
|
||||
- Nim support
|
||||
- Kotlin support
|
||||
- templ support
|
||||
- Terraform support
|
||||
- TOML support
|
||||
|
||||
Fixed
|
||||
=====
|
||||
|
||||
- Type error in local strategy
|
||||
- Log error in local strategy (Neovim <0.10 only)
|
||||
- Missing patterns for CSS
|
||||
|
||||
- `feature_query`
|
||||
- `arguments`
|
||||
- `attribute_selector`
|
||||
|
||||
- Missing patterns for Go
|
||||
|
||||
- `array_type`
|
||||
- `slice_expression`
|
||||
|
||||
- Missing patterns for HCL
|
||||
|
||||
- `for_tuple_expr`
|
||||
- `new_index`
|
||||
- `expression`
|
||||
- `binary_operation`
|
||||
- `for_object_expr`
|
||||
- `template_interpolation`
|
||||
- `unary_operation`
|
||||
|
||||
- Missing pattern for Javascript and Typescript
|
||||
|
||||
- `switch_body`
|
||||
|
||||
- Missing patterns for Nix
|
||||
|
||||
- `rec_attrset_expression`
|
||||
- `inherit_from`
|
||||
|
||||
- Missing pattern for SCSS
|
||||
|
||||
- `parameters`
|
||||
|
||||
Changed
|
||||
=======
|
||||
|
||||
- Default highlight priority is 110 instead of 210, which is between
|
||||
Tree-sitter and LSP semantic tokens
|
||||
|
||||
|
||||
[0.1.0] - 2023-11-12
|
||||
####################
|
||||
|
||||
Initial release
|
||||
|
||||
|
||||
|
||||
.. ----------------------------------------------------------------------------
|
||||
.. _Keep a Changelog: https://keepachangelog.com/en/1.0.0/,
|
||||
.. _Semantic Versioning: https://semver.org/spec/v2.0.0.html
|
||||
@ -0,0 +1,38 @@
|
||||
.. default-role:: code
|
||||
|
||||
#####################
|
||||
Contributor's guide
|
||||
#####################
|
||||
|
||||
|
||||
Adding support for a new language
|
||||
#################################
|
||||
|
||||
Languages are supported through language-specific queries. Each language needs
|
||||
at lease one query which matches the most common delimiters, usually `(`, `)`,
|
||||
`[`, `]`, `{`, `}`, `<` and `>`. Read `:h rb-delimiters-custom-query` in the
|
||||
manual first to understand how to write queries. Your query should meet the
|
||||
following criteria:
|
||||
|
||||
- Named `rainbow-delimiters`
|
||||
- Few `@delimiter` capture groups per `@container`; we do not want the default
|
||||
query to be too vibrant
|
||||
- Write one or more files in the language under `test/highlight/<lang>` (where
|
||||
`<lang>` is the language); the standard file name is `regular.<ext>`
|
||||
- The test code must have at least one instance of each pattern in the query
|
||||
- The test code must not have parsing errors
|
||||
- The test code should ideally have multiple levels of nesting
|
||||
- The test code should compile and have no linter errors if that is feasible
|
||||
(this is not a hard rule though)
|
||||
|
||||
If there are many test cases or if the code becomes too verbose feel free to
|
||||
create multiple test files.
|
||||
|
||||
In addition to the queries and test file(s), please consider adding the type
|
||||
annotations in `lua/rainbow-delimiters.types.lua` if you are adding queries
|
||||
for a new language. You will need to update:
|
||||
|
||||
- `@class rainbow_delimiters.config.strategies`
|
||||
- `@class rainbow_delimiters.config.queries`
|
||||
- `@class rainbow_delimiters.config.priorities`
|
||||
- `@alias rainbow_delimiters.language`
|
||||
@ -0,0 +1,335 @@
|
||||
.. default-role:: code
|
||||
|
||||
#################################
|
||||
Hacking on Rainbow Delimiters 2
|
||||
#################################
|
||||
|
||||
|
||||
Testing
|
||||
#######
|
||||
|
||||
|
||||
A test setup must meet the following criteria:
|
||||
|
||||
- Test definitions must be run by with Neovim as the Lua interpreter to get
|
||||
access to all Neovim APIs
|
||||
- Tests must not be affected by the user's own plugins and configuration
|
||||
- Each test which mutates editor state must run in its own Neovim process
|
||||
|
||||
The first two points are achieved through a small command-line interface
|
||||
adapter script (a shim). The shim exposes the command-line interface of a Lua
|
||||
interpreter, and internally it sets up environment variable to point Neovim at
|
||||
a prepared blank directory structure. Neovim is then called with the `-l`
|
||||
flag.
|
||||
|
||||
We do have to use some plugins though:
|
||||
|
||||
- This plugin itself
|
||||
- nvim-treesitter_ to install parsers for some languages
|
||||
|
||||
Both plugins are stored under the `$XDG_DATA_HOME` directory, the former as a
|
||||
symlink and the latter as a Git submodule.
|
||||
|
||||
As for process isolation, this is achieved inside the tests. We start a
|
||||
headless embedded Neovim instance which we control through MsgPack RPC from
|
||||
inside the test. We can control and probe this process only indirectly, which
|
||||
is awkward, but this is the best solution I could find.
|
||||
|
||||
|
||||
Unit testing
|
||||
============
|
||||
|
||||
We use busted_ for unit testing. A unit is a self-contained module which can
|
||||
be used on its own independent of the editor. Execute `make unit-test` to run
|
||||
unit tests. The `busted` binary must be available on the system `$PATH`.
|
||||
|
||||
End to end testing
|
||||
==================
|
||||
|
||||
End-to-end tests run in a separate Neovim instance which we control via RPC.
|
||||
These are tests which mutate the state of the editor, such as adding
|
||||
highlighting on changes. Execute `make e2e-test` to run all end to end tests.
|
||||
|
||||
Running tests with Neotest-busted
|
||||
=================================
|
||||
|
||||
To run tests the `g:bustedprg` variable must be set to `'./test/busted'`, which
|
||||
is the path to the shim script. If the `exrc` option is set the variable will
|
||||
be set automatically.
|
||||
|
||||
|
||||
|
||||
Design decisions
|
||||
################
|
||||
|
||||
Tables over strings for configuration
|
||||
=====================================
|
||||
|
||||
Strategies are given as a complex table, but a string identifier would have
|
||||
been much more pleasant on the eye. Which of these two is easier to read and
|
||||
write?
|
||||
|
||||
.. code:: lua
|
||||
|
||||
-- This?
|
||||
settings = {
|
||||
strategy = {
|
||||
'global'
|
||||
html = 'local'
|
||||
}
|
||||
}
|
||||
|
||||
-- Or this?
|
||||
settings = {
|
||||
strategy = {
|
||||
require 'ts-rainbow.strategy.global'
|
||||
html = require 'ts-rainbow.strategy.local'
|
||||
}
|
||||
}
|
||||
|
||||
Using strings might seem like the more elegant choice, but it it makes the code
|
||||
more complicated to maintain and less flexible for the user. With tables a
|
||||
user can create a new custom strategy and assign it directly without the need
|
||||
to "register" them first under some name.
|
||||
|
||||
More importantly though, we have unlimited freedom where that table is coming
|
||||
from. Suppose we wanted to add settings to a strategy. With string
|
||||
identifiers we now need much more machinery to connect a string identifier and
|
||||
its settings. On the other hand, we can just call a function with the settings
|
||||
are arguments which returns the strategy table.
|
||||
|
||||
.. code:: lua
|
||||
|
||||
settings = {
|
||||
strategy = {
|
||||
require 'ts-rainbow.strategy.global',
|
||||
-- Function call evaluates to a strategy table
|
||||
latext = my_custom_strategy {
|
||||
option_1 = true,
|
||||
option_2 = 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Strategies
|
||||
##########
|
||||
|
||||
On container nodes
|
||||
==================
|
||||
|
||||
Every query has to define a `container` capture in addition to `opening` and
|
||||
`closing` captures. As humans we understand the code at an abstract level, but
|
||||
Tree-sitter works on a more concrete level. To a human the HTML tag `<div>` is
|
||||
one atomic object, but to Tree-sitter it is actually a container with further
|
||||
elements.
|
||||
|
||||
Consider the following HTML snippet:
|
||||
|
||||
.. code:: html
|
||||
|
||||
<div>
|
||||
Hello
|
||||
</div>
|
||||
|
||||
The tree looks like this (showing anonymous nodes):
|
||||
|
||||
.. code::
|
||||
|
||||
element [0, 0] - [2, 6]
|
||||
start_tag [0, 0] - [0, 5]
|
||||
"<" [0, 0] - [0, 1]
|
||||
tag_name [0, 1] - [0, 4]
|
||||
">" [0, 4] - [0, 5]
|
||||
text [1, 1] - [1, 6]
|
||||
end_tag [2, 0] - [2, 6]
|
||||
"</" [2, 0] - [2, 2]
|
||||
tag_name [2, 2] - [2, 5]
|
||||
">" [2, 5] - [2, 6]
|
||||
|
||||
We want to highlight the lower-level nodes like `tag_name` or `start_tag` and
|
||||
`end_tag`, but we want to base our logic on the higher-level nodes like
|
||||
`element`. The `@container` node will not be highlighted, we use it to
|
||||
determine the nesting level or the relationship to other container nodes.
|
||||
|
||||
|
||||
Determining the level of container node
|
||||
=======================================
|
||||
|
||||
In order to correctly highlight containers we need to know the nesting level of
|
||||
each container relative to the other containers in the document. We can use
|
||||
the order in which matches are returned by the `iter_matches` method of a
|
||||
query. The iterator traverses the document tree in a depth-first manner
|
||||
according to the visitor patter, but matches are created upon exiting a node.
|
||||
|
||||
Let us look at a practical example. Here is a hypothetical tree:
|
||||
|
||||
.. code::
|
||||
|
||||
A
|
||||
├─B
|
||||
│ └─C
|
||||
│ └─D
|
||||
└─E
|
||||
├─F
|
||||
└─G
|
||||
|
||||
The nodes are returned in the following order:
|
||||
|
||||
#) D
|
||||
#) C
|
||||
#) B
|
||||
#) F
|
||||
#) G
|
||||
#) E
|
||||
#) A
|
||||
|
||||
We can only know how deeply nodes are nested relative to one another. We need
|
||||
to build the entire tree structure to know the absolute nesting levels. Here
|
||||
is an algorithm which can build up the tree, it uses the fact that the order of
|
||||
nodes never skips over an ancestor.
|
||||
|
||||
Start with an empty stack `s = []`. For each match `m` do the following:
|
||||
|
||||
#) Keep popping matches off `s` up until we find a match `m'` whose
|
||||
`@container` node is not a descendant of the container node of `m`. Collect
|
||||
the popped matches (excluding `m'`) onto a new stack `s_m` (order does not
|
||||
matter)
|
||||
#) Set `s_m` as the child match stack of `m`
|
||||
#) Add `m` to `s`
|
||||
|
||||
Eventually `s` will only contain root-level matches, i.e. matches of nesting
|
||||
level one. To apply the highlighting we can then traverse the match tree,
|
||||
incrementing the highlighting level by one each time we descend a level.
|
||||
|
||||
The order of matches among siblings in the tree does not matter. The above
|
||||
algorithm uses a stack when collecting children, but any unordered
|
||||
one-dimensional sequence will do. The stack `s` is important for determining
|
||||
the relationship between nodes: since we know that no ancestors will be skipped
|
||||
we can be certain that we can stop checking the stack for descendants of `m`
|
||||
once we encounter the first non-descendant match. Otherwise we would have to
|
||||
compare each match with each other match, which would tank the performance.
|
||||
|
||||
|
||||
The local highlight strategy
|
||||
============================
|
||||
|
||||
Consider the following bit of contrived HTML code:
|
||||
|
||||
.. code:: html
|
||||
|
||||
<div id="Alpha">
|
||||
<div id="Bravo">
|
||||
<div id="Charlie">
|
||||
</div>
|
||||
</div>
|
||||
<div id="Delta">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Supposed the cursor was inside the angle brackets of `Bravo`, which tags
|
||||
should we highlight? From eyeballing the obvious answer is `Alpha`, `Bravo`
|
||||
and `Charlie`. Obviously `Alpha` and `Bravo` both contain the cursor within
|
||||
the range, but how do we know that we need to highlight `Charlie`? `Charlie`
|
||||
is contained inside `Bravo`, which contains the cursor, but on the other hand
|
||||
`Delta` is contained inside `Alpha`, which also contains the cursor. We cannot
|
||||
simply check whether the parent contains the cursor.
|
||||
|
||||
When working with the Tree-sitter API and iterating through matches and
|
||||
captures we have no way of knowing that any of the captures within `Charlie`
|
||||
are contained within `Bravo`. However, due to the order of traversal we do
|
||||
know that `Bravo` is the lowest node to still contain the cursor.
|
||||
|
||||
Therefore we that the first match which contains the cursor is the lowest one.
|
||||
If a match does not contain the cursor we can check whether it is a
|
||||
descendant of the cursor container match.
|
||||
|
||||
|
||||
The problem with nested languages
|
||||
#################################
|
||||
|
||||
The language tree of a buffer is a tree of parsers. Some languages like
|
||||
Markdown can contain other languages, which complicates things.
|
||||
|
||||
|
||||
Foreign extmarks
|
||||
================
|
||||
|
||||
Extmarks move along with the text they belong to. This is generally a good
|
||||
thing, but it can become a problem if we move text from one language to
|
||||
another. Consider the following Markdown code:
|
||||
|
||||
.. code:: markdown
|
||||
|
||||
Hello world
|
||||
|
||||
```lua
|
||||
print {{{{}}}}
|
||||
print {{{{}}}}
|
||||
```
|
||||
|
||||
We can move the cursor to line 4 and move that line out of the Lua block by
|
||||
executing `:move 1` to move it to the second line. However, this will preserve
|
||||
the extmarks and we will end up with Lua delimiter highlighting inside
|
||||
Markdown.
|
||||
|
||||
My solution is on every change to delete all rainbow delimiter extmarks which
|
||||
do not belong to the current language.
|
||||
|
||||
|
||||
Overwritten extmarks
|
||||
====================
|
||||
|
||||
Take the following Markdown code:
|
||||
|
||||
.. code:: markdown
|
||||
|
||||
Hello world
|
||||
|
||||
```c
|
||||
puts("This is an injected language")
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
return ((((((2)))))) + ((((3))))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If we put the cursor on the line with the `puts` statement and move it up one
|
||||
line (`:move -2`) we get the following changes:
|
||||
|
||||
- Markdown
|
||||
- `{ 2, 0, 3, 0 }`
|
||||
|
||||
This means lines 3 and 4 of the Markdown tree have changed; we have changed the
|
||||
contents of the fifth line and added one more line. This is all as expected.
|
||||
However, let us now move the line back down by executing `:move +1`. We get
|
||||
the following changes:
|
||||
|
||||
- Markdown
|
||||
- `{ 3, 0, 15, 0 }`
|
||||
- C
|
||||
- `{ 3, 0, 4, 0 }`
|
||||
|
||||
The changes to the C tree are what we expect. However, the changes to the
|
||||
Markdown tree span the code block as well. This is a problem when we start
|
||||
deleting foreign extmarks (see above). If we work from the outside we wipe out
|
||||
all non-Markdown extmarks in the range, which includes the C extmarks. Then we
|
||||
apply the C extmarks inside the C block, but the C change does not span the
|
||||
entire C tree. Thus we will only apply highlighting to the changed C line, but
|
||||
not the remainder of the C block.
|
||||
|
||||
The solution at the moment is to overwrite the changes of nested languages. If
|
||||
the changes belong to a language tree with parent language we replace all the
|
||||
changes with a range that spans the entire tree for that language.
|
||||
|
||||
|
||||
|
||||
.. _busted: https://lunarmodules.github.io/busted/#defining-tests
|
||||
.. _nvim-treesitter: https://github.com/nvim-treesitter/nvim-treesitter
|
||||
201
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/LICENSE
Normal file
201
config/neovim/store/lazy-plugins/rainbow-delimiters.nvim/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@ -0,0 +1,229 @@
|
||||
.. default-role:: code
|
||||
|
||||
|
||||
###############################
|
||||
Rainbow delimiters for Neovim
|
||||
###############################
|
||||
|
||||
This Neovim plugin provides alternating syntax highlighting (“rainbow
|
||||
parentheses”) for Neovim, powered by `Tree-sitter`_. The goal is to have a
|
||||
hackable plugin which allows for different configuration of queries and
|
||||
strategies, both globally and per file type. Users can override and extend the
|
||||
built-in defaults through their own configuration.
|
||||
|
||||
This is a fork of `nvim-ts-rainbow2`_, which was implemented as a module for
|
||||
`nvim-treessiter`_. However, since nvim-treesitter has deprecated the module
|
||||
system I had to create this standalone plugin.
|
||||
|
||||
|
||||
Installation and setup
|
||||
######################
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Install it like any other Neovim plugin. You will need a Tree-sitter parser
|
||||
for each language you want to use rainbow delimiters with.
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
No configuration is needed to get started, this plugin has reasonable defaults
|
||||
which you can override. Configuration is done by setting entries in the Vim
|
||||
script dictionary `g:rainbow_delimiters`. Here is an example configuration:
|
||||
|
||||
.. code:: 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',
|
||||
\ ],
|
||||
\ }
|
||||
|
||||
The equivalent code in Lua:
|
||||
|
||||
.. code:: 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'],
|
||||
vim = rainbow_delimiters.strategy['local'],
|
||||
},
|
||||
query = {
|
||||
[''] = 'rainbow-delimiters',
|
||||
lua = 'rainbow-blocks',
|
||||
},
|
||||
priority = {
|
||||
[''] = 110,
|
||||
lua = 210,
|
||||
},
|
||||
highlight = {
|
||||
'RainbowDelimiterRed',
|
||||
'RainbowDelimiterYellow',
|
||||
'RainbowDelimiterBlue',
|
||||
'RainbowDelimiterOrange',
|
||||
'RainbowDelimiterGreen',
|
||||
'RainbowDelimiterViolet',
|
||||
'RainbowDelimiterCyan',
|
||||
},
|
||||
}
|
||||
|
||||
Please refer to the `manual`_ for more details. For those who prefer a `setup`
|
||||
function there is the module `rainbow-delimiters.setup` that accepts all the
|
||||
same parameters as `g:rainbow-delimiters`.
|
||||
|
||||
.. code:: lua
|
||||
|
||||
require('rainbow-delimiters.setup').setup {
|
||||
strategy = {
|
||||
-- ...
|
||||
},
|
||||
query = {
|
||||
-- ...
|
||||
},
|
||||
highlight = {
|
||||
-- ...
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Help wanted
|
||||
###########
|
||||
|
||||
There are only so many languages which I understand to the point that I can
|
||||
write queries for them. If you want support for a new language please consider
|
||||
contributing code. See the CONTRIBUTING_ for details.
|
||||
|
||||
|
||||
Status of the plugin
|
||||
####################
|
||||
|
||||
Tree-sitter support in Neovim is still experimental. This plugin and its API
|
||||
should be considered stable insofar as breaking changes will only happen if
|
||||
changes to Neovim necessitates them.
|
||||
|
||||
|
||||
License
|
||||
#######
|
||||
|
||||
Licensed under the Apache-2.0 license. Please see the `LICENSE`_ file for
|
||||
details.
|
||||
|
||||
|
||||
Migrating from nvim-ts-rainbow2
|
||||
###############################
|
||||
|
||||
Rainbow-Delimiters uses different settings than nvim-ts-rainbow2, but
|
||||
converting the configuration is straight-forward. The biggest change is where
|
||||
the settings are stored.
|
||||
|
||||
- Settings are stored in the global variable `g:rainbow-delimiters`, which has
|
||||
the same keys as the old settings
|
||||
- The default strategy and query have index `''` (empty string) instead of `1`
|
||||
- Default highlight groups have the prefix `RainbowDelimiter` instead of
|
||||
`TSRainbow`, e.g. `RainbowDelimiterRed` instead of `TSRainbowRed`
|
||||
- The default query is now called `rainbow-delimiters` instead of
|
||||
`rainbow-parens`
|
||||
- The public Lua module is called `rainbow-delimiters` instead of `ts-rainbow`
|
||||
|
||||
The name of the default query is now `rainbow-delimiters` because for some
|
||||
languages like HTML the notion of "parentheses" does not make any sense. In
|
||||
HTML the only meaningful delimiter is the tag. Hence the generic notion of a
|
||||
"delimiter".
|
||||
|
||||
|
||||
Attribution
|
||||
###########
|
||||
|
||||
This is a fork of a previous Neovim plugin, the original repository is
|
||||
available under https://sr.ht/~p00f/nvim-ts-rainbow/.
|
||||
|
||||
Attributions from the original author
|
||||
=====================================
|
||||
|
||||
Huge thanks to @vigoux, @theHamsta, @sogaiu, @bfredl and @sunjon and
|
||||
@steelsojka for all their help
|
||||
|
||||
|
||||
.. _Tree-sitter: https://tree-sitter.github.io/tree-sitter/
|
||||
.. _nvim-treesitter: https://github.com/nvim-treesitter/nvim-treesitter
|
||||
.. _CONTRIBUTING: CONTRIBUTING.rst
|
||||
.. _LICENSE: LICENSE
|
||||
.. _manual: doc/rainbow-delimiters.txt
|
||||
.. _neovim/neovim#17099: https://github.com/neovim/neovim/pull/17099
|
||||
.. _nvim-ts-rainbow2: https://gitlab.com/HiPhish/nvim-ts-rainbow2
|
||||
.. _nvim-treessiter: https://github.com/nvim-treesitter/nvim-treesitter
|
||||
|
||||
|
||||
Screenshots
|
||||
###########
|
||||
|
||||
Bash
|
||||
====
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/514ed2a2-68a4-427e-aef6-7ac3a02a2ba0
|
||||
:alt: Screenshot of a Bash script with alternating coloured delimiters
|
||||
|
||||
C
|
||||
=
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/45f8e727-d507-43df-b112-a269e7262533
|
||||
:alt: Screenshot of a C program with alternating coloured delimiters
|
||||
|
||||
Common Lisp
|
||||
===========
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/5e7e15bb-a4e3-41e5-b3fc-3c4150ffd252
|
||||
:alt: Screenshot of a Common Lisp program with alternating coloured delimiters
|
||||
|
||||
HTML
|
||||
====
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/371d310c-d5a7-490d-bb55-d3fe4bd8b1a8
|
||||
:alt: Screenshot of an HTML document with alternating coloured delimiters
|
||||
|
||||
Java
|
||||
====
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/bb372051-ec5f-4c0b-a9b9-3cd37edafa4f
|
||||
:alt: Screenshot of a Java program with alternating coloured delimiters
|
||||
|
||||
LaTeX
|
||||
=====
|
||||
|
||||
Using the `rainbow-blocks` query to highlight the entire `\begin` and `\end`
|
||||
instructions.
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/0176cc0d-b729-417e-8f85-c31da70d49f5
|
||||
:alt: Screenshot of a LaTeX document with alternating coloured delimiters
|
||||
|
||||
Lua
|
||||
===
|
||||
|
||||
Using the `rainbow-blocks` query to highlight the entire keywords like
|
||||
`function`, `if`, `else` and `end`.
|
||||
|
||||
.. image:: https://github.com/HiPhish/rainbow-delimiters.nvim/assets/4954650/a915f7e0-b1c9-4af2-ae1d-f2f48aa325e5
|
||||
:alt: Screenshot of a Lua script with alternating coloured delimiters
|
||||
@ -0,0 +1,36 @@
|
||||
.. default-role:: code
|
||||
|
||||
#######################
|
||||
Plans for this plugin
|
||||
#######################
|
||||
|
||||
|
||||
Built-in queries
|
||||
################
|
||||
|
||||
As of version 0.8.3 Neovim can only match one node per query. This is a
|
||||
limitation of Neovim and there is nothing that can be done on this end.
|
||||
|
||||
The global query does not updated the highlighting of injected languages.
|
||||
|
||||
|
||||
Queries which I cannot port
|
||||
===========================
|
||||
|
||||
I do not know enough about the following languages in order to write good
|
||||
queries. Contributions are welcome.
|
||||
|
||||
- devicetree
|
||||
- elm
|
||||
- gdscript
|
||||
- graphql
|
||||
- kotlin
|
||||
- meson
|
||||
- ocaml
|
||||
- ocaml_interface
|
||||
- scala
|
||||
- solidity
|
||||
- sparql
|
||||
- supercollider
|
||||
- svelte
|
||||
- turtle
|
||||
@ -0,0 +1,50 @@
|
||||
" Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
"
|
||||
" Licensed under the Apache License, Version 2.0 (the "License");
|
||||
" you may not use this file except in compliance with the License.
|
||||
" You may obtain a copy of the License at
|
||||
"
|
||||
" http://www.apache.org/licenses/LICENSE-2.0
|
||||
"
|
||||
" Unless required by applicable law or agreed to in writing, software
|
||||
" distributed under the License is distributed on an "AS IS" BASIS,
|
||||
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
" See the License for the specific language governing permissions and
|
||||
" limitations under the License.
|
||||
|
||||
let g:rainbow_delimiters#strategy = {
|
||||
\ 'global': luaeval("require 'rainbow-delimiters.strategy.global'"),
|
||||
\ 'local': luaeval("require 'rainbow-delimiters.strategy.local'"),
|
||||
\ 'noop': luaeval("require 'rainbow-delimiters.strategy.no-op'"),
|
||||
\ }
|
||||
|
||||
" Get the appropriate highlight group for the given level of nesting.
|
||||
function! rainbow_delimiters#hlgroup_at(i)
|
||||
return luaeval("require('rainbow-delimiters').hlgroup_at(_A)", a:i)
|
||||
endfunction
|
||||
|
||||
" Disable highlighting for the given buffer. Buffer number zero means current
|
||||
" buffer.
|
||||
function! rainbow_delimiters#disable(bufnr)
|
||||
call luaeval("require('rainbow-delimiters').disable(_A)", a:bufnr)
|
||||
endfunction
|
||||
|
||||
" Enable highlighting for the given buffer. Buffer number zero means current
|
||||
" buffer.
|
||||
function! rainbow_delimiters#enable(bufnr)
|
||||
call luaeval("require('rainbow-delimiters').enable(_A)", a:bufnr)
|
||||
endfunction
|
||||
|
||||
" Toggle highlighting for the given buffer. Buffer number zero means current
|
||||
" buffer.
|
||||
function! rainbow_delimiters#toggle(bufnr)
|
||||
call luaeval("require('rainbow-delimiters').toggle(_A)", a:bufnr)
|
||||
endfunction
|
||||
|
||||
" Check if highlighting is enabled for the given buffer. Buffer number zero
|
||||
" means current buffer.
|
||||
function! rainbow_delimiters#is_enabled(bufnr)
|
||||
return luaeval("require('rainbow-delimiters').is_enabled(_A)", a:bufnr)
|
||||
endfunction
|
||||
|
||||
" vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -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:
|
||||
@ -0,0 +1,75 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
Copyright 2020-2022 Chinmay Dalal
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
local lib = require 'rainbow-delimiters.lib'
|
||||
|
||||
---Disable rainbow delimiters for a given buffer.
|
||||
---@param bufnr integer Buffer number, zero for current buffer.
|
||||
local function disable(bufnr)
|
||||
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
lib.detach(bufnr)
|
||||
lib.buffers[bufnr] = false
|
||||
end
|
||||
|
||||
---Enable rainbow delimiters for a given buffer.
|
||||
---@param bufnr integer Buffer number, zero for current buffer.
|
||||
local function enable(bufnr)
|
||||
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
lib.buffers[bufnr] = nil
|
||||
lib.attach(bufnr)
|
||||
end
|
||||
|
||||
---Toggle rainbow delimiters for a given buffer.
|
||||
---@param bufnr integer Buffer number, zero for current buffer.
|
||||
local function toggle(bufnr)
|
||||
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
if lib.buffers[bufnr] then
|
||||
disable(bufnr)
|
||||
else
|
||||
enable(bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
---Check if rainbow delimiters are enabled for a given buffer.
|
||||
---@param bufnr integer Buffer number, zero for current buffer.
|
||||
---@return boolean # Whether or not rainbow delimiters is enabled
|
||||
local function is_enabled(bufnr)
|
||||
if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
return lib.buffers[bufnr] ~= nil and lib.buffers[bufnr] ~= false
|
||||
end
|
||||
|
||||
---Public API for use in writing strategies or other custom code.
|
||||
local M = {
|
||||
hlgroup_at = lib.hlgroup_at,
|
||||
---Available default highlight strategies
|
||||
strategy = {
|
||||
---Global highlighting strategy
|
||||
['global'] = require 'rainbow-delimiters.strategy.global',
|
||||
---Local highlighting strategy
|
||||
['local'] = require 'rainbow-delimiters.strategy.local',
|
||||
---Empty highlighting strategy for testing
|
||||
['noop'] = require 'rainbow-delimiters.strategy.no-op',
|
||||
},
|
||||
enable = enable,
|
||||
disable = disable,
|
||||
toggle = toggle,
|
||||
is_enabled = is_enabled,
|
||||
}
|
||||
|
||||
|
||||
return M
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,311 @@
|
||||
---@meta
|
||||
|
||||
|
||||
--# Utility Library #--
|
||||
|
||||
---Strategy to use for highlighting with rainbow-delimiters
|
||||
---Must implement `on_attach`, `on_detach` and `on_reset`
|
||||
---@class rainbow_delimiters.strategy
|
||||
---`on_attach`: setup the highlighting on attach
|
||||
---@field on_attach fun(bufnr: integer, settings: rainbow_delimiters.buffer_settings)
|
||||
---`on_detach`: remove any unneccesary remaining setup on detach
|
||||
---@field on_detach fun(bufnr: integer)
|
||||
---`on_reset`: update the highlighting on reset
|
||||
---@field on_reset fun(bufnr: integer, settings: rainbow_delimiters.buffer_settings)
|
||||
|
||||
---@class (exact) rainbow_delimiters.buffer_settings
|
||||
---@field strategy rainbow_delimiters.strategy
|
||||
---@field parser LanguageTree
|
||||
---@field lang string
|
||||
|
||||
|
||||
--# Config #--
|
||||
|
||||
---Configuration table for rainbow-delimiters
|
||||
---@class (exact) rainbow_delimiters.config
|
||||
---Strategy to use for highlighting
|
||||
---@field strategy rainbow_delimiters.config.strategies?
|
||||
---Query to use for highlighting
|
||||
---@field query rainbow_delimiters.config.queries?
|
||||
---Highlight priority of rainbow delimiters
|
||||
---@field priority rainbow_delimiters.config.priorities?
|
||||
---Highlight colors
|
||||
---@field highlight string[]?
|
||||
---Whitelist for languages to highlight
|
||||
---@field whitelist rainbow_delimiters.language[]?
|
||||
---Blacklist for languages not to highlight
|
||||
---@field blacklist rainbow_delimiters.language[]?
|
||||
---Logging with log file and log level
|
||||
---@field log rainbow_delimiters.logging?
|
||||
|
||||
---@class rainbow_delimiters.config.strategies
|
||||
---@field [''] (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field astro (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field bash (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field c (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field c_sharp (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field clojure (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field commonlisp (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field cpp (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field css (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field cuda (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field cue (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field dart (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field elixir (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field elm (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field fennel (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field fish (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field go (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field haskell (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field hcl (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field html (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field janet_simple (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field java (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field javascript (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field json (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field json5 (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field jsonc (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field jsonnet (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field julia (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field kotlin (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field latex (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field lua (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field luadoc (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field make (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field markdown (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field nim (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field nix (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field perl (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field php (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field python (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field query (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field r (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field racket (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field rasi (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field regex (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field rst (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field ruby (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field rust (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field scheme (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field scss (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field sql (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field starlark (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field templ (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field terraform (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field toml (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field tsx (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field typescript (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field typst (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field verilog (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field vim (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field vimdoc (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field vue (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field yaml (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---@field zig (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
---User defined language, not part of rainbow_delimiters support
|
||||
---@field [string] (rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?)?
|
||||
|
||||
---@class rainbow_delimiters.config.queries
|
||||
---@field [''] (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field astro (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field bash (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field c (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field c_sharp (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field clojure (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field commonlisp (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field cpp (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field css (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field cuda (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field cue (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field dart (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field elixir (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field elm (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field fennel (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field fish (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field go (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field haskell (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field hcl (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field html (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field janet_simple (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field java (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field javascript (('rainbow-delimiters' | 'rainbow-parens' | 'rainbow-delimiters-react' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-parens' | 'rainbow-delimiters-react' | string))?
|
||||
---@field json (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field json5 (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field jsonc (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field jsonnet (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field julia (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field kotlin (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field latex (('rainbow-delimiters' | 'rainbow-blocks' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-blocks' | string))?
|
||||
---@field lua (('rainbow-delimiters' | 'rainbow-blocks' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-blocks' | string))?
|
||||
---@field luadoc (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field make (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field markdown (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field nim (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field nix (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field perl (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field php (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field python (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field query (('rainbow-delimiters' | 'rainbow-blocks' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-blocks' | string))?
|
||||
---@field r (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field racket (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field rasi (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field regex (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field rst (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field ruby (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field rust (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field scheme (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field scss (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field sql (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field starlark (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field templ (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field terraform (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field toml (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field tsx (('rainbow-delimiters' | 'rainbow-parens' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-parens' | string))?
|
||||
---@field typescript (('rainbow-delimiters' | 'rainbow-parens' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-parens' | string))?
|
||||
---@field typst (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field verilog (('rainbow-delimiters' | 'rainbow-blocks' | string) | fun(bufnr: integer): ('rainbow-delimiters' | 'rainbow-blocks' | string))?
|
||||
---@field vim (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field vimdoc (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field vue (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field yaml (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---@field zig (('rainbow-delimiters' | string) | fun(bufnr: integer): ('rainbow-delimiters' | string))?
|
||||
---User defined language, not part of rainbow_delimiters support
|
||||
---@field [string] (string | fun(bufnr: integer): string)?
|
||||
|
||||
---@class rainbow_delimiters.config.priorities
|
||||
---@field [''] (integer | fun(bufnr: integer): integer)?
|
||||
---@field astro (integer | fun(bufnr: integer): integer)?
|
||||
---@field bash (integer | fun(bufnr: integer): integer)?
|
||||
---@field c (integer | fun(bufnr: integer): integer)?
|
||||
---@field c_sharp (integer | fun(bufnr: integer): integer)?
|
||||
---@field clojure (integer | fun(bufnr: integer): integer)?
|
||||
---@field commonlisp (integer | fun(bufnr: integer): integer)?
|
||||
---@field cpp (integer | fun(bufnr: integer): integer)?
|
||||
---@field css (integer | fun(bufnr: integer): integer)?
|
||||
---@field cuda (integer | fun(bufnr: integer): integer)?
|
||||
---@field cue (integer | fun(bufnr: integer): integer)?
|
||||
---@field dart (integer | fun(bufnr: integer): integer)?
|
||||
---@field elixir (integer | fun(bufnr: integer): integer)?
|
||||
---@field elm (integer | fun(bufnr: integer): integer)?
|
||||
---@field fennel (integer | fun(bufnr: integer): integer)?
|
||||
---@field fish (integer | fun(bufnr: integer): integer)?
|
||||
---@field go (integer | fun(bufnr: integer): integer)?
|
||||
---@field haskell (integer | fun(bufnr: integer): integer)?
|
||||
---@field hcl (integer | fun(bufnr: integer): integer)?
|
||||
---@field html (integer | fun(bufnr: integer): integer)?
|
||||
---@field janet_simple (integer | fun(bufnr: integer): integer)?
|
||||
---@field java (integer | fun(bufnr: integer): integer)?
|
||||
---@field javascript (integer | fun(bufnr: integer): integer)?
|
||||
---@field json (integer | fun(bufnr: integer): integer)?
|
||||
---@field json5 (integer | fun(bufnr: integer): integer)?
|
||||
---@field jsonc (integer | fun(bufnr: integer): integer)?
|
||||
---@field jsonnet (integer | fun(bufnr: integer): integer)?
|
||||
---@field julia (integer | fun(bufnr: integer): integer)?
|
||||
---@field kotlin (integer | fun(bufnr: integer): integer)?
|
||||
---@field latex (integer | fun(bufnr: integer): integer)?
|
||||
---@field lua (integer | fun(bufnr: integer): integer)?
|
||||
---@field luadoc (integer | fun(bufnr: integer): integer)?
|
||||
---@field make (integer | fun(bufnr: integer): integer)?
|
||||
---@field markdown (integer | fun(bufnr: integer): integer)?
|
||||
---@field nim (integer | fun(bufnr: integer): integer)?
|
||||
---@field nix (integer | fun(bufnr: integer): integer)?
|
||||
---@field perl (integer | fun(bufnr: integer): integer)?
|
||||
---@field php (integer | fun(bufnr: integer): integer)?
|
||||
---@field python (integer | fun(bufnr: integer): integer)?
|
||||
---@field query (integer | fun(bufnr: integer): integer)?
|
||||
---@field r (integer | fun(bufnr: integer): integer)?
|
||||
---@field racket (integer | fun(bufnr: integer): integer)?
|
||||
---@field rasi (integer | fun(bufnr: integer): integer)?
|
||||
---@field regex (integer | fun(bufnr: integer): integer)?
|
||||
---@field rst (integer | fun(bufnr: integer): integer)?
|
||||
---@field ruby (integer | fun(bufnr: integer): integer)?
|
||||
---@field rust (integer | fun(bufnr: integer): integer)?
|
||||
---@field scheme (integer | fun(bufnr: integer): integer)?
|
||||
---@field scss (integer | fun(bufnr: integer): integer)?
|
||||
---@field sql (integer | fun(bufnr: integer): integer)?
|
||||
---@field starlark (integer | fun(bufnr: integer): integer)?
|
||||
---@field templ (integer | fun(bufnr: integer): integer)?
|
||||
---@field terraform (integer | fun(bufnr: integer): integer)?
|
||||
---@field toml (integer | fun(bufnr: integer): integer)?
|
||||
---@field tsx (integer | fun(bufnr: integer): integer)?
|
||||
---@field typescript (integer | fun(bufnr: integer): integer)?
|
||||
---@field typst (integer | fun(bufnr: integer): integer)?
|
||||
---@field verilog (integer | fun(bufnr: integer): integer)?
|
||||
---@field vim (integer | fun(bufnr: integer): integer)?
|
||||
---@field vimdoc (integer | fun(bufnr: integer): integer)?
|
||||
---@field vue (integer | fun(bufnr: integer): integer)?
|
||||
---@field yaml (integer | fun(bufnr: integer): integer)?
|
||||
---@field zig (integer | fun(bufnr: integer): integer)?
|
||||
---User defined language, not part of rainbow_delimiters support
|
||||
---@field [string] (integer | fun(bufnr: integer): integer)?
|
||||
|
||||
|
||||
---@alias rainbow_delimiters.language
|
||||
---| 'astro'
|
||||
---| 'bash'
|
||||
---| 'c'
|
||||
---| 'c_sharp'
|
||||
---| 'clojure'
|
||||
---| 'commonlisp'
|
||||
---| 'cpp'
|
||||
---| 'css'
|
||||
---| 'cuda'
|
||||
---| 'cue'
|
||||
---| 'dart'
|
||||
---| 'elixir'
|
||||
---| 'elm'
|
||||
---| 'fennel'
|
||||
---| 'fish'
|
||||
---| 'go'
|
||||
---| 'haskell'
|
||||
---| 'hcl'
|
||||
---| 'html'
|
||||
---| 'janet_simple'
|
||||
---| 'java'
|
||||
---| 'javascript'
|
||||
---| 'json'
|
||||
---| 'json5'
|
||||
---| 'jsonc'
|
||||
---| 'jsonnet'
|
||||
---| 'julia'
|
||||
---| 'kotlin'
|
||||
---| 'latex'
|
||||
---| 'lua'
|
||||
---| 'luadoc'
|
||||
---| 'make'
|
||||
---| 'markdown'
|
||||
---| 'nim'
|
||||
---| 'nix'
|
||||
---| 'perl'
|
||||
---| 'php'
|
||||
---| 'python'
|
||||
---| 'query'
|
||||
---| 'r'
|
||||
---| 'racket'
|
||||
---| 'rasi'
|
||||
---| 'regex'
|
||||
---| 'rst'
|
||||
---| 'ruby'
|
||||
---| 'rust'
|
||||
---| 'scheme'
|
||||
---| 'scss'
|
||||
---| 'sql'
|
||||
---| 'starlark'
|
||||
---| 'templ'
|
||||
---| 'terraform'
|
||||
---| 'toml'
|
||||
---| 'tsx'
|
||||
---| 'typescript'
|
||||
---| 'typst'
|
||||
---| 'verilog'
|
||||
---| 'vim'
|
||||
---| 'vimdoc'
|
||||
---| 'vue'
|
||||
---| 'yaml'
|
||||
---| 'zig'
|
||||
---User defined language, not part of rainbow_delimiters support
|
||||
---| string
|
||||
|
||||
---@class (exact) rainbow_delimiters.logging
|
||||
---@field file ('rainbow_delimiters.log' | string)?
|
||||
---@field level integer
|
||||
@ -0,0 +1,107 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
local function get_nested(table, index, key)
|
||||
local result
|
||||
|
||||
-- 1. User setting for file type
|
||||
if vim.g.rainbow_delimiters and vim.g.rainbow_delimiters[index] then
|
||||
result = rawget(vim.g.rainbow_delimiters[index], key)
|
||||
end
|
||||
if result ~= nil then return result end
|
||||
|
||||
-- 2. User setting for fallback
|
||||
if vim.g.rainbow_delimiters and vim.g.rainbow_delimiters[index] then
|
||||
result = rawget(vim.g.rainbow_delimiters[index], '')
|
||||
end
|
||||
if result ~= nil then return result end
|
||||
|
||||
-- 3. Default setting
|
||||
result = rawget(table, key)
|
||||
if result ~= nil then return result end
|
||||
|
||||
result = require('rainbow-delimiters.default')[index][key]
|
||||
return result
|
||||
end
|
||||
|
||||
---Plugin settings lookup table. This table is only used for looking up
|
||||
---values. Set `g:rainbow_delimiters` to change the values.
|
||||
local M = {
|
||||
query = setmetatable({}, {
|
||||
__index = function(table, key)
|
||||
return get_nested(table, 'query', key)
|
||||
end
|
||||
}),
|
||||
strategy = setmetatable({}, {
|
||||
__index = function(table, key)
|
||||
return get_nested(table, 'strategy', key)
|
||||
end
|
||||
}),
|
||||
priority = setmetatable({}, {
|
||||
__index = function(table, key)
|
||||
return get_nested(table, 'priority', key)
|
||||
end
|
||||
}),
|
||||
log = setmetatable({}, {
|
||||
__index = function(table, key)
|
||||
return get_nested(table, 'log', key)
|
||||
end
|
||||
}),
|
||||
enabled_for = function(lang)
|
||||
local conf = vim.g.rainbow_delimiters
|
||||
if not conf then return true end
|
||||
|
||||
local whitelist = conf.whitelist
|
||||
local blacklist = conf.blacklist
|
||||
|
||||
if whitelist then
|
||||
for _, v in ipairs(whitelist) do
|
||||
if v == lang then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
if blacklist then
|
||||
for _, v in ipairs(blacklist) do
|
||||
if v == lang then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
setmetatable(M, {
|
||||
__index = function(table, key)
|
||||
if key == 'highlight' then
|
||||
local highlight
|
||||
|
||||
if vim.g.rainbow_delimiters then
|
||||
highlight = rawget(vim.g.rainbow_delimiters, 'highlight')
|
||||
end
|
||||
if highlight and #highlight > 0 then return highlight end
|
||||
|
||||
highlight = require('rainbow-delimiters.default').highlight
|
||||
return highlight
|
||||
end
|
||||
return rawget(table, key)
|
||||
end,
|
||||
})
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,74 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---Default plugin configuration.
|
||||
---@type rainbow_delimiters.config
|
||||
local M = {
|
||||
---Query names by file type
|
||||
query = {
|
||||
[''] = 'rainbow-delimiters',
|
||||
javascript = 'rainbow-delimiters-react'
|
||||
},
|
||||
---Highlight strategies by file type
|
||||
strategy = {
|
||||
[''] = require 'rainbow-delimiters.strategy.global',
|
||||
},
|
||||
priority = {
|
||||
[''] = 110,
|
||||
},
|
||||
---Event logging settings
|
||||
log = {
|
||||
---Log level of the module, see `:h log_levels`.
|
||||
level = vim.log.levels.WARN,
|
||||
---File name of the log file
|
||||
file = vim.fn.stdpath('log') .. '/rainbow-delimiters.log',
|
||||
},
|
||||
-- Highlight groups in order of display
|
||||
highlight = {
|
||||
-- The colours are intentionally not in the usual order to make
|
||||
-- the contrast between them stronger
|
||||
'RainbowDelimiterRed',
|
||||
'RainbowDelimiterYellow',
|
||||
'RainbowDelimiterBlue',
|
||||
'RainbowDelimiterOrange',
|
||||
'RainbowDelimiterGreen',
|
||||
'RainbowDelimiterViolet',
|
||||
'RainbowDelimiterCyan',
|
||||
}
|
||||
}
|
||||
|
||||
---If the key does not exist in the table fall back on the empty string as
|
||||
---key.
|
||||
local function get_with_fallback(table, key)
|
||||
return rawget(table, key) or rawget(table, '')
|
||||
end
|
||||
|
||||
setmetatable(M.query, {
|
||||
__index = get_with_fallback,
|
||||
})
|
||||
|
||||
setmetatable(M.strategy, {
|
||||
__index = get_with_fallback,
|
||||
})
|
||||
|
||||
setmetatable(M.priority, {
|
||||
__index = get_with_fallback,
|
||||
})
|
||||
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,284 @@
|
||||
---Health check module.
|
||||
local M = {}
|
||||
|
||||
-- In Neovim 0.10 the following functions have been renamed
|
||||
local start = vim.health.start or vim.health.report_start
|
||||
local ok = vim.health.ok or vim.health.report_ok
|
||||
local info = vim.health.info or vim.health.report_info
|
||||
local warn = vim.health.warn or vim.health.report_warn
|
||||
local error = vim.health.error or vim.health.report_error
|
||||
|
||||
local filewritable = vim.fn.filewritable
|
||||
local fnamemodify = vim.fn.fnamemodify
|
||||
|
||||
|
||||
local STRATEGY_ADVICE = "See :h rb-delimiters-strategy for the strategy protocol"
|
||||
local QUERY_ADVICE = "See :h rb-delimiters-query for included standard queries."
|
||||
local HLGROUP_ADVICE = "Consecutive highlight groups make delimiter levels indistinguishable, use another highlight group."
|
||||
local SCHEMA_ADVICE = "This might be a typo, see :h g:rainbow_delimiters for valid entries."
|
||||
|
||||
---Specification of valid options. The key is the name of an option, the value
|
||||
---is either true (no further validation) or a table containing the nested
|
||||
---schema for the option
|
||||
local schema = {
|
||||
strategy = true,
|
||||
query = true,
|
||||
highlight = true,
|
||||
priority = true,
|
||||
blacklist = true,
|
||||
whitelist = true,
|
||||
log = {level = true, file = true},
|
||||
}
|
||||
|
||||
|
||||
---Check whether there is a parser installed for the given language.
|
||||
---@param lang string
|
||||
---@return boolean
|
||||
local function check_parser_installed(lang)
|
||||
local success = pcall(vim.treesitter.language.inspect, lang)
|
||||
return success
|
||||
end
|
||||
|
||||
---Check whether the strategy is a valid strategy.
|
||||
---
|
||||
---This is not a 100% reliable check; we only test the type of the argument and
|
||||
---whether the table has the correct fields, but not what the callback
|
||||
---functions actually do.
|
||||
---@param strategy rainbow_delimiters.strategy | fun(bufnr: integer): rainbow_delimiters.strategy?
|
||||
---@return boolean
|
||||
local function check_strategy(strategy)
|
||||
if type(strategy) == 'function' then
|
||||
local finfo = debug.getinfo(strategy)
|
||||
return finfo.nparams == 0 or finfo.nparams == 1
|
||||
end
|
||||
if type(strategy) == 'table' then
|
||||
if type(strategy.on_attach) ~= 'function' then
|
||||
return false
|
||||
end
|
||||
if type(strategy.on_detach) ~= 'function' then
|
||||
return false
|
||||
end
|
||||
if type(strategy.on_reset) ~= 'function' then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---Check whether the given query is defined for the given language.
|
||||
---@param lang string
|
||||
---@param name string | fun(bufnr: integer): string
|
||||
---@return boolean
|
||||
local function check_query(lang, name)
|
||||
if type(name) == 'function' then
|
||||
local finfo = debug.getinfo(name)
|
||||
return finfo.nparams == 0 or finfo.nparams == 1
|
||||
end
|
||||
if type(name) == 'string' then
|
||||
local query = vim.treesitter.query.get(lang, name)
|
||||
return query ~= nil
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---Check whether the given priority is defined for the given language.
|
||||
---@param priority integer | fun(bufnr: integer): integer
|
||||
---@return boolean
|
||||
local function check_priority(priority)
|
||||
if type(priority) == 'function' then
|
||||
local finfo = debug.getinfo(priority)
|
||||
return finfo.nparams == 0 or finfo.nparams == 1
|
||||
end
|
||||
if type(priority) == 'number' then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param settings rainbow_delimiters.logging
|
||||
local function check_logging(settings)
|
||||
local level, file = settings.level, settings.file
|
||||
if level then
|
||||
-- Note: although the log level is an integer, Lua 5.1 only has the
|
||||
-- number type
|
||||
if type(level) ~= 'number' then
|
||||
error('The log level must be a number', 'See :h vim.log.levels for valid log levels.')
|
||||
else
|
||||
ok('Valid log level.')
|
||||
end
|
||||
end
|
||||
if file then
|
||||
if type(file) ~= 'string' then
|
||||
error('The log file path must be a string')
|
||||
elseif filewritable(file) == 0 then
|
||||
if filewritable(fnamemodify(file, ':h')) == 2 then
|
||||
ok('Valid location for log file.')
|
||||
else
|
||||
local msg = string.format("Cannot write to file '%s'", file)
|
||||
error(msg)
|
||||
end
|
||||
else
|
||||
ok('Valid log file.')
|
||||
end
|
||||
end
|
||||
|
||||
local advice = "This might be a typo, see :h rb-delimiters-logging for valid entries."
|
||||
for option in pairs(settings) do
|
||||
if not schema.log[option] then
|
||||
local msg = string.format("Unknown logging option '%s' in settings", option)
|
||||
warn(msg, advice)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.check()
|
||||
local settings = vim.g.rainbow_delimiters --[[@as rainbow_delimiters.config]]
|
||||
if not settings then
|
||||
return
|
||||
info("No custom configuration; see :h rb-delimiters-setup for information.")
|
||||
end
|
||||
|
||||
local whitelist = settings.whitelist
|
||||
if whitelist then
|
||||
start 'Parsers for whitelisted languages'
|
||||
for _, lang in ipairs(whitelist) do
|
||||
local success = check_parser_installed(lang)
|
||||
if success then
|
||||
local msg = string.format("Parser installed for '%s'", lang)
|
||||
ok(msg)
|
||||
else
|
||||
local msg = string.format("No parser installed for '%s'", lang)
|
||||
warn(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local strategies = settings.strategy
|
||||
if strategies then
|
||||
start 'Custom strategies'
|
||||
for lang, strategy in pairs(strategies) do
|
||||
local has_strategy = check_strategy(strategy)
|
||||
if lang == '' then
|
||||
if has_strategy then
|
||||
local msg = 'Valid custom default strategy.'
|
||||
ok(msg)
|
||||
else
|
||||
local msg = 'Invalid custom default strategy.'
|
||||
error(msg, STRATEGY_ADVICE)
|
||||
end
|
||||
else
|
||||
local has_parser = check_parser_installed(lang)
|
||||
if not has_parser then
|
||||
local msg = string.format("No parser installed for '%s'", lang)
|
||||
error(msg)
|
||||
end
|
||||
if not has_strategy then
|
||||
local msg = string.format("Invalid custom strategy for '%s'", lang)
|
||||
error(msg, STRATEGY_ADVICE)
|
||||
end
|
||||
if has_parser and has_strategy then
|
||||
local msg = string.format("Valid custom strategy for '%s'.", lang)
|
||||
ok(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local queries = settings.query
|
||||
if queries then
|
||||
start 'Custom queries'
|
||||
for lang, query in pairs(queries) do
|
||||
if lang == '' then
|
||||
if query ~= 'rainbow-delimiters' then
|
||||
local msg = string.format(
|
||||
"User-defined default query '%s'\
|
||||
If you meant 'rainbow-delimiters' check for typos",
|
||||
query
|
||||
)
|
||||
ok(msg)
|
||||
else
|
||||
local msg = "Valid custom default query"
|
||||
ok(msg)
|
||||
end
|
||||
else
|
||||
local has_lang = check_parser_installed(lang)
|
||||
local has_query = check_query(lang, query)
|
||||
if not has_lang then
|
||||
local msg = string.format("No parser installed for '%s'.", lang)
|
||||
warn(msg)
|
||||
end
|
||||
if not has_query then
|
||||
local msg = string.format("No query named '%s' for '%s' found.", query, lang)
|
||||
warn(msg, QUERY_ADVICE)
|
||||
end
|
||||
if has_lang and has_query then
|
||||
local msg = string.format("Valid custom query for '%s'", lang)
|
||||
ok(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local priorities = settings.priority
|
||||
if priorities then
|
||||
start 'Custom priorities'
|
||||
for lang, priority in pairs(priorities) do
|
||||
local is_valid_prirority = check_priority(priority)
|
||||
if lang == '' then
|
||||
if is_valid_prirority then
|
||||
local msg = "Valid custom default priority"
|
||||
ok(msg)
|
||||
else
|
||||
local msg = "Invalid custom default priority"
|
||||
error(msg)
|
||||
end
|
||||
else
|
||||
if is_valid_prirority then
|
||||
local msg = string.format("Valid custom priority for '%s'", lang)
|
||||
ok(msg)
|
||||
else
|
||||
local msg = string.format("Invalid custom priority for '%s'", lang)
|
||||
error(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hlgroups = settings.highlight
|
||||
if hlgroups then
|
||||
start 'Custom highlight groups'
|
||||
local previous
|
||||
for _, hlgroup in ipairs(hlgroups) do
|
||||
local has_hlgroup = vim.fn.hlID(hlgroup) ~= 0
|
||||
if has_hlgroup then
|
||||
ok(string.format("Highlight group '%s' defined.", hlgroup))
|
||||
else
|
||||
error(string.format("Highlight group '%s' not defined.", hlgroup))
|
||||
end
|
||||
if previous and hlgroup == previous then
|
||||
local msg = string.format("Consecutive highlight group '%s'", hlgroup)
|
||||
warn(msg, HLGROUP_ADVICE)
|
||||
end
|
||||
previous = hlgroup
|
||||
end
|
||||
end
|
||||
|
||||
local logging = settings.log
|
||||
if logging then
|
||||
start 'Logging settings'
|
||||
check_logging(logging)
|
||||
end
|
||||
|
||||
for option in pairs(settings) do
|
||||
if not schema[option] then
|
||||
local msg = string.format("Unknown option '%s' in settings", option)
|
||||
warn(msg, SCHEMA_ADVICE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,248 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
Copyright 2020-2022 Chinmay Dalal
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
local api = vim.api
|
||||
local get_query = vim.treesitter.query.get
|
||||
local get_parser = vim.treesitter.get_parser
|
||||
local log = require 'rainbow-delimiters.log'
|
||||
local config = require 'rainbow-delimiters.config'
|
||||
local util = require 'rainbow-delimiters.util'
|
||||
|
||||
|
||||
---[ Internal ]----------------------------------------------------------------
|
||||
-- The following symbols should only be used internally. In particular, they
|
||||
-- should not be used by strategies, or else our strategies are using
|
||||
-- undocumented APIs.
|
||||
|
||||
---Private library of shared internal functions and variables.
|
||||
local M = {}
|
||||
|
||||
M.enabled_for = config.enabled_for
|
||||
|
||||
---Per-language namespaces. This table instantiates namespaces on demand, i.e.
|
||||
---a namespace won't exist until we first try to get it from the table.
|
||||
M.nsids = setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
local result = rawget(t, k)
|
||||
if result == nil then
|
||||
result = vim.api.nvim_create_namespace('')
|
||||
rawset(t, k, result)
|
||||
end
|
||||
return result
|
||||
end,
|
||||
-- Note: this will only catch new indices, not assignment to an already
|
||||
-- existing key
|
||||
__newindex = function(_, _, _)
|
||||
error('Table is immutable')
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
---Keeps track of attached buffers. The key is the buffer number and the value
|
||||
---is a table of information about that buffer (e.g. language, strategy,
|
||||
---query). This also makes sure we keep track of all parsers in active use to
|
||||
---prevent them from being garbage-collected.
|
||||
---@type table<integer, rainbow_delimiters.buffer_settings | false>
|
||||
M.buffers = {}
|
||||
|
||||
|
||||
---[ This stuff needs to be re-exported ]--------------------------------------
|
||||
-- The following entries can be used in the public API as well.
|
||||
|
||||
---Fetches the query object for the given language from the settings. If a
|
||||
---buffer number is given it will be used as the current buffer, otherwise the
|
||||
---actual current buffer is used.
|
||||
---
|
||||
---@param lang string Name of the language to get the query for
|
||||
---@param bufnr integer Use this buffer as the current buffer
|
||||
---@return Query? query The query object
|
||||
function M.get_query(lang, bufnr)
|
||||
local name = config['query'][lang]
|
||||
if type(name) == "function" then
|
||||
name = name(bufnr)
|
||||
end
|
||||
local query = get_query(lang, name)
|
||||
|
||||
if not query then
|
||||
log.debug('Query %s not found for %s', name, lang)
|
||||
else
|
||||
log.trace('Query %s found for %s', name, lang)
|
||||
end
|
||||
return query
|
||||
end
|
||||
|
||||
---Apply highlighting to a single node.
|
||||
---@param bufnr integer Buffer which contains the node
|
||||
---@param lang string Language of the node (to group HL into namespaces)
|
||||
---@param node table Node to highlight
|
||||
---@param hlgroup string Name of the highlight group to apply.
|
||||
function M.highlight(bufnr, lang, node, hlgroup)
|
||||
-- range of the capture, zero-indexed
|
||||
local startRow, startCol, endRow, endCol = node:range()
|
||||
|
||||
local start, finish = {startRow, startCol}, {endRow, endCol - 1}
|
||||
local priority = config.priority[lang]
|
||||
if type(priority) == "function" then
|
||||
priority = priority(bufnr)
|
||||
end
|
||||
local opts = {
|
||||
regtype = 'c',
|
||||
inclusive = true,
|
||||
priority = priority,
|
||||
}
|
||||
|
||||
local nsid = M.nsids[lang]
|
||||
|
||||
if vim.api.nvim_buf_is_loaded(bufnr) then
|
||||
vim.highlight.range(bufnr, nsid, hlgroup, start, finish, opts)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Get the appropriate highlight group for the given level of nesting.
|
||||
---@param i integer One-based index into the highlight groups
|
||||
---@return string hlgroup Name of the highlight groups
|
||||
function M.hlgroup_at(i)
|
||||
local hlgroups = config.highlight
|
||||
return hlgroups[(i - 1) % #hlgroups + 1]
|
||||
end
|
||||
|
||||
|
||||
---Clears the reserved Rainbow namespace.
|
||||
---
|
||||
---@param bufnr integer Number of the buffer for which to clear the namespace
|
||||
---@param lang string
|
||||
---@param line_start integer?
|
||||
---@param line_end integer?
|
||||
function M.clear_namespace(bufnr, lang, line_start, line_end)
|
||||
local nsid = M.nsids[lang]
|
||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, nsid, line_start or 0, line_end or -1)
|
||||
end
|
||||
end
|
||||
|
||||
---Start rainbow highlighting for the given buffer
|
||||
---@param bufnr integer
|
||||
function M.attach(bufnr)
|
||||
-- Rainbow delimiters was explicitly disabled for this buffer
|
||||
if M.buffers[bufnr] == false then return end
|
||||
|
||||
local lang = vim.treesitter.language.get_lang(vim.bo[bufnr].ft)
|
||||
if not lang then
|
||||
log.trace('Cannot attach to buffer %d, no parser for %s', bufnr, lang)
|
||||
return
|
||||
end
|
||||
log.trace('Attaching to buffer %d with language %s.', bufnr, lang)
|
||||
|
||||
local settings = M.buffers[bufnr]
|
||||
if settings then
|
||||
-- if M.buffers[bufnr].lang == lang then return end
|
||||
-- TODO: If the language is the same reload the parser
|
||||
if settings.lang == lang then
|
||||
local parser = get_parser(bufnr, lang)
|
||||
local strategy = settings.strategy
|
||||
parser:invalidate(true)
|
||||
parser:parse()
|
||||
strategy.on_reset(bufnr, settings)
|
||||
return
|
||||
end
|
||||
-- The file type of the buffer has changed, so we need to detach first
|
||||
-- before we re-attach
|
||||
M.detach(bufnr)
|
||||
end
|
||||
|
||||
local parser
|
||||
do
|
||||
local success
|
||||
success, parser = pcall(get_parser, bufnr, lang)
|
||||
if not success then return end
|
||||
end
|
||||
|
||||
local strategy
|
||||
do
|
||||
strategy = config.strategy[lang]
|
||||
if type(strategy) == 'function' then
|
||||
strategy = strategy(bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Intentionally abort; the user has explicitly disabled rainbow delimiters
|
||||
-- for this buffer, usually by setting a strategy- or query function which
|
||||
-- returned nil.
|
||||
if not strategy then
|
||||
log.warn('No strategy defined for %s', lang)
|
||||
end
|
||||
if not strategy or strategy == vim.NIL then return end
|
||||
|
||||
parser:register_cbs {
|
||||
---@param bnr integer
|
||||
on_detach = function(bnr)
|
||||
if not M.buffers[bnr] then return end
|
||||
M.detach(bufnr)
|
||||
end,
|
||||
---@param child LanguageTree
|
||||
on_child_removed = function(child)
|
||||
M.clear_namespace(bufnr, child:lang())
|
||||
end,
|
||||
}
|
||||
|
||||
settings = {
|
||||
strategy = strategy,
|
||||
parser = parser,
|
||||
lang = lang
|
||||
}
|
||||
M.buffers[bufnr] = settings
|
||||
|
||||
-- For now we silently discard errors, but in the future we should log
|
||||
-- them.
|
||||
local success, error = pcall(strategy.on_attach, bufnr, settings)
|
||||
if not success then
|
||||
log.error('Error attaching strategy to buffer %d: %s', bufnr, error)
|
||||
M.buffers[bufnr] = nil
|
||||
end
|
||||
end
|
||||
|
||||
---Start rainbow highlighting for the given buffer
|
||||
---@param bufnr integer
|
||||
function M.detach(bufnr)
|
||||
log.trace('Detaching from buffer %d.', bufnr)
|
||||
if not M.buffers[bufnr] then
|
||||
return
|
||||
end
|
||||
|
||||
local strategy = M.buffers[bufnr].strategy
|
||||
local parser = M.buffers[bufnr].parser
|
||||
|
||||
-- Clear all the namespaces for each language
|
||||
util.for_each_child(nil, parser:lang(), parser, function(_, lang)
|
||||
M.clear_namespace(bufnr, lang)
|
||||
end)
|
||||
-- Finally release all resources the parser is holding on to
|
||||
parser:destroy()
|
||||
|
||||
-- For now we silently discard errors, but in the future we should log
|
||||
-- them.
|
||||
local success, error = pcall(strategy.on_detach, bufnr)
|
||||
if not success then
|
||||
log.error('Error detaching strategy from buffer %d: %s', bufnr, error)
|
||||
end
|
||||
M.buffers[bufnr] = nil
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,103 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---Logger module for rainbow delimiters. Logs any message whose log level is
|
||||
---equal to or greater than the log level of the module.
|
||||
local M = {}
|
||||
|
||||
local date = os.date
|
||||
local levels = vim.log.levels
|
||||
local config = require 'rainbow-delimiters.config'
|
||||
|
||||
---Reverse lookup table; maps a log level to its text label
|
||||
local level_str = {}
|
||||
for key, value in pairs(levels) do
|
||||
level_str[value] = key
|
||||
end
|
||||
|
||||
---Dynamically determines the module from which the log function was called.
|
||||
---If it was called from somewhere else return the name of the plugin.
|
||||
---@return string
|
||||
local function get_module()
|
||||
local module = debug.getinfo(4, 'S').source:match('^.+rainbow%-delimiters/(.+).lua$')
|
||||
if not module then
|
||||
return ''
|
||||
end
|
||||
return module:gsub('/', '.')
|
||||
end
|
||||
|
||||
---@param file file*
|
||||
---@param level integer
|
||||
---@param module string
|
||||
---@param message any
|
||||
---@param ... any
|
||||
local function write_log(file, level, module, message, ...)
|
||||
local msg
|
||||
local timestamp = date('%FT%H:%M%z')
|
||||
if type(message) == 'function' then
|
||||
msg = message()
|
||||
else
|
||||
msg = string.format(message, ...)
|
||||
end
|
||||
|
||||
file:write(string.format('%s %s %s %s\n', timestamp, level, module, msg))
|
||||
end
|
||||
|
||||
---@param level integer
|
||||
---@param message any
|
||||
---@param ... any
|
||||
local function log(level, message, ...)
|
||||
if level < config.log.level then return end
|
||||
|
||||
local file = io.open(config.log.file, 'a+')
|
||||
-- Intentional: Silently discard the log if the log file cannot be opened
|
||||
if not file then return end
|
||||
|
||||
-- Wrap inside a pcall to make sure the file gets closed even if an error
|
||||
-- occurs
|
||||
pcall(write_log, file, level_str[level], get_module(), message, ...)
|
||||
file:close()
|
||||
-- Should I also print the message?
|
||||
end
|
||||
|
||||
---Log an error message
|
||||
function M.error(message, ...)
|
||||
log(levels.ERROR, message, ...)
|
||||
end
|
||||
|
||||
---Log a warning message
|
||||
function M.warn(message, ...)
|
||||
log(levels.WARN, message, ...)
|
||||
end
|
||||
|
||||
---Log a tracing message
|
||||
function M.debug(message, ...)
|
||||
log(levels.DEBUG, message, ...)
|
||||
end
|
||||
|
||||
---Log a tracing message
|
||||
function M.trace(message, ...)
|
||||
log(levels.TRACE, message, ...)
|
||||
end
|
||||
|
||||
---Log an info message
|
||||
function M.info(message, ...)
|
||||
log(levels.INFO, message, ...)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,17 @@
|
||||
local M = {}
|
||||
|
||||
---Apply the given configuration to the rainbow-delimiter settings. Will
|
||||
---overwrite existing settings.
|
||||
---
|
||||
---@param opts rainbow_delimiters.config Settings, same format as `vim.g.rainbow_delimiters`
|
||||
function M.setup(opts)
|
||||
vim.g.rainbow_delimiters = opts
|
||||
end
|
||||
|
||||
|
||||
-- Make it possible to call the module directly; for backwards compatibility
|
||||
-- with a previous version of this module.
|
||||
setmetatable(M, {__call = function(_t, opts) M.setup(opts) end})
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,124 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---Helper library for stack-like tables.
|
||||
local M = {}
|
||||
|
||||
---@class (exact) Stack
|
||||
---@field public size fun(self: Stack): integer
|
||||
---@field public peek fun(self: Stack): any
|
||||
---@field public push fun(self: Stack, item: any): Stack
|
||||
---@field public pop fun(self: Stack): any
|
||||
---@field public iter fun(self: Stack): ((fun(i: integer, item: any): integer?, any), Stack, integer)
|
||||
---@field package content any[]
|
||||
|
||||
---The stack metatable.
|
||||
local mt = {}
|
||||
|
||||
---The actual iterator implementation, hidden behind the iter-method.
|
||||
---@param stack Stack
|
||||
---@param i integer
|
||||
---@return integer?
|
||||
---@return any
|
||||
local function iter_stack(stack, i)
|
||||
if i <= 1 then return end
|
||||
return i - 1, stack.content[i - 1]
|
||||
end
|
||||
|
||||
---@param stack Stack
|
||||
---@return string
|
||||
local function stack_tostring(stack)
|
||||
local items = {}
|
||||
for _, item in ipairs(stack.content) do
|
||||
items[#items + 1] = tostring(item)
|
||||
end
|
||||
return string.format('[%s]', table.concat(items, ', '))
|
||||
end
|
||||
|
||||
|
||||
---[ Methods ]-----------------------------------------------------------------
|
||||
|
||||
---Returns the current number of items in the stack.
|
||||
---@param self Stack
|
||||
---@return integer size Current size of the stack
|
||||
local function size(self)
|
||||
return #self.content
|
||||
end
|
||||
|
||||
---Iterate through the content of the stack from top to bottom. Each iteration
|
||||
---returns the current index (one-based, counting from the bottom) and the
|
||||
---current item.
|
||||
---@param self Stack The stack instance
|
||||
---@return fun(i: integer, stack: Stack): integer?, any
|
||||
---@return Stack
|
||||
---@return integer
|
||||
local function iter(self)
|
||||
return iter_stack, self, self:size() + 1
|
||||
end
|
||||
|
||||
---Add a new item to the top of the stack. Modifies the stack in-place.
|
||||
---@param item any The item to push onto the stack
|
||||
---@return Stack stack The stack.
|
||||
local function push(self, item)
|
||||
self.content[self:size() + 1] = item
|
||||
return self
|
||||
end
|
||||
|
||||
---Returns the topmost item of the stack without altering the stack.
|
||||
---@return any top The top-most item.
|
||||
local function peek(self)
|
||||
local result = self.content[self:size()]
|
||||
return result
|
||||
end
|
||||
|
||||
---Returns the topmost item of the stack and removes it from the stack.
|
||||
---@return any top The top-most item.
|
||||
local function pop(self)
|
||||
local n = self:size()
|
||||
local result = self.content[n]
|
||||
self.content[n] = nil
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
---[ Public module interface ]-------------------------------------------------
|
||||
|
||||
---Instantiates a new stack containing the given items, or the empty stack if
|
||||
---the argument is `nil`.
|
||||
---@param items any[]? Array of items in order from bottom to top
|
||||
---@return Stack stack The new stack instance
|
||||
function M.new(items)
|
||||
---@type Stack
|
||||
local result = {
|
||||
content = {},
|
||||
size = size,
|
||||
iter = iter,
|
||||
push = push,
|
||||
pop = pop,
|
||||
peek = peek,
|
||||
}
|
||||
setmetatable(result, mt)
|
||||
for _, item in ipairs(items or {}) do result:push(item) end
|
||||
return result
|
||||
end
|
||||
|
||||
---[ Metamethods ]-------------------------------------------------------------
|
||||
mt.__tostring = stack_tostring
|
||||
|
||||
return M
|
||||
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,75 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---Strategy decorator which makes your delimiters change colours like Christmas
|
||||
---lights. This module is meant as a joke and will not be loaded by default
|
||||
---with the rest of the plugin.
|
||||
local M = {}
|
||||
|
||||
local uv = vim.loop
|
||||
local lib = require 'rainbow-delimiters.lib'
|
||||
local original_hlgroup_at = lib.hlgroup_at
|
||||
|
||||
|
||||
local counter = 0
|
||||
|
||||
---Wrapper around the original function which applies some offset to the index.
|
||||
---@param i integer
|
||||
---@return string hlgroup
|
||||
local function patched_hlgroup_at(i)
|
||||
return original_hlgroup_at(counter + i)
|
||||
end
|
||||
|
||||
---Wraps the given strategy with a new strategy that switches colours like a
|
||||
---chain of Christmas lights.
|
||||
---@param strategy rainbow_delimiters.strategy The original strategy
|
||||
---@param delay integer? Time between switches in milliseconds (default 500)
|
||||
---@return rainbow_delimiters.strategy christmas_lights A new strategy object
|
||||
function M.lights(strategy, delay)
|
||||
delay = delay or 500
|
||||
local timer = uv.new_timer()
|
||||
|
||||
---@param bufnr integer
|
||||
---@param settings rainbow_delimiters.buffer_settings
|
||||
local function on_attach(bufnr, settings)
|
||||
local function blink()
|
||||
counter = counter + 1
|
||||
local function callback()
|
||||
lib.hlgroup_at = patched_hlgroup_at
|
||||
strategy.on_reset(bufnr, lib.buffers[bufnr])
|
||||
lib.hlgroup_at = original_hlgroup_at
|
||||
end
|
||||
vim.schedule(callback)
|
||||
end
|
||||
timer:start(0, delay, blink)
|
||||
strategy.on_attach(bufnr, settings)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
local function on_detach(bufnr)
|
||||
timer:stop()
|
||||
strategy.on_detach(bufnr)
|
||||
end
|
||||
|
||||
return {
|
||||
strategy = strategy,
|
||||
on_attach = on_attach,
|
||||
on_detach = on_detach,
|
||||
on_reset = strategy.on_reset,
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,300 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
Copyright 2020-2022 Chinmay Dalal
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
local Stack = require 'rainbow-delimiters.stack'
|
||||
local lib = require 'rainbow-delimiters.lib'
|
||||
local util = require 'rainbow-delimiters.util'
|
||||
local log = require 'rainbow-delimiters.log'
|
||||
|
||||
|
||||
---Strategy which highlights the entire buffer.
|
||||
local M = {}
|
||||
|
||||
---Changes are range objects and come in two variants: one with four entries and
|
||||
---one with six entries. We only want the four-entry variant. See
|
||||
---`:h TSNode:range()`
|
||||
---@param change integer[]
|
||||
---@return integer[]
|
||||
local function normalize_change(change)
|
||||
local result
|
||||
if #change == 4 then
|
||||
result = change
|
||||
elseif #change == 6 then
|
||||
result = {change[1], change[2], change[4], change[5]}
|
||||
else
|
||||
result = {}
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param lang string
|
||||
---@param matches Stack
|
||||
---@param level integer
|
||||
local function highlight_matches(bufnr, lang, matches, level)
|
||||
local hlgroup = lib.hlgroup_at(level)
|
||||
for _, match in matches:iter() do
|
||||
for _, delimiter in match.delimiter:iter() do lib.highlight(bufnr, lang, delimiter, hlgroup) end
|
||||
highlight_matches(bufnr, lang, match.children, level + 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Create a new empty match_record
|
||||
---@return table
|
||||
local function new_match_record()
|
||||
return {
|
||||
delimiter = Stack.new(),
|
||||
children = Stack.new(),
|
||||
}
|
||||
end
|
||||
|
||||
---Update highlights for a range. Called every time text is changed.
|
||||
---@param bufnr integer Buffer number
|
||||
---@param changes table List of node ranges in which the changes occurred
|
||||
---@param tree TSTree TS tree
|
||||
---@param lang string Language
|
||||
local function update_range(bufnr, changes, tree, lang)
|
||||
log.debug('Updated range with changes %s', vim.inspect(changes))
|
||||
|
||||
if not lib.enabled_for(lang) then return end
|
||||
if vim.fn.pumvisible() ~= 0 or not lang then return end
|
||||
|
||||
local query = lib.get_query(lang, bufnr)
|
||||
if not query then return end
|
||||
|
||||
local matches = Stack.new()
|
||||
|
||||
for _, change in ipairs(changes) do
|
||||
-- This is the match record, it lists all the relevant nodes from
|
||||
-- each match.
|
||||
---@type table?
|
||||
local match_record
|
||||
local root_node = tree:root()
|
||||
local start_row, end_row = change[1], change[3] + 1
|
||||
lib.clear_namespace(bufnr, lang, start_row, end_row)
|
||||
|
||||
for qid, node, _ in query:iter_captures(root_node, bufnr, start_row, end_row) do
|
||||
local name = query.captures[qid]
|
||||
-- check for 'delimiter' first, since that should be the most
|
||||
-- common name
|
||||
if name == 'delimiter' and match_record then
|
||||
match_record.delimiter:push(node)
|
||||
elseif name == 'container' and not match_record then
|
||||
match_record = new_match_record()
|
||||
elseif name == 'container' then
|
||||
-- temporarily push the match_record to matches to be retrieved
|
||||
-- later, since we haven't closed it yet
|
||||
matches:push(match_record)
|
||||
match_record = new_match_record()
|
||||
-- since we didn't close the previous match_record, it must
|
||||
-- mean that the current match_record has it as an ancestor
|
||||
match_record.has_ancestor = true
|
||||
elseif name == 'sentinel' and match_record then
|
||||
-- if we see the sentinel, then we are done with the current
|
||||
-- container
|
||||
if match_record.has_ancestor then
|
||||
local prev_match_record = matches:pop()
|
||||
if prev_match_record then
|
||||
-- since we have an ancestor, it has to be the last
|
||||
-- element of the stack
|
||||
prev_match_record.children:push(match_record)
|
||||
match_record = prev_match_record
|
||||
else
|
||||
-- since match_record.has_ancestor was true, we shouldn't
|
||||
-- be able to get to here unless something went wrong
|
||||
-- with the queries or treesitter itself
|
||||
log.error([[You are missing a @container,
|
||||
which should be impossible!
|
||||
Please double check the queries.]])
|
||||
end
|
||||
else
|
||||
-- if match_record doesn't have an ancestor, the sentinel
|
||||
-- means that we are done with it
|
||||
matches:push(match_record)
|
||||
match_record = nil
|
||||
end
|
||||
elseif (name == 'delimiter' or name == 'sentinel') and not match_record then
|
||||
log.error([[You query got the capture name %s.
|
||||
But it didn't come with a container, which should be impossible!
|
||||
Please double check your queries.]], name)
|
||||
end -- do nothing with other capture names
|
||||
end
|
||||
if match_record then
|
||||
-- we might have a dangling match_record, so we push it back into
|
||||
-- matches
|
||||
-- this should only happen when the query is on a proper subset
|
||||
-- of the full tree (usually just one line)
|
||||
matches:push(match_record)
|
||||
end
|
||||
end
|
||||
|
||||
-- when we capture on a row and not the full tree, we get the previous
|
||||
-- containers (on earlier rows) included in the above, but not the
|
||||
-- delimiters and sentinels from them, so we push them up as long as
|
||||
-- we know they have an ancestor
|
||||
local last_match = matches:pop()
|
||||
while last_match and last_match.has_ancestor do
|
||||
local prev_match = matches:pop()
|
||||
|
||||
if prev_match then
|
||||
prev_match.children:push(last_match)
|
||||
else
|
||||
log.error('You are in what should be an unreachable position.')
|
||||
end
|
||||
last_match = prev_match
|
||||
end
|
||||
matches:push(last_match)
|
||||
|
||||
highlight_matches(bufnr, lang, matches, 1)
|
||||
end
|
||||
|
||||
---Update highlights for every tree in given buffer.
|
||||
---@param bufnr integer # Buffer number
|
||||
---@param parser LanguageTree
|
||||
local function full_update(bufnr, parser)
|
||||
log.debug('Performing full updated on buffer %d', bufnr)
|
||||
local function callback(tree, sub_parser)
|
||||
local changes = {{tree:root():range()}}
|
||||
update_range(bufnr, changes, tree, sub_parser:lang())
|
||||
end
|
||||
|
||||
parser:for_each_tree(callback)
|
||||
end
|
||||
|
||||
|
||||
---Sets up all the callbacks and performs an initial highlighting
|
||||
---@param bufnr integer # Buffer number
|
||||
---@param parser LanguageTree
|
||||
---@param start_parent_lang string? # Parent language or nil
|
||||
local function setup_parser(bufnr, parser, start_parent_lang)
|
||||
log.debug('Setting up parser for buffer %d', bufnr)
|
||||
|
||||
util.for_each_child(start_parent_lang, parser:lang(), parser, function(p, lang, parent_lang)
|
||||
log.debug("Setting up parser for '%s' in buffer %d", lang, bufnr)
|
||||
-- Skip languages which are not supported, otherwise we get a
|
||||
-- nil-reference error
|
||||
if not lib.get_query(lang, bufnr) then return end
|
||||
|
||||
p:register_cbs {
|
||||
---@param changes table
|
||||
---@param tree TSTree
|
||||
on_changedtree = function(changes, tree)
|
||||
log.trace('Changed tree in buffer %d with languages %s', bufnr, lang)
|
||||
-- HACK: As of Neovim v0.9.1 there is no way of unregistering a
|
||||
-- callback, so we use this check to abort
|
||||
if not lib.buffers[bufnr] then return end
|
||||
|
||||
-- HACK: changes can accidentally overwrite highlighting in injected code
|
||||
-- blocks.
|
||||
if not parent_lang then
|
||||
-- If we have no parent language, then we use changes, otherwise we use the
|
||||
-- whole tree's range.
|
||||
-- Normalize the changes object if we have no parent language (the one we
|
||||
-- get from on_changedtree)
|
||||
changes = vim.tbl_map(normalize_change, changes)
|
||||
elseif parent_lang ~= lang and changes[1] then
|
||||
-- We have a parent language, so we are in an injected language code
|
||||
-- block, thus we update all of the current code block
|
||||
changes = {{tree:root():range()}}
|
||||
else
|
||||
-- some languages (like rust) use injections of the language itself for
|
||||
-- certain functionality (e.g., macros in rust). For these the
|
||||
-- highlighting will be updated by the non-injected language part of the
|
||||
-- code.
|
||||
changes = {}
|
||||
end
|
||||
|
||||
-- If a line has been moved from another region it will still carry with it
|
||||
-- the extmarks from the old region. We need to clear all extmarks which
|
||||
-- do not belong to the current language
|
||||
for _, change in ipairs(changes) do
|
||||
for key, nsid in pairs(lib.nsids) do
|
||||
if key ~= lang then
|
||||
-- HACK: changes in the main language sometimes need to overwrite
|
||||
-- highlighting on one more line
|
||||
local line_end = change[3] + (parent_lang and 0 or 1)
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, nsid, change[1], line_end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- only update highlighting if we have changes
|
||||
if changes[1] then
|
||||
update_range(bufnr, changes, tree, lang)
|
||||
end
|
||||
|
||||
-- HACK: Since we update the whole tree when we have a parent
|
||||
-- language, we need to make sure to then update all children
|
||||
-- too, even if there is no change in them. This shouldn't
|
||||
-- affect performance, since it only affects code nested at
|
||||
-- least 2 injection languages deep.
|
||||
if parent_lang then
|
||||
local children = p:children()
|
||||
for child_lang, child in pairs(children) do
|
||||
if lang == child_lang then return end
|
||||
child:for_each_tree(function(child_tree, child_p)
|
||||
local child_changes = {{child_tree:root():range()}}
|
||||
|
||||
-- we don't need to remove old extmarks, since
|
||||
-- the above code will handle that correctly
|
||||
-- already, but we might have accidentally
|
||||
-- removed extmarks that we need to set again
|
||||
update_range(bufnr, child_changes, child_tree, child_p:lang())
|
||||
end)
|
||||
end
|
||||
end
|
||||
end,
|
||||
-- New languages can be added into the text at some later time, e.g.
|
||||
-- code snippets in Markdown
|
||||
---@param child LanguageTree
|
||||
on_child_added = function(child)
|
||||
setup_parser(bufnr, child, lang)
|
||||
end,
|
||||
}
|
||||
log.trace("Done with setting up parser for '%s' in buffer %d", lang, bufnr)
|
||||
end)
|
||||
|
||||
full_update(bufnr, parser)
|
||||
end
|
||||
|
||||
|
||||
---on_attach implementation for the global strategy
|
||||
---@param bufnr integer
|
||||
---@param settings rainbow_delimiters.buffer_settings
|
||||
function M.on_attach(bufnr, settings)
|
||||
log.trace('global strategy on_attach')
|
||||
local parser = settings.parser
|
||||
setup_parser(bufnr, parser, nil)
|
||||
end
|
||||
|
||||
---on_detach implementation for the global strategy
|
||||
---@param _bufnr integer
|
||||
function M.on_detach(_bufnr)
|
||||
end
|
||||
|
||||
---on_reset implementation for the global strategy
|
||||
---@param bufnr integer
|
||||
---@param settings rainbow_delimiters.buffer_settings
|
||||
function M.on_reset(bufnr, settings)
|
||||
log.trace('global strategy on_reset')
|
||||
full_update(bufnr, settings.parser)
|
||||
end
|
||||
|
||||
return M --[[@as rainbow_delimiters.strategy]]
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,338 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
local Stack = require 'rainbow-delimiters.stack'
|
||||
local lib = require 'rainbow-delimiters.lib'
|
||||
local log = require 'rainbow-delimiters.log'
|
||||
local util = require 'rainbow-delimiters.util'
|
||||
local api = vim.api
|
||||
local ts = vim.treesitter
|
||||
|
||||
---Highlight strategy which highlights the sub-tree of the buffer which
|
||||
---contains the cursor. Re-computes -highlights when the buffer contents change
|
||||
---or when the cursor is moved.
|
||||
local M = {}
|
||||
|
||||
-- Implementation note: This strategy uses a two-step process: on every change
|
||||
-- to the document tree we compute the match tree and cache it, then when the
|
||||
-- cursor moves we use the cached match tree and the current cursor position to
|
||||
-- decide which matches to highlight.
|
||||
--
|
||||
-- The document tree changes rarely, so there is no need to re-compute the
|
||||
-- match tree every time the cursor moves.
|
||||
|
||||
|
||||
---Cache of match trees, maps a buffer number to its match tree. We compute
|
||||
---the match tree on every change, so that when the cursor moves without
|
||||
---changing the tree we don't need to re-compute it.
|
||||
---
|
||||
---Each match tree maps a language and TS Tree to the corresponding match tree.
|
||||
---We need TS Tree because there might be multiple trees per buffer, such as a
|
||||
---Markdown buffer which contains multiple code blocks.
|
||||
local match_trees = {}
|
||||
|
||||
---Reusable autogroup for events in this strategy.
|
||||
---@type integer
|
||||
local augroup = api.nvim_create_augroup('TSRainbowLocalCursor', {})
|
||||
|
||||
|
||||
---Highlights a single match with the given highlight group
|
||||
---@param bufnr integer
|
||||
---@param lang string
|
||||
---@param match table
|
||||
---@param hlgroup string
|
||||
local function highlight_match(bufnr, lang, match, hlgroup)
|
||||
for _, delimiter in match.delimiter:iter() do lib.highlight(bufnr, lang, delimiter, hlgroup) end
|
||||
end
|
||||
|
||||
---Highlights all matches and their children on the stack of matches. All
|
||||
---matches must be on the same level of the match tree.
|
||||
---
|
||||
---@param bufnr integer Number of the buffer
|
||||
---@param matches Stack Stack of matches
|
||||
---@param level integer Level of the matches
|
||||
local function highlight_matches(bufnr, lang, matches, level)
|
||||
local hlgroup = lib.hlgroup_at(level)
|
||||
for _, match in matches:iter() do
|
||||
highlight_match(bufnr, lang, match, hlgroup)
|
||||
highlight_matches(bufnr, lang, match.children, level + 1)
|
||||
end
|
||||
end
|
||||
|
||||
---Finds a match (and its level) in the match tree whose container node is the
|
||||
---given container node.
|
||||
---@param matches Stack
|
||||
---@param container TSNode
|
||||
---@param level integer
|
||||
---@return table
|
||||
---@return integer
|
||||
---If no match is found, return nil.
|
||||
---@overload fun(matches: Stack, container: TSNode, level: integer)
|
||||
local function find_container(matches, container, level)
|
||||
for _, match in matches:iter() do
|
||||
if match.container == container then return match, level end
|
||||
local result, final_level = find_container(match.children, container, level + 1)
|
||||
if result then return result, final_level end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a new empty match_record with an optionally set container
|
||||
---@param container TSNode
|
||||
---@return table
|
||||
local function new_match_record(container)
|
||||
return {
|
||||
container = container,
|
||||
delimiter = Stack.new(),
|
||||
children = Stack.new(),
|
||||
}
|
||||
end
|
||||
|
||||
---Assembles the match tree, usually called after the document tree has
|
||||
---changed.
|
||||
---@param bufnr integer Buffer number
|
||||
---@param changes table List of node ranges in which the changes occurred
|
||||
---@param tree TSTree TS tree
|
||||
---@param lang string Language
|
||||
---@return Stack?
|
||||
local function build_match_tree(bufnr, changes, tree, lang)
|
||||
if not lib.enabled_for(lang) then return end
|
||||
|
||||
local query = lib.get_query(lang, bufnr)
|
||||
if not query then return end
|
||||
|
||||
local matches = Stack.new()
|
||||
|
||||
for _, change in ipairs(changes) do
|
||||
-- This is the match record, it lists all the relevant nodes from
|
||||
-- each match.
|
||||
---@type table?
|
||||
local match_record
|
||||
local root_node = tree:root()
|
||||
local start_row, end_row = change[1], change[3] + 1
|
||||
lib.clear_namespace(bufnr, lang, start_row, end_row)
|
||||
for qid, node, _ in query:iter_captures(root_node, bufnr, start_row, end_row) do
|
||||
local name = query.captures[qid]
|
||||
-- check for 'delimiter' first, since that should be the most
|
||||
-- common name
|
||||
if name == 'delimiter' and match_record then
|
||||
match_record.delimiter:push(node)
|
||||
elseif name == 'container' and not match_record then
|
||||
match_record = new_match_record(node)
|
||||
elseif name == 'container' then
|
||||
local prev_match_record = match_record
|
||||
-- temporarily push the match_record to matches to be retrieved
|
||||
-- later, since we haven't closed it yet
|
||||
matches:push(match_record)
|
||||
match_record = new_match_record(node)
|
||||
-- since we didn't close the previous match_record, it must
|
||||
-- mean that the current match_record has it as an ancestor
|
||||
match_record.ancestor = prev_match_record
|
||||
elseif name == 'sentinel' and match_record then
|
||||
-- if we see the sentinel, then we are done with the current
|
||||
-- container
|
||||
if match_record.ancestor then
|
||||
local prev_match_record = matches:pop()
|
||||
if prev_match_record then
|
||||
-- since we have an ancestor, it has to be the last
|
||||
-- element of the stack
|
||||
prev_match_record.children:push(match_record)
|
||||
match_record = prev_match_record
|
||||
else
|
||||
-- since match_record.has_ancestor was true, we shouldn't
|
||||
-- be able to get to here unless something went wrong
|
||||
-- with the queries or treesitter itself
|
||||
log.error([[You are missing a @container,
|
||||
which should be impossible!
|
||||
Please double check the queries.]])
|
||||
end
|
||||
else
|
||||
-- if match_record doesn't have an ancestor, the sentinel
|
||||
-- means that we are done with it
|
||||
matches:push(match_record)
|
||||
match_record = nil
|
||||
end
|
||||
elseif (name == 'delimiter' or name == 'sentinel') and not match_record then
|
||||
log.error([[You query got the capture name: %s.
|
||||
But it didn't come with a container, which should be impossible!
|
||||
Please double check your queries.]], name)
|
||||
end -- do nothing with other capture names
|
||||
end
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param tree TSTree
|
||||
---@param lang string
|
||||
local function update_local(bufnr, tree, lang)
|
||||
if not lib.enabled_for(lang) then return end
|
||||
local query = lib.get_query(lang, bufnr)
|
||||
if not query then return end
|
||||
|
||||
-- Find the lowest container node which contains the cursor
|
||||
local cursor_container
|
||||
do
|
||||
local curpos = api.nvim_win_get_cursor(0)
|
||||
-- The order of traversal guarantees that the first match which
|
||||
-- contains the cursor is also the lowest one.
|
||||
for _, match in query:iter_matches(tree:root(), bufnr, 0, -1) do
|
||||
if cursor_container then break end
|
||||
for id, node in pairs(match) do
|
||||
local name = query.captures[id]
|
||||
if name == 'container' and ts.is_in_node_range(node, curpos[1] - 1, curpos[2]) then
|
||||
cursor_container = node
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not cursor_container then return end
|
||||
|
||||
local matches_lang = match_trees[bufnr][lang]
|
||||
if not matches_lang then
|
||||
log.debug("Did not build any matches Stack for language '%s'", lang)
|
||||
return
|
||||
end
|
||||
local matches = matches_lang[tree]
|
||||
if not matches then
|
||||
-- Note: vim.inspect(tree:root():range()) errors, so we need
|
||||
-- to make it into a table instead of a list of numbers
|
||||
log.debug("Did not build any matches Stack for tree '%s'", vim.inspect({tree:root():range()}))
|
||||
return
|
||||
end
|
||||
|
||||
-- Find the correct container in the match tree
|
||||
local cursor_match, level = find_container(matches, cursor_container, 1)
|
||||
if not cursor_match then return end
|
||||
|
||||
-- Highlight the container match and everything below
|
||||
highlight_matches(bufnr, lang, Stack.new {cursor_match}, level)
|
||||
|
||||
-- Starting with the cursor match travel up and highlight every ancestor as
|
||||
-- well
|
||||
local ancestor = cursor_match.ancestor
|
||||
level = level - 1
|
||||
while ancestor do
|
||||
highlight_match(bufnr, lang, ancestor, lib.hlgroup_at(level))
|
||||
ancestor, level = ancestor.ancestor, level - 1
|
||||
end
|
||||
end
|
||||
|
||||
---Callback function to re-highlight the buffer according to the current cursor
|
||||
---position.
|
||||
---@param bufnr integer
|
||||
---@param parser LanguageTree
|
||||
local function local_rainbow(bufnr, parser)
|
||||
parser:for_each_tree(function(tree, sub_parser)
|
||||
update_local(bufnr, tree, sub_parser:lang())
|
||||
end)
|
||||
end
|
||||
|
||||
---Sets up all the callbacks and performs an initial highlighting
|
||||
---@param bufnr integer # Buffer number
|
||||
---@param parser LanguageTree
|
||||
local function setup_parser(bufnr, parser)
|
||||
log.debug('Setting up parser for buffer %d', bufnr)
|
||||
util.for_each_child(nil, parser:lang(), parser, function(p, lang, _parent_lang)
|
||||
log.debug("Setting up parser for '%s' in buffer %d", lang, bufnr)
|
||||
-- Skip languages which are not supported, otherwise we get a
|
||||
-- nil-reference error
|
||||
if not lib.get_query(lang, bufnr) then return end
|
||||
p:register_cbs {
|
||||
---@param _changes table
|
||||
---@param tree TSTree
|
||||
on_changedtree = function(_changes, tree)
|
||||
-- HACK: As of Neovim v0.9.1 there is no way of unregistering a
|
||||
-- callback, so we use this check to abort
|
||||
if not lib.buffers[bufnr] then return end
|
||||
|
||||
if vim.fn.pumvisible() ~= 0 then return end
|
||||
-- Ideally we would only rebuild the parts of the tree that have changed,
|
||||
-- but this doesn't work, so we will rebuild the entire tree
|
||||
-- instead.
|
||||
local fake_changes = {
|
||||
{tree:root():range()}
|
||||
}
|
||||
match_trees[bufnr][lang] = match_trees[bufnr][lang] or {}
|
||||
match_trees[bufnr][lang][tree] = build_match_tree(bufnr, fake_changes, tree, lang)
|
||||
-- Re-highlight after the change
|
||||
local_rainbow(bufnr, p)
|
||||
end,
|
||||
-- New languages can be added into the text at some later time, e.g.
|
||||
-- code snippets in Markdown
|
||||
---@param child LanguageTree
|
||||
on_child_added = function(child)
|
||||
setup_parser(bufnr, child)
|
||||
end,
|
||||
}
|
||||
log.trace("Done with setting up parser for '%s' in buffer %d", lang, bufnr)
|
||||
end)
|
||||
end
|
||||
|
||||
---on_attach implementation for the local strategy
|
||||
---@param bufnr integer
|
||||
---@param settings rainbow_delimiters.buffer_settings
|
||||
function M.on_attach(bufnr, settings)
|
||||
local parser = settings.parser
|
||||
setup_parser(bufnr, parser)
|
||||
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
group = augroup,
|
||||
buffer = bufnr,
|
||||
callback = function(args)
|
||||
util.for_each_child(nil, parser:lang(), parser, function(_, lang, _)
|
||||
lib.clear_namespace(bufnr, lang)
|
||||
end)
|
||||
local_rainbow(args.buf, parser)
|
||||
end
|
||||
})
|
||||
|
||||
-- Build up the initial match tree
|
||||
match_trees[bufnr] = {}
|
||||
parser:for_each_tree(function(tree, sub_parser)
|
||||
local sub_lang = sub_parser:lang()
|
||||
local changes = {
|
||||
{tree:root():range()}
|
||||
}
|
||||
match_trees[bufnr][sub_lang] = match_trees[bufnr][sub_lang] or {}
|
||||
match_trees[bufnr][sub_lang][tree] = build_match_tree(bufnr, changes, tree, sub_lang)
|
||||
end)
|
||||
local_rainbow(bufnr, parser)
|
||||
end
|
||||
|
||||
---on_detach implementation for the local strategy
|
||||
---@param bufnr integer
|
||||
function M.on_detach(bufnr)
|
||||
-- Uninstall autocommand and delete cached match tree
|
||||
api.nvim_clear_autocmds {
|
||||
buffer = bufnr,
|
||||
group = augroup,
|
||||
}
|
||||
match_trees[bufnr] = nil
|
||||
end
|
||||
|
||||
---on_reset implementation for the local strategy
|
||||
---@param bufnr integer
|
||||
---@param settings rainbow_delimiters.buffer_settings
|
||||
function M.on_reset(bufnr, settings)
|
||||
local parser = settings.parser
|
||||
local_rainbow(bufnr, parser)
|
||||
end
|
||||
|
||||
return M --[[@as rainbow_delimiters.strategy]]
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,39 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---A dummy strategy which does nothing; can be used in testing.
|
||||
local M = {}
|
||||
|
||||
---on_attach implementation for the noop strategy
|
||||
---@param _bufnr integer
|
||||
---@param _settings rainbow_delimiters.buffer_settings
|
||||
M.on_attach = function(_bufnr, _settings)
|
||||
end
|
||||
|
||||
---on_detach implementation for the noop strategy
|
||||
---@param _bufnr integer
|
||||
M.on_detach = function(_bufnr)
|
||||
end
|
||||
|
||||
---on_reset implementation for the noop strategy
|
||||
---@param _bufnr integer
|
||||
---@param _settings rainbow_delimiters.buffer_settings
|
||||
M.on_reset = function(_bufnr, _settings)
|
||||
end
|
||||
|
||||
return M --[[@as rainbow_delimiters.strategy]]
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,51 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---A strategy decorator; the decorated strategy keeps track of all currently
|
||||
---attached buffers. Thew new strategy has the following fields:
|
||||
---
|
||||
--- - strategy The wrapped strategy object
|
||||
--- - buffers Table mapping of buffer number to buffer settings
|
||||
--- - attachments Number of currently active attachments
|
||||
---
|
||||
---@param strategy table
|
||||
local function track(strategy)
|
||||
local buffers = {}
|
||||
local attachments = {0} -- Table because I want to pass it by reference
|
||||
|
||||
return {
|
||||
strategy = strategy,
|
||||
buffers = buffers,
|
||||
attachments = attachments,
|
||||
on_attach = function(bufnr, settings, ...)
|
||||
buffers[bufnr] = settings
|
||||
attachments[1] = attachments[1] + 1
|
||||
strategy.on_attach(bufnr, settings, ...)
|
||||
end,
|
||||
on_detach = function(bufnr, ...)
|
||||
buffers[bufnr] = nil
|
||||
attachments[1] = attachments[1] - 1
|
||||
strategy.on_detach(bufnr, ...)
|
||||
end,
|
||||
on_reset = function(...)
|
||||
strategy.on_reset(...)
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
return track
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,42 @@
|
||||
--[[
|
||||
Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--]]
|
||||
|
||||
---Internal helper functions. This module will probably be removed when I no
|
||||
---longer need the helpers.
|
||||
local M = {}
|
||||
|
||||
|
||||
---Similar to the function `LanguageTree:for_each_child` which has been
|
||||
---deprecated. Applies the thunk to the language tree and each of its
|
||||
---descendants recursively.
|
||||
---
|
||||
---See also https://github.com/neovim/neovim/pull/25154 for a better
|
||||
---replacement.
|
||||
---@param parent_lang string? # Parent language or nil
|
||||
---@param lang string
|
||||
---@param language_tree LanguageTree
|
||||
---@param thunk fun(p: LanguageTree, lang: string, parent_lang: string?)
|
||||
function M.for_each_child(parent_lang, lang, language_tree, thunk)
|
||||
thunk(language_tree, lang, parent_lang)
|
||||
local children = language_tree:children()
|
||||
for child_lang, child in pairs(children) do
|
||||
M.for_each_child(lang, child_lang, child, thunk)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
# This is free and unencumbered software released into the public domain.
|
||||
#
|
||||
# Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
# this software, either in source code form or as a compiled binary, for any
|
||||
# purpose, commercial or non-commercial, and by any means.
|
||||
#
|
||||
# In jurisdictions that recognize copyright laws, the author or authors of
|
||||
# this software dedicate any and all copyright interest in the software to
|
||||
# the public domain. We make this dedication for the benefit of the public
|
||||
# at large and to the detriment of our heirs and successors. We intend this
|
||||
# dedication to be an overt act of relinquishment in perpetuity of all
|
||||
# present and future rights to this software under copyright law.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# For more information, please refer to <https://unlicense.org/>
|
||||
|
||||
|
||||
.PHONY: check unit-test e2e-test clean
|
||||
|
||||
check: unit-test e2e-test
|
||||
|
||||
unit-test:
|
||||
@./test/busted --run unit
|
||||
|
||||
e2e-test:
|
||||
@./test/busted --run e2e
|
||||
|
||||
clean:
|
||||
@rm -rf test/xdg/local/state/nvim/*
|
||||
@rm -rf test/xdg/local/share/nvim/site/pack/testing/start/nvim-treesitter/parser/*
|
||||
@# The symlink might have been left over from a failed test run
|
||||
@rm -rf test/xdg/local/share/nvim/site/pack/self-*
|
||||
@ -0,0 +1,75 @@
|
||||
-- Copyright 2023 Alejandro "HiPhish" Sanchez
|
||||
-- Copyright 2020-2022 Chinmay Dalal
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
if vim.g.loaded_rainbow then
|
||||
return
|
||||
end
|
||||
|
||||
local api = vim.api
|
||||
local set_hl = api.nvim_set_hl
|
||||
local create_augroup = api.nvim_create_augroup
|
||||
local create_autocmd = api.nvim_create_autocmd
|
||||
local get_lang = vim.treesitter.language.get_lang
|
||||
local config = require 'rainbow-delimiters.config'
|
||||
local log = require 'rainbow-delimiters.log'
|
||||
local lib = require 'rainbow-delimiters.lib'
|
||||
|
||||
|
||||
--- [ DEFINE HIGHLIGHT GROUPS ]------------------------------------------------
|
||||
local function define_hlgroups()
|
||||
log.trace 'Define highlight groups'
|
||||
|
||||
set_hl(0, 'RainbowDelimiterRed' , {default = true, fg = '#cc241d', ctermfg= 'Red' })
|
||||
set_hl(0, 'RainbowDelimiterOrange', {default = true, fg = '#d65d0e', ctermfg= 'White' })
|
||||
set_hl(0, 'RainbowDelimiterYellow', {default = true, fg = '#d79921', ctermfg= 'Yellow' })
|
||||
set_hl(0, 'RainbowDelimiterGreen' , {default = true, fg = '#689d6a', ctermfg= 'Green' })
|
||||
set_hl(0, 'RainbowDelimiterCyan' , {default = true, fg = '#a89984', ctermfg= 'Cyan' })
|
||||
set_hl(0, 'RainbowDelimiterBlue' , {default = true, fg = '#458588', ctermfg= 'Blue' })
|
||||
set_hl(0, 'RainbowDelimiterViolet', {default = true, fg = '#b16286', ctermfg= 'Magenta'})
|
||||
end
|
||||
|
||||
define_hlgroups()
|
||||
|
||||
|
||||
--- [ SET UP AUTOCOMMANDS ]----------------------------------------------------
|
||||
local hl_augroup = create_augroup('TSRainbowHighlight', {})
|
||||
local rb_augroup = create_augroup('TSRainbowDelimits', {})
|
||||
|
||||
create_autocmd('ColorScheme', {
|
||||
desc = 'Re-apply highlight group definitions when the colour scheme changes',
|
||||
group = hl_augroup,
|
||||
callback = define_hlgroups
|
||||
})
|
||||
|
||||
create_autocmd('FileType', {
|
||||
desc = 'Attach to a new buffer',
|
||||
group = rb_augroup,
|
||||
callback = function(args)
|
||||
local lang = get_lang(args.match)
|
||||
if not config.enabled_for(lang) then return end
|
||||
|
||||
lib.attach(args.buf)
|
||||
end,
|
||||
})
|
||||
|
||||
create_autocmd('BufUnload', {
|
||||
desc = 'Detach from the current buffer',
|
||||
group = rb_augroup,
|
||||
callback = function(args) lib.detach(args.buf) end
|
||||
})
|
||||
|
||||
vim.g.loaded_rainbow = true
|
||||
|
||||
-- vim:tw=79:ts=4:sw=4:noet:
|
||||
@ -0,0 +1,13 @@
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(interpolation
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,37 @@
|
||||
(command_substitution
|
||||
"$(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(expansion
|
||||
"${" @delimiter
|
||||
(":-" @delimiter)?
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
;;; The double-bracket variant is a bashism
|
||||
(test_command
|
||||
["[[" "["] @delimiter
|
||||
["]]" "]"] @delimiter @sentinel) @container
|
||||
|
||||
(subshell
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(function_definition
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(arithmetic_expansion
|
||||
"$((" @delimiter
|
||||
"))" @delimiter @sentinel) @container
|
||||
|
||||
(compound_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(subscript
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,67 @@
|
||||
(parameter_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(compound_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(initializer_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
; This highlights the nested levels in an array differently
|
||||
; although they are the same level in terms of the nesting
|
||||
; of delimiters
|
||||
(subscript_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(field_declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_declarator
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(sizeof_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
; Comment out the following to not highlight type casts
|
||||
(cast_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(enumerator_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(macro_type_specifier
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(preproc_params
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(compound_literal_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_declarator
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,143 @@
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameter_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(if_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(foreach_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(while_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(do_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(attribute_argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(attribute_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(switch_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(switch_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(switch_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(default_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(catch_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(catch_filter_clause
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(using_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(lock_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(cast_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(typeof_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(sizeof_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(checked_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(accessor_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(anonymous_object_creation_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(enum_member_declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameter_list
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(type_argument_list
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(initializer_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_rank_specifier
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(bracketed_argument_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(implicit_array_creation_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(implicit_stackalloc_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,19 @@
|
||||
(list_lit
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(vec_lit
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(map_lit
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(set_lit
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(anon_fn_lit
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,13 @@
|
||||
(list_lit
|
||||
"(" @delimiter
|
||||
_*
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(defun
|
||||
"(" @delimiter
|
||||
_*
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(loop_macro
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel ) @container
|
||||
@ -0,0 +1,61 @@
|
||||
;;; NOTE: The C and C++ grammar have diverged, so I cannot include the C query.
|
||||
|
||||
(parameter_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(condition_clause
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(compound_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(cast_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel)
|
||||
|
||||
(initializer_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_declarator
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(subscript_argument_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(field_declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(template_parameter_list
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(initializer_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(template_argument_list
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,19 @@
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_query
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(feature_query
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(attribute_selector
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,5 @@
|
||||
; inherits: cpp
|
||||
|
||||
(kernel_call_syntax
|
||||
"<<<" @delimiter
|
||||
">>>" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,31 @@
|
||||
(struct_lit
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(list_lit
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(label
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(attribute
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(import_spec_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(interpolation
|
||||
"\\(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,31 @@
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameter_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(optional_formal_parameters
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(list_literal
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(set_or_map_literal
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,34 @@
|
||||
(call
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container)
|
||||
|
||||
(block
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(string
|
||||
(interpolation
|
||||
"#{" @delimiter
|
||||
"}" @delimiter @sentinel) @container)
|
||||
|
||||
(tuple
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(access_call
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(bitstring
|
||||
"<<" @delimiter
|
||||
">>" @delimiter @sentinel) @container
|
||||
|
||||
(map
|
||||
"%" @delimiter
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,63 @@
|
||||
(exposing_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(exposed_operator
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(exposed_union_constructors
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(_
|
||||
"(" @delimiter
|
||||
.
|
||||
(type_expression)
|
||||
.
|
||||
")" @delimiter @sentinel
|
||||
) @container
|
||||
|
||||
(_
|
||||
"(" @delimiter
|
||||
.
|
||||
[(pattern) (union_pattern)]
|
||||
.
|
||||
")" @delimiter @sentinel
|
||||
) @container
|
||||
|
||||
(record_expr
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(record_type
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(record_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_expr
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expr
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list_expr
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,3 @@
|
||||
(_
|
||||
open: ["(" "[" "{"] @delimiter
|
||||
close: [")" "]" "}"] @delimiter @sentinel) @container
|
||||
@ -0,0 +1,15 @@
|
||||
(command_substitution
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(concatenation
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list_element_access
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(brace_expansion
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,79 @@
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(import_spec_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(var_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(const_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(type_assertion_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(field_declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameter_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(expression_switch_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(type_switch_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(literal_value
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(slice_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(map_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(interface_type
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameter_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(index_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(slice_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,39 @@
|
||||
(parens
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(unit
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(exports
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(children
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(import_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(prefix_id
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(fields
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(record
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,47 @@
|
||||
(tuple
|
||||
(tuple_start "[") @delimiter
|
||||
(tuple_end "]") @delimiter @sentinel) @container
|
||||
|
||||
(for_tuple_expr
|
||||
(tuple_start "[") @delimiter
|
||||
(tuple_end "]") @delimiter @sentinel) @container
|
||||
|
||||
(new_index
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(function_call
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(binary_operation
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(unary_operation
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
(block_start "{") @delimiter
|
||||
(block_end "}") @delimiter @sentinel) @container
|
||||
|
||||
(object
|
||||
(object_start "{") @delimiter
|
||||
(object_end "}") @delimiter @sentinel) @container
|
||||
|
||||
(for_object_expr
|
||||
(object_start "{") @delimiter
|
||||
(object_end "}") @delimiter @sentinel) @container
|
||||
|
||||
(template_interpolation
|
||||
(template_interpolation_start) @delimiter
|
||||
(template_interpolation_end) @delimiter @sentinel) @container
|
||||
|
||||
(_
|
||||
(template_directive_start) @delimiter
|
||||
(template_directive_end) @delimiter @sentinel) @container
|
||||
@ -0,0 +1,69 @@
|
||||
;;; A pair of delimiter tags with any content in-between.
|
||||
;;; Last tag should be a sentinel.
|
||||
|
||||
;;; If instead you want rainbow-delimiters to only highlight
|
||||
;;; the tag names without any of "<", "</", ">" or "/>", then
|
||||
;;; you can make your own query file, e.g.,
|
||||
;;; 'rainbow-tag-names'
|
||||
;;; and use the following with
|
||||
;;; x @delimiter
|
||||
;;; deleted for x equal to any of "<", "</", ">" or "/>".
|
||||
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(self_closing_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
"/>" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter @_tag_name
|
||||
">" @delimiter @sentinel)
|
||||
(#any-of? @_tag_name
|
||||
"area"
|
||||
"base"
|
||||
"br"
|
||||
"col"
|
||||
"embed"
|
||||
"hr"
|
||||
"img"
|
||||
"input"
|
||||
"link"
|
||||
"meta"
|
||||
"param"
|
||||
"source"
|
||||
"track"
|
||||
"wbr")
|
||||
) @container
|
||||
|
||||
(style_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(element (self_closing_tag) @delimiter)*
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(script_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
@ -0,0 +1,23 @@
|
||||
(par_tup_lit
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(par_arr_lit
|
||||
"@(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(sqr_tup_lit
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(sqr_arr_lit
|
||||
"@[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(struct_lit
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(tbl_lit
|
||||
"@{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,70 @@
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_initializer
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(resource_specification
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(catch_clause
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(cast_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(inferred_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(annotation_argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(enhanced_for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(constructor_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
;; Treat it as a single delimiter because it will always have the same color
|
||||
(dimensions) @container @delimiter @sentinel
|
||||
|
||||
(dimensions_expr
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_access
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,102 @@
|
||||
;;; This query includes React support as well.
|
||||
|
||||
;; String interpolation inside template strings
|
||||
(template_substitution
|
||||
"${" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(statement_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(switch_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_in_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subscript_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(named_imports
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(export_clause
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
|
||||
;;; React.js support
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
|
||||
(jsx_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,68 @@
|
||||
;;; This query only covers Javascript without any React support. It exists so
|
||||
;;; that Typescript query can inherit it.
|
||||
|
||||
;; String interpolation inside template strings
|
||||
(template_substitution
|
||||
"${" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(statement_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(switch_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_in_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subscript_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(named_imports
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(export_clause
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
;;; This query only covers Javascript without any React support. It exists so
|
||||
;;; that Typescript query can inherit it.
|
||||
|
||||
;; String interpolation inside template strings
|
||||
(template_substitution
|
||||
"${" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(statement_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(switch_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_in_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subscript_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(named_imports
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(export_clause
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(object_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,7 @@
|
||||
(object
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1 @@
|
||||
; inherits: json
|
||||
@ -0,0 +1 @@
|
||||
; inherits: json
|
||||
@ -0,0 +1,39 @@
|
||||
(anonymous_function
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(functioncall
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(bind
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesis
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(field
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(fieldname
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(forloop
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(indexing
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(object
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,27 @@
|
||||
(vector_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(matrix_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(comprehension_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(curly_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,55 @@
|
||||
(class_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(function_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(control_structure_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
|
||||
(lambda_literal
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(primary_constructor
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(function_value_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(value_arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(multi_variable_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(when_expression
|
||||
(when_subject
|
||||
"(" @delimiter
|
||||
")" @delimiter)?
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(indexing_suffix
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameters
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,11 @@
|
||||
(inline_formula
|
||||
"$" @delimiter
|
||||
"$" @delimiter @sentinel) @container
|
||||
|
||||
(generic_environment
|
||||
(begin) @delimiter
|
||||
(end) @delimiter @sentinel) @container
|
||||
|
||||
(math_environment
|
||||
(begin) @delimiter
|
||||
(end) @delimiter @sentinel) @container
|
||||
@ -0,0 +1,15 @@
|
||||
(curly_group
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(curly_group_text
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(curly_group_text_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(inline_formula
|
||||
"$" @delimiter
|
||||
"$" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,69 @@
|
||||
;;; Note: Some patterns are commented out because currently Neovim can capture
|
||||
;;; only one node at a time. Once it becomes possible to capture multiple
|
||||
;;; nodes they should be commented back in.
|
||||
|
||||
|
||||
(function_declaration
|
||||
"function" @delimiter
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
(function_definition
|
||||
"function" @delimiter
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
(if_statement
|
||||
"if" @delimiter
|
||||
"then" @delimiter
|
||||
(elseif_statement
|
||||
"elseif" @delimiter
|
||||
"then" @delimiter)*
|
||||
(else_statement
|
||||
"else" @delimiter)?
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
(while_statement
|
||||
"while" @delimiter
|
||||
"do" @delimiter
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
(repeat_statement
|
||||
"repeat" @delimiter
|
||||
"until" @delimiter @sentinel) @container
|
||||
|
||||
(for_statement
|
||||
"for" @delimiter
|
||||
(for_generic_clause
|
||||
"in" @delimiter)?
|
||||
"do" @delimiter
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
(do_statement
|
||||
"do" @delimiter
|
||||
"end" @delimiter @sentinel) @container
|
||||
|
||||
|
||||
;;; Copied over from rainbow-parens
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(table_constructor
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(bracket_index_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(field
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,23 @@
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(table_constructor
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(bracket_index_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(field
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,40 @@
|
||||
(function_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
;;; I wanted to use something like
|
||||
; (union_type
|
||||
; "|" @delimiter @sentinel
|
||||
; ) @container
|
||||
;;; too, but it doesn't fully work with the current parser
|
||||
|
||||
(array_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(table_type
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(table_literal_type
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(indexed_field
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(_
|
||||
"[" @delimiter
|
||||
.
|
||||
field: (_)
|
||||
.
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1 @@
|
||||
;;; Nothing I can think of, everything gets taken from the injected bash query.
|
||||
@ -0,0 +1,3 @@
|
||||
;;; Intentionally empty. Markdown can have other languages embedded and we
|
||||
;;; want to let those grammars handle the highlighting. This query only exists
|
||||
;;; to satisfy the requirements of this plugin.
|
||||
@ -0,0 +1,47 @@
|
||||
(array_construction
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
(tuple_construction
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
(tuple_deconstruct_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
(curly_construction
|
||||
"{" @delimiter
|
||||
":"? @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
(parameter_declaration_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(bracket_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
(field_declaration_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
(generic_parameter_list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(cast
|
||||
"[" @delimiter
|
||||
"]" @delimiter
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(term_rewriting_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
(curly_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,27 @@
|
||||
(attrset_expression
|
||||
("{" @delimiter)
|
||||
("}" @delimiter @sentinel)) @container
|
||||
|
||||
(rec_attrset_expression
|
||||
("{" @delimiter)
|
||||
("}" @delimiter @sentinel)) @container
|
||||
|
||||
(formals
|
||||
("{" @delimiter)
|
||||
("}" @delimiter @sentinel)) @container
|
||||
|
||||
(list_expression
|
||||
("[" @delimiter)
|
||||
("]" @delimiter @sentinel)) @container
|
||||
|
||||
(parenthesized_expression
|
||||
("(" @delimiter)
|
||||
(")" @delimiter @sentinel)) @container
|
||||
|
||||
(interpolation
|
||||
("${" @delimiter)
|
||||
("}" @delimiter @sentinel)) @container
|
||||
|
||||
(inherit_from
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,86 @@
|
||||
(argument
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(array_dereference
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_ref
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_ref
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(hash_access_variable
|
||||
"->{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(hash_access_variable
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(hash_ref
|
||||
"+" @delimiter
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(multi_var_declaration
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(standalone_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_argument
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(word_list_qw
|
||||
(start_delimiter_qw) @delimiter
|
||||
(end_delimiter_qw) @delimiter @sentinel) @container
|
||||
|
||||
(regex_pattern_qr
|
||||
(start_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
|
||||
(command_qx_quoted
|
||||
(start_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
|
||||
(string_qq_quoted
|
||||
(start_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
|
||||
(patter_matcher_m
|
||||
(start_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
|
||||
(substitution_pattern_s
|
||||
(start_delimiter) @delimiter
|
||||
(separator_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
|
||||
(transliteration_tr_or_y
|
||||
(start_delimiter) @delimiter
|
||||
(separator_delimiter) @delimiter
|
||||
(end_delimiter) @delimiter @sentinel) @container
|
||||
@ -0,0 +1,31 @@
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(compound_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(encapsed_string
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array_creation_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(subscript_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,75 @@
|
||||
;; NOTE: When updating this file update the Starlark test file as well if
|
||||
;; applicable.
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list_comprehension
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(dictionary
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(dict_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(dictionary_comprehension
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(set
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(set_comprehension
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(tuple
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(generator_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subscript
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameter
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(import_from_statement
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(string
|
||||
(interpolation
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container)
|
||||
@ -0,0 +1,28 @@
|
||||
;; Note: These queries are very useful when looking at a large
|
||||
;; tree of queries like in `InspectTree`
|
||||
(named_node
|
||||
"(" @delimiter
|
||||
(identifier) @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(grouping
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(predicate
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(field_definition
|
||||
(identifier) @delimiter @sentinel) @container
|
||||
|
||||
;; For more highlighting the following can be added too:
|
||||
; (parameters
|
||||
; (identifier) @delimiter @sentinel) @container
|
||||
;
|
||||
; (negated_field
|
||||
; (identifier) @delimiter @sentinel) @container
|
||||
@ -0,0 +1,15 @@
|
||||
(named_node
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(grouping
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(predicate
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,36 @@
|
||||
(call
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subset
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(subset2
|
||||
"[[" @delimiter
|
||||
"]]" @delimiter @sentinel) @container
|
||||
|
||||
(if
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(for
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(while
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(switch
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(function_definition
|
||||
(formal_parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel)) @container
|
||||
|
||||
(brace_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,14 @@
|
||||
(list
|
||||
"(" @delimiter
|
||||
(dot)? @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
(dot)? @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"{" @delimiter
|
||||
(dot)? @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,52 @@
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(environ_value
|
||||
"$" @delimiter
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(environ_value
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list_value
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(distance_calc
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(feature_query
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(reference_value
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(rgb_color
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(hsl_color
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(hwb_color
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(cmyk_color
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(url_image
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(gradient_image
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,17 @@
|
||||
(anonymous_capturing_group
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
;;; The inversion `^` should be an opening node as well
|
||||
(character_class
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(count_quantifier
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
;;; We should probably include the character after `?` like `=` as well
|
||||
(lookaround_assertion
|
||||
"(?" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,3 @@
|
||||
;;; Intentionally empty. ReStructuredText can have other languages embedded
|
||||
;;; and we want to let those grammars handle the highlighting. This query only
|
||||
;;; exists to satisfy the requirements of this plugin.
|
||||
@ -0,0 +1,19 @@
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(hash
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_statements
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(block_parameters
|
||||
"|" @delimiter
|
||||
"|" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,133 @@
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(field_declaration_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(ordered_field_declaration_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(enum_variant_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(use_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(field_initializer_list
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(match_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_type
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(token_tree
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(token_tree
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(token_tree
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(token_tree_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(token_repetition_pattern
|
||||
"$" @delimiter
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(token_repetition
|
||||
"$" @delimiter
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(attribute_item
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(inner_attribute_item
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameters
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(closure_parameters
|
||||
"|" @delimiter
|
||||
"|" @delimiter @sentinel) @container
|
||||
|
||||
(array_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(index_expression
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_struct_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(struct_pattern
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(slice_pattern
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(macro_definition
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(visibility_modifier
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,7 @@
|
||||
(list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,5 @@
|
||||
; inherits: css
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,28 @@
|
||||
(subquery
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(invocation
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(where
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(binary_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel
|
||||
) @container
|
||||
|
||||
; The following can cause problems with (((())))
|
||||
(term
|
||||
"(" @delimiter
|
||||
; ("(" ")")* ; to fix _some_ problems, this can be uncommented
|
||||
")" @delimiter @sentinel
|
||||
) @container
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
;; This is mostly identical to Python, without `generator_expression`.
|
||||
;; NOTE: if you update queries for Python, please consider adding the changes
|
||||
;; to this file as well, given that the tree-sitter's node types exist. See
|
||||
;; https://github.com/amaanq/tree-sitter-starlark/blob/master/src/node-types.json
|
||||
|
||||
(list
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(list_comprehension
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(dictionary
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(dictionary_comprehension
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(set
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(set_comprehension
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(tuple
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(tuple_pattern
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parameters
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(argument_list
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(parenthesized_expression
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(subscript
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameter
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,35 @@
|
||||
(script_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(style_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(self_closing_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
"/>" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
@ -0,0 +1,53 @@
|
||||
(script_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(style_element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(self_closing_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
"/>" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(start_tag
|
||||
"<" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter)
|
||||
(end_tag
|
||||
"</" @delimiter
|
||||
(tag_name) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(const_expr
|
||||
"{" @delimiter
|
||||
"@" @delimiter
|
||||
(special_block_keyword) @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(each_statement
|
||||
(each_start_expr
|
||||
"{" @delimiter
|
||||
"#" @delimiter
|
||||
(special_block_keyword) @delimiter
|
||||
"}" @delimiter) @container
|
||||
(each_end_expr
|
||||
"{" @delimiter
|
||||
"/" @delimiter
|
||||
(special_block_keyword) @delimiter
|
||||
"}" @delimiter @sentinel)) @container
|
||||
@ -0,0 +1,19 @@
|
||||
(arguments
|
||||
"(" @delimiter
|
||||
")" @delimiter @sentinel) @container
|
||||
|
||||
(table_constructor
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(table_entry
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(index
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(field
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,61 @@
|
||||
; inherits: go
|
||||
|
||||
;; HTML elements
|
||||
|
||||
(element
|
||||
(tag_start
|
||||
"<" @delimiter
|
||||
(element_identifier) @delimiter
|
||||
">" @delimiter)
|
||||
(tag_end
|
||||
"</" @delimiter
|
||||
(element_identifier) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(element
|
||||
(self_closing_tag
|
||||
"<" @delimiter
|
||||
(element_identifier) @delimiter
|
||||
"/>" @delimiter @sentinel)) @container
|
||||
|
||||
(style_element
|
||||
("<" @delimiter
|
||||
"style" @delimiter
|
||||
">" @delimiter)
|
||||
("</" @delimiter
|
||||
"style" @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(script_element
|
||||
("<" @delimiter
|
||||
"script" @delimiter
|
||||
">" @delimiter)
|
||||
("</" @delimiter
|
||||
"script" @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
;; Brackets
|
||||
|
||||
(component_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(script_block
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(css_declaration
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(component_switch_statement
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(component_children_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1 @@
|
||||
; inherits: hcl
|
||||
@ -0,0 +1,15 @@
|
||||
(table
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(array
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(inline_table
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(table_array_element
|
||||
"[[" @delimiter
|
||||
"]]" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,36 @@
|
||||
; inherits: typescript
|
||||
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_element
|
||||
open_tag: (jsx_opening_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter)
|
||||
close_tag: (jsx_closing_element
|
||||
"</" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
">" @delimiter @sentinel)) @container
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (identifier) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
|
||||
|
||||
(jsx_self_closing_element
|
||||
"<" @delimiter
|
||||
name: (member_expression) @delimiter
|
||||
"/>" @delimiter @sentinel) @container
|
||||
|
||||
(jsx_expression
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
@ -0,0 +1,4 @@
|
||||
; inherits: typescript
|
||||
|
||||
;;; This query exists for people who only want to highlight parentheses without
|
||||
;;; tags.
|
||||
@ -0,0 +1,4 @@
|
||||
; inherits: javascript
|
||||
|
||||
;;; This query exists for people who only want to highlight tags without
|
||||
;;; parentheses.
|
||||
@ -0,0 +1,25 @@
|
||||
; inherits: javascript
|
||||
|
||||
(interface_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(enum_body
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
|
||||
(type_arguments
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(type_parameters
|
||||
"<" @delimiter
|
||||
">" @delimiter @sentinel) @container
|
||||
|
||||
(lookup_type
|
||||
"[" @delimiter
|
||||
"]" @delimiter @sentinel) @container
|
||||
|
||||
(object_type
|
||||
"{" @delimiter
|
||||
"}" @delimiter @sentinel) @container
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user