diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 62bd838d474d..e6bc5b735720 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -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) diff --git a/book/src/editor.md b/book/src/editor.md index b919250985e5..052b94c357e5 100644 --- a/book/src/editor.md +++ b/book/src/editor.md @@ -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 diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 2875cb72405a..e6ca8bce7c34 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -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` | diff --git a/book/src/guides/README.md b/book/src/guides/README.md index c25768e68961..e53983d60fb1 100644 --- a/book/src/guides/README.md +++ b/book/src/guides/README.md @@ -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. diff --git a/book/src/guides/rainbow_bracket_queries.md b/book/src/guides/rainbow_bracket_queries.md new file mode 100644 index 000000000000..1cba6a9907d1 --- /dev/null +++ b/book/src/guides/rainbow_bracket_queries.md @@ -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 `link`, the syntax tree is: + +```tsq +(element ; link + (start_tag ; + (tag_name)) ; a + (text) ; link + (end_tag ; + (tag_name))) ; a +``` + +If we want to highlight the `<`, `>` and `" "` and `` and ``, and `>, textobject_query: OnceCell>, tag_query: OnceCell>, + rainbow_query: OnceCell>, } 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> { + 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 { &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, + ) -> OverlayHighlights { + struct RainbowScope<'tree> { + end: u32, + node: Option>, + highlight: Highlight, + } + + let mut scope_stack = Vec::::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( 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) -> Option> { + 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, + scope_capture: Option, + bracket_capture: Option, +} + +impl RainbowQuery { + fn new(grammar: Grammar, source: &str) -> Result { + 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; diff --git a/helix-core/src/syntax/config.rs b/helix-core/src/syntax/config.rs index ddff26f17f5a..6299ceb2bb5b 100644 --- a/helix-core/src/syntax/config.rs +++ b/helix-core/src/syntax/config.rs @@ -101,6 +101,8 @@ pub struct LanguageConfiguration { pub workspace_lsp_roots: Option>, #[serde(default)] pub persistent_diagnostic_sources: Vec, + /// Overrides the `editor.rainbow-brackets` config key for the language. + pub rainbow_brackets: Option, } impl LanguageConfiguration { diff --git a/helix-term/src/health.rs b/helix-term/src/health.rs index fcaf2b568ed3..78b51939b0f9 100644 --- a/helix-term/src/health.rs +++ b/helix-term/src/health.rs @@ -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", } } } diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 9343d55d4083..1f0ff4b3ee44 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -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 { + 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, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 1051d2c40f4e..34854054b38f 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -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, } } } diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 77fa78331146..e2e109328cb8 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -227,6 +227,7 @@ pub struct Theme { // tree-sitter highlight styles are stored in a Vec to optimize lookups scopes: Vec, highlights: Vec