Rainbow tree-sitter matches 🌈 (#13530)

This commit is contained in:
Michael Davis
2025-07-26 15:02:29 -07:00
committed by GitHub
parent e17b80a5a2
commit 1941f0b639
44 changed files with 1277 additions and 290 deletions

View File

@@ -30,3 +30,4 @@
- [Adding indent queries](./guides/indent.md)
- [Adding injection queries](./guides/injection.md)
- [Adding tags queries](./guides/tags.md)
- [Adding rainbow bracket queries](./guides/rainbow_bracket_queries.md)

View File

@@ -63,6 +63,7 @@
| `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | "disable"
| `clipboard-provider` | Which API to use for clipboard interaction. One of `pasteboard` (MacOS), `wayland`, `x-clip`, `x-sel`, `win-32-yank`, `termux`, `tmux`, `windows`, `termcode`, `none`, or a custom command set. | Platform and environment specific. |
| `editor-config` | Whether to read settings from [EditorConfig](https://editorconfig.org) files | `true` |
| `rainbow-brackets` | Whether to render rainbow colors for matching brackets. Requires tree-sitter `rainbows.scm` queries for the language. | `false` |
### `[editor.clipboard-provider]` Section

View File

@@ -1,285 +1,285 @@
| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Code Navigation Tags | Default language servers |
| --- | --- | --- | --- | --- | --- |
| ada | ✓ | ✓ | | | `ada_language_server` |
| adl | ✓ | ✓ | ✓ | | |
| agda | ✓ | | | | |
| alloy | ✓ | | | | |
| amber | ✓ | | | | `amber-lsp` |
| astro | ✓ | | | | `astro-ls` |
| awk | ✓ | ✓ | | | `awk-language-server` |
| bash | ✓ | ✓ | ✓ | | `bash-language-server` |
| bass | ✓ | | | | `bass` |
| beancount | ✓ | | | | `beancount-language-server` |
| bibtex | ✓ | | | | `texlab` |
| bicep | ✓ | | | | `bicep-langserver` |
| bitbake | ✓ | | | | `bitbake-language-server` |
| blade | ✓ | | | | |
| blueprint | ✓ | | | | `blueprint-compiler` |
| c | ✓ | ✓ | ✓ | ✓ | `clangd` |
| c-sharp | ✓ | ✓ | | ✓ | `OmniSharp` |
| cabal | | | | | `haskell-language-server-wrapper` |
| caddyfile | ✓ | ✓ | ✓ | | |
| cairo | ✓ | ✓ | ✓ | | `cairo-language-server` |
| capnp | ✓ | | ✓ | | |
| cel | ✓ | | | | |
| circom | ✓ | | | | `circom-lsp` |
| clarity | ✓ | | | | `clarinet` |
| clojure | ✓ | | | | `clojure-lsp` |
| cmake | ✓ | ✓ | ✓ | | `neocmakelsp`, `cmake-language-server` |
| codeql | ✓ | ✓ | | | `codeql` |
| comment | ✓ | | | | |
| common-lisp | ✓ | | ✓ | | `cl-lsp` |
| cpon | ✓ | | ✓ | | |
| cpp | ✓ | ✓ | ✓ | ✓ | `clangd` |
| crystal | ✓ | ✓ | ✓ | ✓ | `crystalline`, `ameba-ls` |
| css | ✓ | | ✓ | | `vscode-css-language-server` |
| csv | ✓ | | | | |
| cue | ✓ | | | | `cuelsp` |
| cylc | ✓ | ✓ | ✓ | | |
| d | ✓ | ✓ | ✓ | | `serve-d` |
| dart | ✓ | ✓ | ✓ | | `dart` |
| dbml | ✓ | | | | |
| debian | ✓ | | | | |
| devicetree | ✓ | | | | `dts-lsp` |
| dhall | ✓ | ✓ | | | `dhall-lsp-server` |
| diff | ✓ | | | | |
| djot | ✓ | | | | |
| docker-compose | ✓ | ✓ | ✓ | | `docker-compose-langserver`, `yaml-language-server` |
| dockerfile | ✓ | ✓ | | | `docker-langserver` |
| dot | ✓ | | | | `dot-language-server` |
| dtd | ✓ | | | | |
| dune | ✓ | | | | |
| dunstrc | ✓ | | | | |
| earthfile | ✓ | ✓ | ✓ | | `earthlyls` |
| edoc | ✓ | | | | |
| eex | ✓ | | | | |
| ejs | ✓ | | | | |
| elisp | ✓ | | | ✓ | |
| elixir | ✓ | ✓ | ✓ | ✓ | `elixir-ls` |
| elm | ✓ | ✓ | | ✓ | `elm-language-server` |
| elvish | ✓ | | | | `elvish` |
| env | ✓ | ✓ | | | |
| erb | ✓ | | | | |
| erlang | ✓ | ✓ | | ✓ | `erlang_ls`, `elp` |
| esdl | ✓ | | | | |
| fennel | ✓ | | | | `fennel-ls` |
| fga | ✓ | ✓ | ✓ | | |
| fidl | ✓ | | | | |
| fish | ✓ | ✓ | ✓ | | `fish-lsp` |
| forth | ✓ | | | | `forth-lsp` |
| fortran | ✓ | | ✓ | | `fortls` |
| fsharp | ✓ | | | | `fsautocomplete` |
| gas | ✓ | ✓ | | | `asm-lsp` |
| gdscript | ✓ | ✓ | ✓ | ✓ | |
| gemini | ✓ | | | | |
| gherkin | ✓ | | | | |
| ghostty | ✓ | | | | |
| git-attributes | ✓ | | | | |
| git-commit | ✓ | ✓ | | | |
| git-config | ✓ | ✓ | | | |
| git-ignore | ✓ | | | | |
| git-notes | ✓ | | | | |
| git-rebase | ✓ | | | | |
| gjs | ✓ | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| gleam | ✓ | ✓ | | | `gleam` |
| glimmer | ✓ | | | | `ember-language-server` |
| glsl | ✓ | ✓ | ✓ | | `glsl_analyzer` |
| gn | ✓ | | | | |
| go | ✓ | ✓ | ✓ | ✓ | `gopls`, `golangci-lint-langserver` |
| go-format-string | ✓ | | | | |
| godot-resource | ✓ | ✓ | | | |
| gomod | ✓ | | | | `gopls` |
| gotmpl | ✓ | | | | `gopls` |
| gowork | ✓ | | | | `gopls` |
| gpr | ✓ | | | | `ada_language_server` |
| graphql | ✓ | ✓ | | | `graphql-lsp` |
| gren | ✓ | ✓ | | | |
| groovy | ✓ | | | | |
| gts | ✓ | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| hare | ✓ | | | | |
| haskell | ✓ | ✓ | | | `haskell-language-server-wrapper` |
| haskell-persistent | ✓ | | | | |
| hcl | ✓ | ✓ | ✓ | | `terraform-ls` |
| heex | ✓ | ✓ | | | `elixir-ls` |
| helm | ✓ | | | | `helm_ls` |
| hocon | ✓ | ✓ | ✓ | | |
| hoon | ✓ | | | | |
| hosts | ✓ | | | | |
| html | ✓ | ✓ | | | `vscode-html-language-server`, `superhtml` |
| htmldjango | ✓ | | | | `djlsp`, `vscode-html-language-server`, `superhtml` |
| hurl | ✓ | ✓ | ✓ | | |
| hyprlang | ✓ | | ✓ | | `hyprls` |
| idris | | | | | `idris2-lsp` |
| iex | ✓ | | | | |
| ini | ✓ | | | | |
| ink | ✓ | | | | |
| inko | ✓ | ✓ | ✓ | ✓ | |
| janet | ✓ | | ✓ | | |
| java | ✓ | ✓ | ✓ | | `jdtls` |
| javascript | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| jinja | ✓ | | | | |
| jjconfig | ✓ | ✓ | ✓ | | `taplo`, `tombi` |
| jjdescription | ✓ | | | | |
| jjrevset | ✓ | | | | |
| jjtemplate | ✓ | | | | |
| jq | ✓ | ✓ | | | `jq-lsp` |
| jsdoc | ✓ | | | | |
| json | ✓ | ✓ | ✓ | | `vscode-json-language-server` |
| json-ld | ✓ | ✓ | ✓ | | `vscode-json-language-server` |
| json5 | ✓ | | | | |
| jsonc | ✓ | | ✓ | | `vscode-json-language-server` |
| jsonnet | ✓ | | | | `jsonnet-language-server` |
| jsx | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| julia | ✓ | ✓ | ✓ | | `julia` |
| just | ✓ | ✓ | ✓ | | `just-lsp` |
| kdl | ✓ | ✓ | ✓ | | |
| koka | ✓ | | ✓ | | `koka` |
| kotlin | ✓ | ✓ | ✓ | | `kotlin-language-server` |
| koto | ✓ | ✓ | ✓ | | `koto-ls` |
| latex | ✓ | ✓ | | | `texlab` |
| ld | ✓ | | ✓ | | |
| ldif | ✓ | | | | |
| lean | ✓ | | | | `lean` |
| ledger | ✓ | | | | |
| llvm | ✓ | ✓ | ✓ | | |
| llvm-mir | ✓ | ✓ | ✓ | | |
| llvm-mir-yaml | ✓ | | ✓ | | |
| log | ✓ | | | | |
| lpf | ✓ | | | | |
| lua | ✓ | ✓ | ✓ | | `lua-language-server` |
| luap | ✓ | | | | |
| luau | ✓ | ✓ | ✓ | | `luau-lsp` |
| mail | ✓ | ✓ | | | |
| make | ✓ | | ✓ | | |
| markdoc | ✓ | | | | `markdoc-ls` |
| markdown | ✓ | | | ✓ | `marksman`, `markdown-oxide` |
| markdown-rustdoc | ✓ | | | | |
| markdown.inline | ✓ | | | | |
| matlab | ✓ | ✓ | ✓ | | |
| mermaid | ✓ | | | | |
| meson | ✓ | | ✓ | | `mesonlsp` |
| mint | | | | | `mint` |
| mojo | ✓ | ✓ | ✓ | | `pixi` |
| move | ✓ | | | | |
| msbuild | ✓ | | ✓ | | |
| nasm | ✓ | ✓ | | | `asm-lsp` |
| nestedtext | ✓ | ✓ | ✓ | | |
| nginx | ✓ | | | | |
| nickel | ✓ | | ✓ | | `nls` |
| nim | ✓ | ✓ | ✓ | | `nimlangserver` |
| nix | ✓ | ✓ | ✓ | | `nil`, `nixd` |
| nu | ✓ | | | | `nu` |
| nunjucks | ✓ | | | | |
| ocaml | ✓ | | ✓ | | `ocamllsp` |
| ocaml-interface | ✓ | | | | `ocamllsp` |
| odin | ✓ | ✓ | ✓ | | `ols` |
| ohm | ✓ | ✓ | ✓ | | |
| opencl | ✓ | ✓ | ✓ | | `clangd` |
| openscad | ✓ | | | | `openscad-lsp` |
| org | ✓ | | | | |
| pascal | ✓ | ✓ | | | `pasls` |
| passwd | ✓ | | | | |
| pem | ✓ | | | | |
| perl | ✓ | ✓ | ✓ | | `perlnavigator` |
| pest | ✓ | ✓ | ✓ | | `pest-language-server` |
| php | ✓ | ✓ | ✓ | ✓ | `intelephense` |
| php-only | ✓ | | | ✓ | |
| pkgbuild | ✓ | ✓ | ✓ | | `termux-language-server`, `bash-language-server` |
| pkl | ✓ | | ✓ | | `pkl-lsp` |
| po | ✓ | ✓ | | | |
| pod | ✓ | | | | |
| ponylang | ✓ | ✓ | ✓ | | |
| powershell | ✓ | | | | |
| prisma | ✓ | ✓ | | | `prisma-language-server` |
| prolog | ✓ | | ✓ | | `swipl` |
| properties | ✓ | ✓ | | | |
| protobuf | ✓ | ✓ | ✓ | | `buf`, `pb`, `protols` |
| prql | ✓ | | | | |
| pug | ✓ | | | | |
| purescript | ✓ | ✓ | | | `purescript-language-server` |
| python | ✓ | ✓ | ✓ | ✓ | `ty`, `ruff`, `jedi-language-server`, `pylsp` |
| qml | ✓ | ✓ | ✓ | | `qmlls` |
| quarto | ✓ | | ✓ | | |
| quint | ✓ | | | | `quint-language-server` |
| r | ✓ | | | | `R` |
| racket | ✓ | | ✓ | | `racket` |
| regex | ✓ | | | | |
| rego | ✓ | | | | `regols` |
| rescript | ✓ | ✓ | | | `rescript-language-server` |
| rmarkdown | ✓ | | ✓ | | `R` |
| robot | ✓ | | | | `robotframework_ls` |
| ron | ✓ | | ✓ | | |
| rst | ✓ | | | | |
| ruby | ✓ | ✓ | ✓ | ✓ | `ruby-lsp`, `solargraph` |
| rust | ✓ | ✓ | ✓ | ✓ | `rust-analyzer` |
| rust-format-args | ✓ | | | | |
| rust-format-args-macro | ✓ | ✓ | ✓ | | |
| sage | ✓ | ✓ | | | |
| scala | ✓ | ✓ | ✓ | | `metals` |
| scheme | ✓ | | ✓ | | |
| scss | ✓ | | | | `vscode-css-language-server` |
| slang | ✓ | ✓ | ✓ | | `slangd` |
| slint | ✓ | ✓ | ✓ | | `slint-lsp` |
| smali | ✓ | | ✓ | | |
| smithy | ✓ | | | | `cs` |
| sml | ✓ | | | | |
| snakemake | ✓ | | ✓ | | `pylsp` |
| solidity | ✓ | ✓ | | | `solc` |
| sourcepawn | ✓ | ✓ | | | `sourcepawn-studio` |
| spade | ✓ | | ✓ | | `spade-language-server` |
| spicedb | ✓ | | | ✓ | |
| sql | ✓ | ✓ | | | |
| sshclientconfig | ✓ | | | | |
| starlark | ✓ | ✓ | ✓ | | `starpls` |
| strace | ✓ | | | | |
| supercollider | ✓ | | | | |
| svelte | ✓ | | ✓ | | `svelteserver` |
| sway | ✓ | ✓ | ✓ | | `forc` |
| swift | ✓ | ✓ | | | `sourcekit-lsp` |
| systemd | ✓ | | | | `systemd-lsp` |
| t32 | ✓ | | | | |
| tablegen | ✓ | ✓ | ✓ | | |
| tact | ✓ | ✓ | ✓ | | |
| task | ✓ | | | | |
| tcl | ✓ | | ✓ | | |
| teal | ✓ | | | | `teal-language-server` |
| templ | ✓ | | | | `templ` |
| tera | ✓ | | | | |
| textproto | ✓ | ✓ | ✓ | | |
| tfvars | ✓ | | ✓ | | `terraform-ls` |
| thrift | ✓ | | | | |
| tlaplus | ✓ | | | | |
| todotxt | ✓ | | | | |
| toml | ✓ | ✓ | | | `taplo`, `tombi` |
| tsq | ✓ | | | | `ts_query_ls` |
| tsx | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| twig | ✓ | | | | |
| typescript | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| typespec | ✓ | ✓ | ✓ | | `tsp-server` |
| typst | ✓ | | | ✓ | `tinymist` |
| ungrammar | ✓ | | | | |
| unison | ✓ | ✓ | ✓ | | |
| uxntal | ✓ | | | | |
| v | ✓ | ✓ | ✓ | | `v-analyzer` |
| vala | ✓ | ✓ | | | `vala-language-server` |
| vento | ✓ | | | | |
| verilog | ✓ | ✓ | | | `svlangserver` |
| vhdl | ✓ | | | | `vhdl_ls` |
| vhs | ✓ | | | | |
| vim | ✓ | | | | |
| vue | ✓ | | | | `vue-language-server` |
| wast | ✓ | | | | |
| wat | ✓ | | | | `wat_server` |
| webc | ✓ | | | | |
| werk | ✓ | | | | |
| wesl | ✓ | ✓ | | | |
| wgsl | ✓ | | | | `wgsl-analyzer` |
| wit | ✓ | | ✓ | | |
| wren | ✓ | ✓ | ✓ | | |
| xit | ✓ | | | | |
| xml | ✓ | ✓ | ✓ | | |
| xtc | ✓ | | | | |
| yaml | ✓ | ✓ | ✓ | | `yaml-language-server`, `ansible-language-server` |
| yara | ✓ | | | | `yls` |
| yuck | ✓ | | | | |
| zig | ✓ | ✓ | ✓ | | `zls` |
| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Code Navigation Tags | Rainbow Brackets | Default language servers |
| --- | --- | --- | --- | --- | --- | --- |
| ada | ✓ | ✓ | | | | `ada_language_server` |
| adl | ✓ | ✓ | ✓ | | | |
| agda | ✓ | | | | | |
| alloy | ✓ | | | | | |
| amber | ✓ | | | | | `amber-lsp` |
| astro | ✓ | | | | | `astro-ls` |
| awk | ✓ | ✓ | | | | `awk-language-server` |
| bash | ✓ | ✓ | ✓ | | ✓ | `bash-language-server` |
| bass | ✓ | | | | | `bass` |
| beancount | ✓ | | | | | `beancount-language-server` |
| bibtex | ✓ | | | | | `texlab` |
| bicep | ✓ | | | | | `bicep-langserver` |
| bitbake | ✓ | | | | | `bitbake-language-server` |
| blade | ✓ | | | | | |
| blueprint | ✓ | | | | | `blueprint-compiler` |
| c | ✓ | ✓ | ✓ | ✓ | ✓ | `clangd` |
| c-sharp | ✓ | ✓ | | ✓ | | `OmniSharp` |
| cabal | | | | | | `haskell-language-server-wrapper` |
| caddyfile | ✓ | ✓ | ✓ | | | |
| cairo | ✓ | ✓ | ✓ | | | `cairo-language-server` |
| capnp | ✓ | | ✓ | | | |
| cel | ✓ | | | | | |
| circom | ✓ | | | | | `circom-lsp` |
| clarity | ✓ | | | | | `clarinet` |
| clojure | ✓ | | | | ✓ | `clojure-lsp` |
| cmake | ✓ | ✓ | ✓ | | | `neocmakelsp`, `cmake-language-server` |
| codeql | ✓ | ✓ | | | | `codeql` |
| comment | ✓ | | | | | |
| common-lisp | ✓ | | ✓ | | ✓ | `cl-lsp` |
| cpon | ✓ | | ✓ | | | |
| cpp | ✓ | ✓ | ✓ | ✓ | ✓ | `clangd` |
| crystal | ✓ | ✓ | ✓ | ✓ | | `crystalline`, `ameba-ls` |
| css | ✓ | | ✓ | | ✓ | `vscode-css-language-server` |
| csv | ✓ | | | | | |
| cue | ✓ | | | | | `cuelsp` |
| cylc | ✓ | ✓ | ✓ | | | |
| d | ✓ | ✓ | ✓ | | | `serve-d` |
| dart | ✓ | ✓ | ✓ | | | `dart` |
| dbml | ✓ | | | | | |
| debian | ✓ | | | | | |
| devicetree | ✓ | | | | | `dts-lsp` |
| dhall | ✓ | ✓ | | | | `dhall-lsp-server` |
| diff | ✓ | | | | | |
| djot | ✓ | | | | | |
| docker-compose | ✓ | ✓ | ✓ | | | `docker-compose-langserver`, `yaml-language-server` |
| dockerfile | ✓ | ✓ | | | | `docker-langserver` |
| dot | ✓ | | | | | `dot-language-server` |
| dtd | ✓ | | | | | |
| dune | ✓ | | | | | |
| dunstrc | ✓ | | | | | |
| earthfile | ✓ | ✓ | ✓ | | | `earthlyls` |
| edoc | ✓ | | | | | |
| eex | ✓ | | | | | |
| ejs | ✓ | | | | | |
| elisp | ✓ | | | ✓ | | |
| elixir | ✓ | ✓ | ✓ | ✓ | ✓ | `elixir-ls` |
| elm | ✓ | ✓ | | ✓ | | `elm-language-server` |
| elvish | ✓ | | | | | `elvish` |
| env | ✓ | ✓ | | | | |
| erb | ✓ | | | | | |
| erlang | ✓ | ✓ | | ✓ | ✓ | `erlang_ls`, `elp` |
| esdl | ✓ | | | | | |
| fennel | ✓ | | | | | `fennel-ls` |
| fga | ✓ | ✓ | ✓ | | | |
| fidl | ✓ | | | | | |
| fish | ✓ | ✓ | ✓ | | | `fish-lsp` |
| forth | ✓ | | | | | `forth-lsp` |
| fortran | ✓ | | ✓ | | | `fortls` |
| fsharp | ✓ | | | | | `fsautocomplete` |
| gas | ✓ | ✓ | | | | `asm-lsp` |
| gdscript | ✓ | ✓ | ✓ | ✓ | | |
| gemini | ✓ | | | | | |
| gherkin | ✓ | | | | | |
| ghostty | ✓ | | | | | |
| git-attributes | ✓ | | | | | |
| git-commit | ✓ | ✓ | | | | |
| git-config | ✓ | ✓ | | | | |
| git-ignore | ✓ | | | | | |
| git-notes | ✓ | | | | | |
| git-rebase | ✓ | | | | | |
| gjs | ✓ | ✓ | ✓ | ✓ | | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| gleam | ✓ | ✓ | | | ✓ | `gleam` |
| glimmer | ✓ | | | | | `ember-language-server` |
| glsl | ✓ | ✓ | ✓ | | | `glsl_analyzer` |
| gn | ✓ | | | | | |
| go | ✓ | ✓ | ✓ | ✓ | ✓ | `gopls`, `golangci-lint-langserver` |
| go-format-string | ✓ | | | | | |
| godot-resource | ✓ | ✓ | | | | |
| gomod | ✓ | | | | | `gopls` |
| gotmpl | ✓ | | | | | `gopls` |
| gowork | ✓ | | | | | `gopls` |
| gpr | ✓ | | | | | `ada_language_server` |
| graphql | ✓ | ✓ | | | | `graphql-lsp` |
| gren | ✓ | ✓ | | | | |
| groovy | ✓ | | | | | |
| gts | ✓ | ✓ | ✓ | ✓ | | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| hare | ✓ | | | | | |
| haskell | ✓ | ✓ | | | | `haskell-language-server-wrapper` |
| haskell-persistent | ✓ | | | | | |
| hcl | ✓ | ✓ | ✓ | | | `terraform-ls` |
| heex | ✓ | ✓ | | | | `elixir-ls` |
| helm | ✓ | | | | | `helm_ls` |
| hocon | ✓ | ✓ | ✓ | | | |
| hoon | ✓ | | | | | |
| hosts | ✓ | | | | | |
| html | ✓ | ✓ | | | ✓ | `vscode-html-language-server`, `superhtml` |
| htmldjango | ✓ | | | | | `djlsp`, `vscode-html-language-server`, `superhtml` |
| hurl | ✓ | ✓ | ✓ | | | |
| hyprlang | ✓ | | ✓ | | | `hyprls` |
| idris | | | | | | `idris2-lsp` |
| iex | ✓ | | | | | |
| ini | ✓ | | | | | |
| ink | ✓ | | | | | |
| inko | ✓ | ✓ | ✓ | ✓ | | |
| janet | ✓ | | ✓ | | | |
| java | ✓ | ✓ | ✓ | | ✓ | `jdtls` |
| javascript | ✓ | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| jinja | ✓ | | | | | |
| jjconfig | ✓ | ✓ | ✓ | | | `taplo`, `tombi` |
| jjdescription | ✓ | | | | | |
| jjrevset | ✓ | | | | | |
| jjtemplate | ✓ | | | | | |
| jq | ✓ | ✓ | | | | `jq-lsp` |
| jsdoc | ✓ | | | | | |
| json | ✓ | ✓ | ✓ | | ✓ | `vscode-json-language-server` |
| json-ld | ✓ | ✓ | ✓ | | | `vscode-json-language-server` |
| json5 | ✓ | | | | | |
| jsonc | ✓ | | ✓ | | | `vscode-json-language-server` |
| jsonnet | ✓ | | | | | `jsonnet-language-server` |
| jsx | ✓ | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| julia | ✓ | ✓ | ✓ | | | `julia` |
| just | ✓ | ✓ | ✓ | | | `just-lsp` |
| kdl | ✓ | ✓ | ✓ | | | |
| koka | ✓ | | ✓ | | | `koka` |
| kotlin | ✓ | ✓ | ✓ | | | `kotlin-language-server` |
| koto | ✓ | ✓ | ✓ | | | `koto-ls` |
| latex | ✓ | ✓ | | | | `texlab` |
| ld | ✓ | | ✓ | | | |
| ldif | ✓ | | | | | |
| lean | ✓ | | | | | `lean` |
| ledger | ✓ | | | | | |
| llvm | ✓ | ✓ | ✓ | | | |
| llvm-mir | ✓ | ✓ | ✓ | | | |
| llvm-mir-yaml | ✓ | | ✓ | | | |
| log | ✓ | | | | | |
| lpf | ✓ | | | | | |
| lua | ✓ | ✓ | ✓ | | | `lua-language-server` |
| luap | ✓ | | | | | |
| luau | ✓ | ✓ | ✓ | | | `luau-lsp` |
| mail | ✓ | ✓ | | | | |
| make | ✓ | | ✓ | | | |
| markdoc | ✓ | | | | | `markdoc-ls` |
| markdown | ✓ | | | ✓ | | `marksman`, `markdown-oxide` |
| markdown-rustdoc | ✓ | | | | | |
| markdown.inline | ✓ | | | | | |
| matlab | ✓ | ✓ | ✓ | | | |
| mermaid | ✓ | | | | | |
| meson | ✓ | | ✓ | | | `mesonlsp` |
| mint | | | | | | `mint` |
| mojo | ✓ | ✓ | ✓ | | | `pixi` |
| move | ✓ | | | | | |
| msbuild | ✓ | | ✓ | | | |
| nasm | ✓ | ✓ | | | | `asm-lsp` |
| nestedtext | ✓ | ✓ | ✓ | | | |
| nginx | ✓ | | | | | |
| nickel | ✓ | | ✓ | | | `nls` |
| nim | ✓ | ✓ | ✓ | | | `nimlangserver` |
| nix | ✓ | ✓ | ✓ | | ✓ | `nil`, `nixd` |
| nu | ✓ | | | | | `nu` |
| nunjucks | ✓ | | | | | |
| ocaml | ✓ | | ✓ | | | `ocamllsp` |
| ocaml-interface | ✓ | | | | | `ocamllsp` |
| odin | ✓ | ✓ | ✓ | | | `ols` |
| ohm | ✓ | ✓ | ✓ | | | |
| opencl | ✓ | ✓ | ✓ | | | `clangd` |
| openscad | ✓ | | | | | `openscad-lsp` |
| org | ✓ | | | | | |
| pascal | ✓ | ✓ | | | | `pasls` |
| passwd | ✓ | | | | | |
| pem | ✓ | | | | | |
| perl | ✓ | ✓ | ✓ | | | `perlnavigator` |
| pest | ✓ | ✓ | ✓ | | | `pest-language-server` |
| php | ✓ | ✓ | ✓ | ✓ | | `intelephense` |
| php-only | ✓ | | | ✓ | | |
| pkgbuild | ✓ | ✓ | ✓ | | | `termux-language-server`, `bash-language-server` |
| pkl | ✓ | | ✓ | | | `pkl-lsp` |
| po | ✓ | ✓ | | | | |
| pod | ✓ | | | | | |
| ponylang | ✓ | ✓ | ✓ | | | |
| powershell | ✓ | | | | | |
| prisma | ✓ | ✓ | | | | `prisma-language-server` |
| prolog | ✓ | | ✓ | | | `swipl` |
| properties | ✓ | ✓ | | | | |
| protobuf | ✓ | ✓ | ✓ | | | `buf`, `pb`, `protols` |
| prql | ✓ | | | | | |
| pug | ✓ | | | | | |
| purescript | ✓ | ✓ | | | | `purescript-language-server` |
| python | ✓ | ✓ | ✓ | ✓ | ✓ | `ty`, `ruff`, `jedi-language-server`, `pylsp` |
| qml | ✓ | ✓ | ✓ | | | `qmlls` |
| quarto | ✓ | | ✓ | | | |
| quint | ✓ | | | | | `quint-language-server` |
| r | ✓ | | | | | `R` |
| racket | ✓ | | ✓ | | ✓ | `racket` |
| regex | ✓ | | | | ✓ | |
| rego | ✓ | | | | | `regols` |
| rescript | ✓ | ✓ | | | | `rescript-language-server` |
| rmarkdown | ✓ | | ✓ | | | `R` |
| robot | ✓ | | | | | `robotframework_ls` |
| ron | ✓ | | ✓ | | | |
| rst | ✓ | | | | | |
| ruby | ✓ | ✓ | ✓ | ✓ | ✓ | `ruby-lsp`, `solargraph` |
| rust | ✓ | ✓ | ✓ | ✓ | ✓ | `rust-analyzer` |
| rust-format-args | ✓ | | | | | |
| rust-format-args-macro | ✓ | ✓ | ✓ | | | |
| sage | ✓ | ✓ | | | | |
| scala | ✓ | ✓ | ✓ | | | `metals` |
| scheme | ✓ | | ✓ | | ✓ | |
| scss | ✓ | | | | ✓ | `vscode-css-language-server` |
| slang | ✓ | ✓ | ✓ | | | `slangd` |
| slint | ✓ | ✓ | ✓ | | | `slint-lsp` |
| smali | ✓ | | ✓ | | | |
| smithy | ✓ | | | | | `cs` |
| sml | ✓ | | | | | |
| snakemake | ✓ | | ✓ | | | `pylsp` |
| solidity | ✓ | ✓ | | | | `solc` |
| sourcepawn | ✓ | ✓ | | | | `sourcepawn-studio` |
| spade | ✓ | | ✓ | | | `spade-language-server` |
| spicedb | ✓ | | | ✓ | | |
| sql | ✓ | ✓ | | | | |
| sshclientconfig | ✓ | | | | | |
| starlark | ✓ | ✓ | ✓ | | ✓ | `starpls` |
| strace | ✓ | | | | | |
| supercollider | ✓ | | | | | |
| svelte | ✓ | | ✓ | | | `svelteserver` |
| sway | ✓ | ✓ | ✓ | | | `forc` |
| swift | ✓ | ✓ | | | | `sourcekit-lsp` |
| systemd | ✓ | | | | | `systemd-lsp` |
| t32 | ✓ | | | | | |
| tablegen | ✓ | ✓ | ✓ | | | |
| tact | ✓ | ✓ | ✓ | | | |
| task | ✓ | | | | | |
| tcl | ✓ | | ✓ | | | |
| teal | ✓ | | | | | `teal-language-server` |
| templ | ✓ | | | | | `templ` |
| tera | ✓ | | | | | |
| textproto | ✓ | ✓ | ✓ | | | |
| tfvars | ✓ | | ✓ | | | `terraform-ls` |
| thrift | ✓ | | | | | |
| tlaplus | ✓ | | | | | |
| todotxt | ✓ | | | | | |
| toml | ✓ | ✓ | | | ✓ | `taplo`, `tombi` |
| tsq | ✓ | | | | | `ts_query_ls` |
| tsx | ✓ | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| twig | ✓ | | | | | |
| typescript | ✓ | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| typespec | ✓ | ✓ | ✓ | | | `tsp-server` |
| typst | ✓ | | | ✓ | | `tinymist` |
| ungrammar | ✓ | | | | | |
| unison | ✓ | ✓ | ✓ | | | |
| uxntal | ✓ | | | | | |
| v | ✓ | ✓ | ✓ | | | `v-analyzer` |
| vala | ✓ | ✓ | | | | `vala-language-server` |
| vento | ✓ | | | | | |
| verilog | ✓ | ✓ | | | | `svlangserver` |
| vhdl | ✓ | | | | | `vhdl_ls` |
| vhs | ✓ | | | | | |
| vim | ✓ | | | | | |
| vue | ✓ | | | | | `vue-language-server` |
| wast | ✓ | | | | | |
| wat | ✓ | | | | | `wat_server` |
| webc | ✓ | | | | | |
| werk | ✓ | | | | | |
| wesl | ✓ | ✓ | | | | |
| wgsl | ✓ | | | | | `wgsl-analyzer` |
| wit | ✓ | | ✓ | | | |
| wren | ✓ | ✓ | ✓ | | | |
| xit | ✓ | | | | | |
| xml | ✓ | ✓ | ✓ | | ✓ | |
| xtc | ✓ | | | | | |
| yaml | ✓ | ✓ | ✓ | | ✓ | `yaml-language-server`, `ansible-language-server` |
| yara | ✓ | | | | | `yls` |
| yuck | ✓ | | | | | |
| zig | ✓ | ✓ | ✓ | | | `zls` |

View File

@@ -1,4 +1,4 @@
# Guides
This section contains guides for adding new language server configurations,
tree-sitter grammars, textobject queries, and other similar items.
tree-sitter grammars, textobject and rainbow bracket queries, and other similar items.

View File

@@ -0,0 +1,132 @@
# Adding Rainbow Bracket Queries
Helix uses `rainbows.scm` tree-sitter query files to provide rainbow bracket
functionality.
Tree-sitter queries are documented in the tree-sitter online documentation.
If you're writing queries for the first time, be sure to check out the section
on [syntax highlighting queries] and on [query syntax].
Rainbow queries have two captures: `@rainbow.scope` and `@rainbow.bracket`.
`@rainbow.scope` should capture any node that increases the nesting level
while `@rainbow.bracket` should capture any bracket nodes. Put another way:
`@rainbow.scope` switches to the next rainbow color for all nodes in the tree
under it while `@rainbow.bracket` paints captured nodes with the current
rainbow color.
For an example, let's add rainbow queries for the tree-sitter query (TSQ)
language itself. These queries will go into a
`runtime/queries/tsq/rainbows.scm` file in the repository root.
First we'll add the `@rainbow.bracket` captures. TSQ only has parentheses and
square brackets:
```tsq
["(" ")" "[" "]"] @rainbow.bracket
```
The ordering of the nodes within the alternation (square brackets) is not
taken into consideration.
> Note: Why are these nodes quoted? Most syntax highlights capture text
> surrounded by parentheses. These are _named nodes_ and correspond to the
> names of rules in the grammar. Brackets are usually written in tree-sitter
> grammars as literal strings, for example:
>
> ```js
> {
> // ...
> arguments: seq("(", repeat($.argument), ")"),
> // ...
> }
> ```
>
> Nodes written as literal strings in tree-sitter grammars may be captured
> in queries with those same literal strings.
Then we'll add `@rainbow.scope` captures. The easiest way to do this is to
view the `grammar.js` file in the tree-sitter grammar's repository. For TSQ,
that file is [here][tsq grammar.js]. As we scroll down the `grammar.js`, we
see that the `(alternation)`, (L36) `(group)` (L57), `(named_node)` (L59),
`(predicate)` (L87) and `(wildcard_node)` (L97) nodes all contain literal
parentheses or square brackets in their definitions. These nodes are all
direct parents of brackets and happen to also be the nodes we want to change
to the next rainbow color, so we capture them as `@rainbow.scope`.
```tsq
[
(group)
(named_node)
(wildcard_node)
(predicate)
(alternation)
] @rainbow.scope
```
This strategy works as a rule of thumb for most programming and configuration
languages. Markup languages can be trickier and may take additional
experimentation to find the correct nodes to use for scopes and brackets.
The `:tree-sitter-subtree` command shows the syntax tree under the primary
selection in S-expression format and can be a useful tool for determining how
to write a query.
### Properties
The `rainbow.include-children` property may be applied to `@rainbow.scope`
captures. By default, all `@rainbow.bracket` captures must be direct descendant
of a node captured with `@rainbow.scope` in a syntax tree in order to be
highlighted. The `rainbow.include-children` property disables that check and
allows `@rainbow.bracket` captures to be highlighted if they are direct or
indirect descendants of some node captured with `@rainbow.scope`.
For example, this property is used in the HTML rainbow queries.
For a document like `<a>link</a>`, the syntax tree is:
```tsq
(element ; <a>link</a>
(start_tag ; <a>
(tag_name)) ; a
(text) ; link
(end_tag ; </a>
(tag_name))) ; a
```
If we want to highlight the `<`, `>` and `</` nodes with rainbow colors, we
capture them as `@rainbow.bracket`:
```tsq
["<" ">" "</"] @rainbow.bracket
```
And we capture `(element)` as `@rainbow.scope` because `(element)` nodes nest
within each other: they increment the nesting level and switch to the next
color in the rainbow.
```tsq
(element) @rainbow.scope
```
But this combination of `@rainbow.scope` and `@rainbow.bracket` will not
highlight any nodes. `<`, `>` and `</` are children of the `(start_tag)` and
`(end_tag)` nodes. We can't capture `(start_tag)` and `(end_tag)` as
`@rainbow.scope` because they don't nest other elements. We can fix this case
by removing the requirement that `<`, `>` and `</` are direct descendants of
`(element)` using the `rainbow.include-children` property.
```tsq
((element) @rainbow.scope
(#set! rainbow.include-children))
```
With this property set, `<`, `>`, and `</` will highlight with rainbow colors
even though they aren't direct descendents of the `(element)` node.
`rainbow.include-children` is not necessary for the vast majority of programming
languages. It is only necessary when the node that increments the nesting level
(changes rainbow color) is not the direct parent of the bracket node.
[syntax highlighting queries]: https://tree-sitter.github.io/tree-sitter/syntax-highlighting#highlights
[query syntax]: https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries
[tsq grammar.js]: https://github.com/the-mikedavis/tree-sitter-tsq/blob/48b5e9f82ae0a4727201626f33a17f69f8e0ff86/grammar.js

View File

@@ -74,6 +74,7 @@ These configuration keys are available:
| `word-completion` | Overrides the [`editor.word-completion`](./editor.md#editorword-completion-section) configuration for the language. |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml`. Overwrites the setting of the same name in `config.toml` if set. |
| `persistent-diagnostic-sources` | An array of LSP diagnostic sources assumed unchanged when the language server resends the same set of diagnostics. Helix can track the position for these diagnostics internally instead. Useful for diagnostics that are recomputed on save.
| `rainbow-brackets` | Overrides the `editor.rainbow-brackets` config key for the language |
### File-type detection and the `file-types` key

View File

@@ -130,6 +130,17 @@ inherits = "boo_berry"
berry = "#2A2A4D"
```
### Rainbow
The `rainbow` key is used for rainbow highlight for matching brackets.
The key is a list of styles.
```toml
rainbow = ["#ff0000", "#ffa500", "#fff000", { fg = "#00ff00", modifiers = ["bold"] }]
```
Colors from the palette and modifiers may be used.
### Scopes
The following is a list of scopes available to use for styling:

View File

@@ -13,6 +13,7 @@ use std::{
use anyhow::{Context, Result};
use arc_swap::{ArcSwap, Guard};
use config::{Configuration, FileType, LanguageConfiguration, LanguageServerConfiguration};
use foldhash::HashSet;
use helix_loader::grammar::get_language;
use helix_stdx::rope::RopeSliceExt as _;
use once_cell::sync::OnceCell;
@@ -22,7 +23,7 @@ use tree_house::{
query_iter::QueryIter,
tree_sitter::{
query::{InvalidPredicateError, UserPredicate},
Grammar, InactiveQueryCursor, InputEdit, Node, Query, RopeInput, Tree,
Capture, Grammar, InactiveQueryCursor, InputEdit, Node, Pattern, Query, RopeInput, Tree,
},
Error, InjectionLanguageMarker, LanguageConfig as SyntaxConfig, Layer,
};
@@ -42,6 +43,7 @@ pub struct LanguageData {
indent_query: OnceCell<Option<IndentQuery>>,
textobject_query: OnceCell<Option<TextObjectQuery>>,
tag_query: OnceCell<Option<TagQuery>>,
rainbow_query: OnceCell<Option<RainbowQuery>>,
}
impl LanguageData {
@@ -52,6 +54,7 @@ impl LanguageData {
indent_query: OnceCell::new(),
textobject_query: OnceCell::new(),
tag_query: OnceCell::new(),
rainbow_query: OnceCell::new(),
}
}
@@ -198,6 +201,36 @@ impl LanguageData {
.as_ref()
}
/// Compiles the rainbows.scm query for a language.
/// This function should only be used by this module or the xtask crate.
pub fn compile_rainbow_query(
grammar: Grammar,
config: &LanguageConfiguration,
) -> Result<Option<RainbowQuery>> {
let name = &config.language_id;
let text = read_query(name, "rainbows.scm");
if text.is_empty() {
return Ok(None);
}
let rainbow_query = RainbowQuery::new(grammar, &text)
.with_context(|| format!("Failed to compile rainbows.scm query for '{name}'"))?;
Ok(Some(rainbow_query))
}
fn rainbow_query(&self, loader: &Loader) -> Option<&RainbowQuery> {
self.rainbow_query
.get_or_init(|| {
let grammar = self.syntax_config(loader)?.grammar;
Self::compile_rainbow_query(grammar, &self.config)
.map_err(|err| {
log::error!("{err}");
})
.ok()
.flatten()
})
.as_ref()
}
fn reconfigure(&self, scopes: &[String]) {
if let Some(Some(config)) = self.syntax.get() {
reconfigure_highlights(config, scopes);
@@ -387,6 +420,10 @@ impl Loader {
self.language(lang).tag_query(self)
}
fn rainbow_query(&self, lang: Language) -> Option<&RainbowQuery> {
self.language(lang).rainbow_query(self)
}
pub fn language_server_configs(&self) -> &HashMap<String, LanguageServerConfiguration> {
&self.language_server_configs
}
@@ -572,6 +609,79 @@ impl Syntax {
range,
)
}
pub fn rainbow_highlights(
&self,
source: RopeSlice,
rainbow_length: usize,
loader: &Loader,
range: impl RangeBounds<u32>,
) -> OverlayHighlights {
struct RainbowScope<'tree> {
end: u32,
node: Option<Node<'tree>>,
highlight: Highlight,
}
let mut scope_stack = Vec::<RainbowScope>::new();
let mut highlights = Vec::new();
let mut query_iter = self.query_iter::<_, (), _>(
source,
|lang| loader.rainbow_query(lang).map(|q| &q.query),
range,
);
while let Some(event) = query_iter.next() {
let QueryIterEvent::Match(mat) = event else {
continue;
};
let rainbow_query = loader
.rainbow_query(query_iter.current_language())
.expect("language must have a rainbow query to emit matches");
let byte_range = mat.node.byte_range();
// Pop any scopes that end before this capture begins.
while scope_stack
.last()
.is_some_and(|scope| byte_range.start >= scope.end)
{
scope_stack.pop();
}
let capture = Some(mat.capture);
if capture == rainbow_query.scope_capture {
scope_stack.push(RainbowScope {
end: byte_range.end,
node: if rainbow_query
.include_children_patterns
.contains(&mat.pattern)
{
None
} else {
Some(mat.node.clone())
},
highlight: Highlight::new((scope_stack.len() % rainbow_length) as u32),
});
} else if capture == rainbow_query.bracket_capture {
if let Some(scope) = scope_stack.last() {
if !scope
.node
.as_ref()
.is_some_and(|node| mat.node.parent().as_ref() != Some(node))
{
let start = source
.byte_to_char(source.floor_char_boundary(byte_range.start as usize));
let end =
source.byte_to_char(source.ceil_char_boundary(byte_range.end as usize));
highlights.push((scope.highlight, start..end));
}
}
}
}
OverlayHighlights::Heterogenous { highlights }
}
}
pub type Highlighter<'a> = highlighter::Highlighter<'a, 'a, Loader>;
@@ -1019,6 +1129,57 @@ fn pretty_print_tree_impl<W: fmt::Write>(
Ok(())
}
/// Finds the child of `node` which contains the given byte range.
pub fn child_for_byte_range<'a>(node: &Node<'a>, range: ops::Range<u32>) -> Option<Node<'a>> {
for child in node.children() {
let child_range = child.byte_range();
if range.start >= child_range.start && range.end <= child_range.end {
return Some(child);
}
}
None
}
#[derive(Debug)]
pub struct RainbowQuery {
query: Query,
include_children_patterns: HashSet<Pattern>,
scope_capture: Option<Capture>,
bracket_capture: Option<Capture>,
}
impl RainbowQuery {
fn new(grammar: Grammar, source: &str) -> Result<Self, tree_sitter::query::ParseError> {
let mut include_children_patterns = HashSet::default();
let query = Query::new(grammar, source, |pattern, predicate| match predicate {
UserPredicate::SetProperty {
key: "rainbow.include-children",
val,
} => {
if val.is_some() {
return Err(
"property 'rainbow.include-children' does not take an argument".into(),
);
}
include_children_patterns.insert(pattern);
Ok(())
}
_ => Err(InvalidPredicateError::unknown(predicate)),
})?;
Ok(Self {
include_children_patterns,
scope_capture: query.get_capture("rainbow.scope"),
bracket_capture: query.get_capture("rainbow.bracket"),
query,
})
}
}
#[cfg(test)]
mod test {
use once_cell::sync::Lazy;

View File

@@ -101,6 +101,8 @@ pub struct LanguageConfiguration {
pub workspace_lsp_roots: Option<Vec<PathBuf>>,
#[serde(default)]
pub persistent_diagnostic_sources: Vec<String>,
/// Overrides the `editor.rainbow-brackets` config key for the language.
pub rainbow_brackets: Option<bool>,
}
impl LanguageConfiguration {

View File

@@ -13,6 +13,7 @@ pub enum TsFeature {
TextObject,
AutoIndent,
Tags,
RainbowBracket,
}
impl TsFeature {
@@ -22,6 +23,7 @@ impl TsFeature {
Self::TextObject,
Self::AutoIndent,
Self::Tags,
Self::RainbowBracket,
]
}
@@ -31,6 +33,7 @@ impl TsFeature {
Self::TextObject => "textobjects.scm",
Self::AutoIndent => "indents.scm",
Self::Tags => "tags.scm",
Self::RainbowBracket => "rainbows.scm",
}
}
@@ -40,6 +43,7 @@ impl TsFeature {
Self::TextObject => "Treesitter Textobjects",
Self::AutoIndent => "Auto Indent",
Self::Tags => "Code Navigation Tags",
Self::RainbowBracket => "Rainbow Brackets",
}
}
@@ -49,6 +53,7 @@ impl TsFeature {
Self::TextObject => "Textobject",
Self::AutoIndent => "Indent",
Self::Tags => "Tags",
Self::RainbowBracket => "Rainbow",
}
}
}

View File

@@ -127,6 +127,18 @@ impl EditorView {
&text_annotations,
));
if doc
.language_config()
.and_then(|config| config.rainbow_brackets)
.unwrap_or(config.rainbow_brackets)
{
if let Some(overlay) =
Self::doc_rainbow_highlights(doc, view_offset.anchor, inner.height, theme, &loader)
{
overlays.push(overlay);
}
}
Self::doc_diagnostics_highlights_into(doc, theme, &mut overlays);
if is_focused {
@@ -304,6 +316,27 @@ impl EditorView {
text_annotations.collect_overlay_highlights(range)
}
pub fn doc_rainbow_highlights(
doc: &Document,
anchor: usize,
height: u16,
theme: &Theme,
loader: &syntax::Loader,
) -> Option<OverlayHighlights> {
let syntax = doc.syntax()?;
let text = doc.text().slice(..);
let row = text.char_to_line(anchor.min(text.len_chars()));
let visible_range = Self::viewport_byte_range(text, row, height);
let start = syntax::child_for_byte_range(
&syntax.tree().root_node(),
visible_range.start as u32..visible_range.end as u32,
)
.map_or(visible_range.start as u32, |node| node.start_byte());
let range = start..visible_range.end as u32;
Some(syntax.rainbow_highlights(text, theme.rainbow_length(), loader, range))
}
/// Get highlight spans for document diagnostics
pub fn doc_diagnostics_highlights_into(
doc: &Document,

View File

@@ -379,6 +379,8 @@ pub struct Config {
/// Whether to read settings from [EditorConfig](https://editorconfig.org) files. Defaults to
/// `true`.
pub editor_config: bool,
/// Whether to render rainbow colors for matching brackets. Defaults to `false`.
pub rainbow_brackets: bool,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)]
@@ -1058,6 +1060,7 @@ impl Default for Config {
end_of_line_diagnostics: DiagnosticFilter::Enable(Severity::Hint),
clipboard_provider: ClipboardProvider::default(),
editor_config: true,
rainbow_brackets: false,
}
}
}

View File

@@ -227,6 +227,7 @@ pub struct Theme {
// tree-sitter highlight styles are stored in a Vec to optimize lookups
scopes: Vec<String>,
highlights: Vec<Style>,
rainbow_length: usize,
}
impl From<Value> for Theme {
@@ -253,12 +254,20 @@ impl<'de> Deserialize<'de> for Theme {
}
}
#[allow(clippy::type_complexity)]
fn build_theme_values(
mut values: Map<String, Value>,
) -> (HashMap<String, Style>, Vec<String>, Vec<Style>, Vec<String>) {
) -> (
HashMap<String, Style>,
Vec<String>,
Vec<Style>,
usize,
Vec<String>,
) {
let mut styles = HashMap::new();
let mut scopes = Vec::new();
let mut highlights = Vec::new();
let mut rainbow_length = 0;
let mut warnings = Vec::new();
@@ -277,6 +286,27 @@ fn build_theme_values(
styles.reserve(values.len());
scopes.reserve(values.len());
highlights.reserve(values.len());
for (i, style) in values
.remove("rainbow")
.and_then(|value| match palette.parse_style_array(value) {
Ok(styles) => Some(styles),
Err(err) => {
warnings.push(err);
None
}
})
.unwrap_or_else(default_rainbow)
.into_iter()
.enumerate()
{
let name = format!("rainbow.{i}");
styles.insert(name.clone(), style);
scopes.push(name);
highlights.push(style);
rainbow_length += 1;
}
for (name, style_value) in values {
let mut style = Style::default();
if let Err(err) = palette.parse_style(&mut style, style_value) {
@@ -289,9 +319,19 @@ fn build_theme_values(
highlights.push(style);
}
(styles, scopes, highlights, warnings)
(styles, scopes, highlights, rainbow_length, warnings)
}
fn default_rainbow() -> Vec<Style> {
vec![
Style::default().fg(Color::Red),
Style::default().fg(Color::Yellow),
Style::default().fg(Color::Green),
Style::default().fg(Color::Blue),
Style::default().fg(Color::Cyan),
Style::default().fg(Color::Magenta),
]
}
impl Theme {
/// To allow `Highlight` to represent arbitrary RGB colors without turning it into an enum,
/// we interpret the last 256^3 numbers as RGB.
@@ -382,6 +422,10 @@ impl Theme {
})
}
pub fn rainbow_length(&self) -> usize {
self.rainbow_length
}
fn from_toml(value: Value) -> (Self, Vec<String>) {
if let Value::Table(table) = value {
Theme::from_keys(table)
@@ -392,12 +436,14 @@ impl Theme {
}
fn from_keys(toml_keys: Map<String, Value>) -> (Self, Vec<String>) {
let (styles, scopes, highlights, load_errors) = build_theme_values(toml_keys);
let (styles, scopes, highlights, rainbow_length, load_errors) =
build_theme_values(toml_keys);
let theme = Self {
styles,
scopes,
highlights,
rainbow_length,
..Default::default()
};
(theme, load_errors)
@@ -541,6 +587,21 @@ impl ThemePalette {
}
Ok(())
}
fn parse_style_array(&self, value: Value) -> Result<Vec<Style>, String> {
let mut styles = Vec::new();
for v in value
.as_array()
.ok_or_else(|| format!("Could not parse value as an array: '{value}'"))?
{
let mut style = Style::default();
self.parse_style(&mut style, v.clone())?;
styles.push(style);
}
Ok(styles)
}
}
impl TryFrom<Value> for ThemePalette {

View File

@@ -0,0 +1,20 @@
[
(function_definition)
(compound_statement)
(subshell)
(test_command)
(subscript)
(parenthesized_expression)
(array)
(expansion)
(command_substitution)
] @rainbow.scope
[
"(" ")"
"((" "))"
"${" "$("
"{" "}"
"[" "]"
"[[" "]]"
] @rainbow.bracket

View File

@@ -0,0 +1,29 @@
[
(preproc_params)
(preproc_defined)
(argument_list)
(attribute_specifier)
(ms_declspec_modifier)
(declaration_list)
(parenthesized_declarator)
(parenthesized_expression)
(abstract_parenthesized_declarator)
(array_declarator)
(compound_statement)
(initializer_list)
(compound_literal_expression)
(enumerator_list)
(field_declaration_list)
(parameter_list)
(for_statement)
(macro_type_specifier)
(subscript_expression)
(subscript_designator)
(cast_expression)
] @rainbow.scope
[
"(" ")"
"{" "}"
"[" "]"
] @rainbow.bracket

View File

@@ -0,0 +1,13 @@
[
(list_lit)
(map_lit)
(vec_lit)
(anon_fn_lit)
] @rainbow.scope
[
"(" ")"
"#"
"{" "}"
"[" "]"
] @rainbow.bracket

View File

@@ -0,0 +1 @@
; inherits: scheme

View File

@@ -0,0 +1,49 @@
[
; c
(preproc_params)
(preproc_defined)
(argument_list)
(attribute_specifier)
(ms_declspec_modifier)
(declaration_list)
(parenthesized_declarator)
(parenthesized_expression)
(abstract_parenthesized_declarator)
(array_declarator)
(compound_statement)
(initializer_list)
(compound_literal_expression)
(enumerator_list)
(field_declaration_list)
(parameter_list)
(for_statement)
; (macro_type_specifier) - not part of cpp
(subscript_expression)
(subscript_designator)
(cast_expression)
; cpp
(decltype)
(explicit_function_specifier)
(template_parameter_list)
(template_argument_list)
(parameter_list)
(argument_list)
(structured_binding_declarator)
(noexcept)
(throw_specifier)
(static_assert_declaration)
(condition_clause)
(for_range_loop)
(new_declarator)
(delete_expression "[" "]")
(lambda_capture_specifier)
(sizeof_expression)
] @rainbow.scope
[
"(" ")"
"{" "}"
"[" "]"
"<" ">"
] @rainbow.bracket

View File

@@ -0,0 +1,15 @@
[
(keyframe_block_list)
(block)
(attribute_selector)
(feature_query)
(parenthesized_query)
(selector_query)
(parenthesized_value)
(arguments)
] @rainbow.scope
[
"{" "}"
"(" ")"
] @rainbow.bracket

View File

@@ -0,0 +1,28 @@
[
(export_clause)
(named_imports)
(statement_block)
(for_statement)
(for_in_statement)
(switch_body)
(catch_clause "(" ")")
(parenthesized_expression)
(object)
(object_pattern)
(array)
(array_pattern)
(subscript_expression)
(template_substitution)
(arguments)
(class_body)
(formal_parameters)
(computed_property_name)
] @rainbow.scope
[
"(" ")"
"${" "{" "}"
"[" "]"
] @rainbow.bracket
(regex "/" @rainbow.bracket) @rainbow.scope

View File

@@ -0,0 +1,24 @@
[
(block)
(interpolation)
(list)
(tuple)
(bitstring)
(map)
; short-hand function captures like &(&1 + &2)
(unary_operator
operator: "&")
(arguments "(" ")")
(access_call)
(sigil)
] @rainbow.scope
[
"(" ")"
"%"
"{" "}"
"[" "]"
"<<" ">>"
"#{"
"|"
] @rainbow.bracket

View File

@@ -0,0 +1,24 @@
[
; ()
(arguments "(" ")")
(parenthesized_expression)
(function_type)
; #{}
(record)
(map)
; {}
(map_update)
(tuple)
; <<>>
(bitstring)
; []
(list)
] @rainbow.scope
[
"#"
"{" "}"
"(" ")"
"[" "]"
"<<" ">>"
] @rainbow.bracket

View File

@@ -0,0 +1,32 @@
[
(target_group)
(unqualified_imports)
(tuple)
(list)
(function)
(function_parameters)
(todo)
(tuple)
(list)
(anonymous_function)
(block)
(case)
(record_update)
(arguments)
(record_pattern_arguments)
(tuple_pattern)
(list_pattern)
(type_definition)
(data_constructor_arguments)
(tuple_type)
(function_parameter_types)
(type_arguments)
(type_parameters)
] @rainbow.scope
[
"(" ")"
"[" "]"
"{" "}"
"#"
] @rainbow.bracket

View File

@@ -0,0 +1,33 @@
[
(import_spec_list)
(const_declaration)
(var_declaration)
(type_parameter_list)
(parameter_list)
(type_declaration)
(parenthesized_type)
(type_arguments)
(array_type)
(implicit_length_array_type)
(slice_type)
(field_declaration_list)
(interface_type)
(map_type)
(block)
(expression_switch_statement)
(type_switch_statement)
(select_statement)
(parenthesized_expression)
(argument_list)
(index_expression)
(slice_expression)
(type_assertion_expression)
(type_conversion_expression)
(literal_value)
] @rainbow.scope
[
"(" ")"
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -0,0 +1,13 @@
[
(doctype)
(erroneous_end_tag)
] @rainbow.scope
([
(element)
(script_element)
(style_element)
] @rainbow.scope
(#set! rainbow.include-children))
["<" ">" "<!" "</" "/>"] @rainbow.bracket

View File

@@ -0,0 +1,35 @@
[
(cast_expression)
(inferred_parameters)
(dimensions_expr)
(parenthesized_expression)
(array_access)
(argument_list)
(type_arguments)
(dimensions)
(block)
(switch_block)
(catch_clause)
(resource_specification)
(for_statement)
(enhanced_for_statement)
(annotation_argument_list)
(element_value_array_initializer)
(module_body)
(enum_body)
(type_parameters)
(class_body)
(constructor_body)
(annotation_type_body)
(annotation_type_element_declaration)
(interface_body)
(array_initializer)
(formal_parameters)
] @rainbow.scope
[
"(" ")"
"{" "}"
"[" "]"
"<" ">"
] @rainbow.bracket

View File

@@ -0,0 +1 @@
; inherits: ecma

View File

@@ -0,0 +1,9 @@
[
(object)
(array)
] @rainbow.scope
[
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -0,0 +1,9 @@
; inherits: ecma
[
(jsx_expression)
] @rainbow.scope
(jsx_opening_element ["<" ">"] @rainbow.bracket) @rainbow.scope
(jsx_closing_element ["</" ">"] @rainbow.bracket) @rainbow.scope
(jsx_self_closing_element ["<" "/>"] @rainbow.bracket) @rainbow.scope

View File

@@ -0,0 +1,17 @@
[
(formals)
(parenthesized_expression)
(attrset_expression)
(let_attrset_expression)
(rec_attrset_expression)
(inherit_from)
(interpolation)
(list_expression)
] @rainbow.scope
[
"${"
"{" "}"
"(" ")"
"[" "]"
] @rainbow.bracket

View File

@@ -0,0 +1,30 @@
[
(future_import_statement)
(import_from_statement)
(with_clause)
(parameters)
(parenthesized_list_splat)
(argument_list)
(tuple_pattern)
(list_pattern)
(subscript)
(list)
(set)
(tuple)
(dictionary)
(dictionary_comprehension)
(set_comprehension)
(list_comprehension)
(generator_expression)
(parenthesized_expression)
(interpolation)
(format_expression)
] @rainbow.scope
[
"(" ")"
"{" "}"
"[" "]"
] @rainbow.bracket
; (string ["{{" "}}"] @rainbow.bracket) @rainbow.scope

View File

@@ -0,0 +1 @@
; inherits: scheme

View File

@@ -0,0 +1,17 @@
[
(lookahead_assertion)
(character_class)
(anonymous_capturing_group)
(named_capturing_group)
(non_capturing_group)
(count_quantifier)
(character_class_escape)
] @rainbow.scope
[
"(?" "(?:"
"(?<" ">"
"(" ")"
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -0,0 +1,28 @@
[
(begin_block)
(end_block)
(singleton_method)
(block_parameters)
(parenthesized_statements)
(element_reference)
(argument_list "(" ")")
(block)
(destructured_left_assignment)
(interpolation)
(string_array)
(symbol_array)
(regex)
(array)
(hash)
(method_parameters)
] @rainbow.scope
[
"#{"
"{" "}"
"(" ")"
"%w(" "%i("
"[" "]"
"|"
"/"
] @rainbow.bracket

View File

@@ -0,0 +1,60 @@
[
; {/}
(declaration_list)
(field_declaration_list)
(field_initializer_list)
(enum_variant_list)
(block)
(match_block)
(use_list)
(struct_pattern)
; (/)
(ordered_field_declaration_list)
(arguments)
(parameters)
(tuple_type)
(tuple_expression)
(tuple_pattern)
(tuple_struct_pattern)
(unit_type)
(unit_expression)
(visibility_modifier)
(parenthesized_expression)
(token_repetition_pattern)
; </>
(type_parameters)
(type_arguments)
(bracketed_type)
(for_lifetimes)
; [/]
(array_type)
(array_expression)
(index_expression)
(slice_pattern)
; attributes #[]
(attribute_item)
(inner_attribute_item)
; macros
(token_tree_pattern)
(macro_definition)
; closures
(closure_parameters)
] @rainbow.scope
; attributes like `#[serde(rename_all = "kebab-case")]`
(attribute arguments: (token_tree) @rainbow.scope)
[
"#"
"[" "]"
"(" ")"
"{" "}"
"<" ">"
"|"
] @rainbow.bracket

View File

@@ -0,0 +1,12 @@
[
(list)
(vector)
(byte_vector)
] @rainbow.scope
[
"#(" "#vu8("
"(" ")"
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -0,0 +1,3 @@
; inherits: css
(parameters) @rainbow.scope

View File

@@ -0,0 +1 @@
; inherits: python

View File

@@ -0,0 +1,12 @@
[
(table_array_element)
(table)
(array)
(inline_table)
] @rainbow.scope
[
"[[" "]]"
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -0,0 +1,2 @@
; inherits: typescript
; inherits: jsx

View File

@@ -0,0 +1,19 @@
; inherits: ecma
[
(import_require_clause)
(enum_body)
(lookup_type)
(parenthesized_type)
(object_type)
(type_parameters)
(index_signature)
(array_type)
(tuple_type)
] @rainbow.scope
(type_arguments ["<" ">"] @rainbow.bracket) @rainbow.scope
[
"{|" "|}"
] @rainbow.bracket

View File

@@ -0,0 +1,29 @@
[
(processing_instructions)
(cdata_sect)
(xml_decl)
(doctype_decl)
(element_decl)
(element_choice)
(element_seq)
(mixed)
(attlist_decl)
(notation_type)
(enumeration)
(ge_decl)
(pe_decl)
(notation_decl)
] @rainbow.scope
((element) @rainbow.scope
(#set! rainbow.include-children))
[
"<?" "?>"
"<" ">"
"</" "/>"
"<!"
"(" ")"
")*"
"[" "]"
] @rainbow.bracket

View File

@@ -0,0 +1,9 @@
[
(flow_sequence)
(flow_mapping)
] @rainbow.scope
[
"[" "]"
"{" "}"
] @rainbow.bracket

View File

@@ -37,6 +37,7 @@ pub mod tasks {
LanguageData::compile_indent_query(grammar, config)?;
LanguageData::compile_textobject_query(grammar, config)?;
LanguageData::compile_tag_query(grammar, config)?;
LanguageData::compile_rainbow_query(grammar, config)?;
}
println!("Query check succeeded");