From 136be19533931b94b4d36dc96db0b3f7addc229d Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Wed, 4 Feb 2026 16:49:04 -0700 Subject: [PATCH] feat(highlight): migrate to tree-house with Helix queries Replace tree-sitter-highlight dep with tree-house crate from Helix editor. Add ropey dependency required by tree-house. Reorganize query files from Helix's runtime/queries/ for all 14 supported languages: - bash, c, css, go, html, javascript, json, markdown, nix, python, rust, toml, typescript, yaml - Include ecma, _javascript, _typescript base dirs for JS/TS inheritance - Copy highlights.scm, injections.scm, locals.scm where available This commit establishes the foundation; highlight.rs implementation will follow in subsequent commits. --- Cargo.lock | 161 +++++- Cargo.toml | 3 +- queries/_javascript/highlights.scm | 36 ++ queries/_javascript/locals.scm | 14 + queries/_typescript/highlights.scm | 148 +++++ queries/_typescript/locals.scm | 34 ++ queries/bash/highlights.scm | 250 +++++++++ queries/bash/injections.scm | 38 ++ queries/c/highlights.scm | 167 ++++++ queries/c/injections.scm | 2 + queries/c/locals.scm | 38 ++ queries/css/highlights.scm | 99 ++++ queries/css/injections.scm | 2 + queries/ecma/highlights.scm | 288 ++++++++++ queries/ecma/injections.scm | 100 ++++ queries/ecma/locals.scm | 26 + queries/go/highlights.scm | 236 ++++++++ queries/go/injections.scm | 92 ++++ queries/go/locals.scm | 25 + queries/html/highlights.scm | 47 ++ queries/html/injections.scm | 10 + queries/javascript/highlights.scm | 3 + queries/javascript/injections.scm | 3 + queries/javascript/locals.scm | 3 + queries/json/highlights.scm | 20 + queries/markdown/highlights.scm | 62 +++ queries/markdown/injections.scm | 22 + queries/md-injections.scm | 24 - .../highlights.scm} | 53 +- .../injections.scm} | 100 +++- queries/python/highlights.scm | 308 +++++++++++ queries/python/injections.scm | 14 + queries/python/locals.scm | 50 ++ queries/rust/highlights.scm | 514 ++++++++++++++++++ queries/rust/injections.scm | 217 ++++++++ queries/rust/locals.scm | 28 + queries/toml/highlights.scm | 48 ++ queries/toml/injections.scm | 2 + queries/typescript/highlights.scm | 3 + queries/typescript/injections.scm | 3 + queries/typescript/locals.scm | 3 + queries/yaml/highlights.scm | 42 ++ queries/yaml/injections.scm | 57 ++ 43 files changed, 3310 insertions(+), 85 deletions(-) create mode 100644 queries/_javascript/highlights.scm create mode 100644 queries/_javascript/locals.scm create mode 100644 queries/_typescript/highlights.scm create mode 100644 queries/_typescript/locals.scm create mode 100644 queries/bash/highlights.scm create mode 100644 queries/bash/injections.scm create mode 100644 queries/c/highlights.scm create mode 100644 queries/c/injections.scm create mode 100644 queries/c/locals.scm create mode 100644 queries/css/highlights.scm create mode 100644 queries/css/injections.scm create mode 100644 queries/ecma/highlights.scm create mode 100644 queries/ecma/injections.scm create mode 100644 queries/ecma/locals.scm create mode 100644 queries/go/highlights.scm create mode 100644 queries/go/injections.scm create mode 100644 queries/go/locals.scm create mode 100644 queries/html/highlights.scm create mode 100644 queries/html/injections.scm create mode 100644 queries/javascript/highlights.scm create mode 100644 queries/javascript/injections.scm create mode 100644 queries/javascript/locals.scm create mode 100644 queries/json/highlights.scm create mode 100644 queries/markdown/highlights.scm create mode 100644 queries/markdown/injections.scm delete mode 100644 queries/md-injections.scm rename queries/{nix-highlights.scm => nix/highlights.scm} (72%) rename queries/{nix-injections.scm => nix/injections.scm} (63%) create mode 100644 queries/python/highlights.scm create mode 100644 queries/python/injections.scm create mode 100644 queries/python/locals.scm create mode 100644 queries/rust/highlights.scm create mode 100644 queries/rust/injections.scm create mode 100644 queries/rust/locals.scm create mode 100644 queries/toml/highlights.scm create mode 100644 queries/toml/injections.scm create mode 100644 queries/typescript/highlights.scm create mode 100644 queries/typescript/injections.scm create mode 100644 queries/typescript/locals.scm create mode 100644 queries/yaml/highlights.scm create mode 100644 queries/yaml/injections.scm diff --git a/Cargo.lock b/Cargo.lock index b41cf95..c730399 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,6 +56,15 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "arc-swap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ded5f9a03ac8f24d1b8a25101ee812cd32cdc8c50a4c50237de2c4915850e73" +dependencies = [ + "rustversion", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -409,6 +418,12 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" @@ -477,6 +492,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "funty" version = "2.0.0" @@ -499,7 +520,7 @@ version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ - "unicode-width", + "unicode-width 0.2.2", ] [[package]] @@ -589,6 +610,17 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -731,6 +763,15 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "kstring" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -743,6 +784,16 @@ version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -1099,6 +1150,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -1269,6 +1330,19 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-cursor" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0497c781d2f982ae8284d2932aee6a877e58a4541daa5e8fadc18cc75c23a61d" +dependencies = [ + "log", + "memchr", + "regex-automata", + "regex-syntax", + "ropey", +] + [[package]] name = "regex-syntax" version = "0.8.8" @@ -1313,6 +1387,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ropey" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5" +dependencies = [ + "smallvec", + "str_indices", +] + [[package]] name = "rustc-hash" version = "2.1.1" @@ -1459,6 +1543,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "slug" version = "0.1.6" @@ -1475,6 +1565,18 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str_indices" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" + [[package]] name = "streaming-iterator" version = "0.1.9" @@ -1517,17 +1619,18 @@ dependencies = [ "lightningcss", "mermaid-rs-renderer", "pulldown-cmark", + "ropey", "serde", "tempfile", "tera", "thiserror 2.0.18", "toml 0.8.23", + "tree-house", "tree-sitter", "tree-sitter-bash", "tree-sitter-c", "tree-sitter-css", "tree-sitter-go", - "tree-sitter-highlight", "tree-sitter-html", "tree-sitter-javascript", "tree-sitter-json", @@ -1709,6 +1812,36 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "tree-house" +version = "0.3.0" +source = "git+https://github.com/helix-editor/tree-house#f05d27cb52b02209962cc0a2f87de303a2bec870" +dependencies = [ + "arc-swap", + "hashbrown 0.15.5", + "kstring", + "once_cell", + "pretty_assertions", + "regex", + "regex-cursor", + "ropey", + "slab", + "tree-house-bindings", + "unicode-width 0.1.12", +] + +[[package]] +name = "tree-house-bindings" +version = "0.2.2" +source = "git+https://github.com/helix-editor/tree-house#f05d27cb52b02209962cc0a2f87de303a2bec870" +dependencies = [ + "cc", + "libloading", + "regex-cursor", + "ropey", + "thiserror 2.0.18", +] + [[package]] name = "tree-sitter" version = "0.26.3" @@ -1763,18 +1896,6 @@ dependencies = [ "tree-sitter-language", ] -[[package]] -name = "tree-sitter-highlight" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0636662a03005d9289649e0b4a89ff37b75df5033e8d4a16398740ae6496d2" -dependencies = [ - "regex", - "streaming-iterator", - "thiserror 2.0.18", - "tree-sitter", -] - [[package]] name = "tree-sitter-html" version = "0.23.2" @@ -1920,6 +2041,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode-width" version = "0.2.2" @@ -2130,6 +2257,12 @@ dependencies = [ "hashlink", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "zerocopy" version = "0.8.33" diff --git a/Cargo.toml b/Cargo.toml index 0332a22..f0c3af9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,13 @@ thiserror = "2" walkdir = "2" # Syntax highlighting +ropey = "1.6" +tree-house = { git = "https://github.com/helix-editor/tree-house", package = "tree-house" } tree-sitter = "0.26" tree-sitter-bash = "0.23" tree-sitter-c = "0.24" tree-sitter-css = "0.25" tree-sitter-go = "0.25" -tree-sitter-highlight = "0.26" tree-sitter-html = "0.23" tree-sitter-javascript = "0.25" tree-sitter-json = "0.24" diff --git a/queries/_javascript/highlights.scm b/queries/_javascript/highlights.scm new file mode 100644 index 0000000..8b0bbb9 --- /dev/null +++ b/queries/_javascript/highlights.scm @@ -0,0 +1,36 @@ +; Function and method parameters +;------------------------------- + +; Javascript and Typescript Treesitter grammars deviate when defining the +; tree structure for parameters, so we need to address them in each specific +; language instead of ecma. + +; (p) +(formal_parameters + (identifier) @variable.parameter) + +; (...p) +(formal_parameters + (rest_pattern + (identifier) @variable.parameter)) + +; ({ p }) +(formal_parameters + (object_pattern + (shorthand_property_identifier_pattern) @variable.parameter)) + +; ({ a: p }) +(formal_parameters + (object_pattern + (pair_pattern + value: (identifier) @variable.parameter))) + +; ([ p ]) +(formal_parameters + (array_pattern + (identifier) @variable.parameter)) + +; (p = 1) +(formal_parameters + (assignment_pattern + left: (identifier) @variable.parameter)) diff --git a/queries/_javascript/locals.scm b/queries/_javascript/locals.scm new file mode 100644 index 0000000..7c7ffe1 --- /dev/null +++ b/queries/_javascript/locals.scm @@ -0,0 +1,14 @@ +; Definitions +;------------ +; Javascript and Typescript Treesitter grammars deviate when defining the +; tree structure for parameters, so we need to address them in each specific +; language instead of ecma. + +; (i) +(formal_parameters + (identifier) @local.definition.variable.parameter) + +; (i = 1) +(formal_parameters + (assignment_pattern + left: (identifier) @local.definition.variable.parameter)) diff --git a/queries/_typescript/highlights.scm b/queries/_typescript/highlights.scm new file mode 100644 index 0000000..0ec1f9a --- /dev/null +++ b/queries/_typescript/highlights.scm @@ -0,0 +1,148 @@ +; Namespaces +; ---------- + +(internal_module + [((identifier) @namespace) ((nested_identifier (identifier) @namespace))]) + +(ambient_declaration "global" @namespace) + +; Parameters +; ---------- +; Javascript and Typescript Treesitter grammars deviate when defining the +; tree structure for parameters, so we need to address them in each specific +; language instead of ecma. + +; (p: t) +; (p: t = 1) +(required_parameter + (identifier) @variable.parameter) + +; (...p: t) +(required_parameter + (rest_pattern + (identifier) @variable.parameter)) + +; ({ p }: { p: t }) +(required_parameter + (object_pattern + (shorthand_property_identifier_pattern) @variable.parameter)) + +; ({ a: p }: { a: t }) +(required_parameter + (object_pattern + (pair_pattern + value: (identifier) @variable.parameter))) + +; ([ p ]: t[]) +(required_parameter + (array_pattern + (identifier) @variable.parameter)) + +; (p?: t) +; (p?: t = 1) // Invalid but still possible to highlight. +(optional_parameter + (identifier) @variable.parameter) + +; (...p?: t) // Invalid but still possible to highlight. +(optional_parameter + (rest_pattern + (identifier) @variable.parameter)) + +; ({ p }: { p?: t}) +(optional_parameter + (object_pattern + (shorthand_property_identifier_pattern) @variable.parameter)) + +; ({ a: p }: { a?: t }) +(optional_parameter + (object_pattern + (pair_pattern + value: (identifier) @variable.parameter))) + +; ([ p ]?: t[]) // Invalid but still possible to highlight. +(optional_parameter + (array_pattern + (identifier) @variable.parameter)) + +(public_field_definition) @punctuation.special +(this_type) @variable.builtin +(type_predicate) @keyword.operator + +; Punctuation +; ----------- + +[ + ":" +] @punctuation.delimiter + +(optional_parameter "?" @punctuation.special) +(property_signature "?" @punctuation.special) + +(conditional_type ["?" ":"] @operator) +(ternary_expression ["?" ":"] @operator) + +; Keywords +; -------- + +[ + "abstract" + "declare" + "module" + "export" + "infer" + "implements" + "keyof" + "namespace" + "override" + "satisfies" +] @keyword + +[ + "type" + "interface" + "enum" +] @keyword.storage.type + +[ + "public" + "private" + "protected" + "readonly" +] @keyword.storage.modifier + +; Types +; ----- + +(type_identifier) @type +(type_parameter + name: (type_identifier) @type.parameter) +(predefined_type) @type.builtin + +; Type arguments and parameters +; ----------------------------- + +(type_arguments + [ + "<" + ">" + ] @punctuation.bracket) + +(type_parameters + [ + "<" + ">" + ] @punctuation.bracket) + +(omitting_type_annotation) @punctuation.special +(opting_type_annotation) @punctuation.special + +; Literals +; -------- + +[ + (template_literal_type) +] @string + +(import_require_clause + (identifier) "=" + ("require") @keyword) diff --git a/queries/_typescript/locals.scm b/queries/_typescript/locals.scm new file mode 100644 index 0000000..1a44288 --- /dev/null +++ b/queries/_typescript/locals.scm @@ -0,0 +1,34 @@ +; Scopes +;------- + +[ + (type_alias_declaration) + (class_declaration) + (interface_declaration) +] @local.scope + +; Definitions +;------------ + +(type_parameter + name: (type_identifier) @local.definition.type.parameter) + +; Javascript and Typescript Treesitter grammars deviate when defining the +; tree structure for parameters, so we need to address them in each specific +; language instead of ecma. + +; (i: t) +; (i: t = 1) +(required_parameter + (identifier) @local.definition.variable.parameter) + +; (i?: t) +; (i?: t = 1) // Invalid but still possible to highlight. +(optional_parameter + (identifier) @local.definition.variable.parameter) + +; References +;----------- + +(type_identifier) @local.reference +(identifier) @local.reference diff --git a/queries/bash/highlights.scm b/queries/bash/highlights.scm new file mode 100644 index 0000000..f01a347 --- /dev/null +++ b/queries/bash/highlights.scm @@ -0,0 +1,250 @@ +[ + "(" + ")" + "{" + "}" + "[" + "]" + "[[" + "]]" + "((" + "))" +] @punctuation.bracket + +[ + ";" + ";;" + ";&" + ";;&" + "&" +] @punctuation.delimiter + +[ + ">" + ">>" + "<" + "<<" + "&&" + "|" + "|&" + "||" + "=" + "+=" + "=~" + "==" + "!=" + "&>" + "&>>" + "<&" + ">&" + ">|" + "<&-" + ">&-" + "<<-" + "<<<" + ".." + "!" +] @operator + +[ + (string) + (raw_string) + (ansi_c_string) + (heredoc_body) +] @string + +[ + (heredoc_start) + (heredoc_end) +] @label + +(variable_assignment + (word) @string) + +(command + argument: "$" @string) ; bare dollar + +(concatenation + (word) @string) + +[ + "if" + "then" + "else" + "elif" + "fi" + "case" + "in" + "esac" +] @keyword.control.conditional + +[ + "for" + "do" + "done" + "select" + "until" + "while" +] @keyword.control.repeat + +[ + "declare" + "typeset" + "readonly" + "local" + "unset" + "unsetenv" +] @keyword + +"export" @keyword.control.import + +"function" @keyword.function + +(special_variable_name) @constant + +; trap -l +((word) @constant.builtin + (#any-of? @constant.builtin + "SIGHUP" "SIGINT" "SIGQUIT" "SIGILL" "SIGTRAP" "SIGABRT" "SIGBUS" "SIGFPE" "SIGKILL" "SIGUSR1" + "SIGSEGV" "SIGUSR2" "SIGPIPE" "SIGALRM" "SIGTERM" "SIGSTKFLT" "SIGCHLD" "SIGCONT" "SIGSTOP" + "SIGTSTP" "SIGTTIN" "SIGTTOU" "SIGURG" "SIGXCPU" "SIGXFSZ" "SIGVTALRM" "SIGPROF" "SIGWINCH" + "SIGIO" "SIGPWR" "SIGSYS" "SIGRTMIN" "SIGRTMIN+1" "SIGRTMIN+2" "SIGRTMIN+3" "SIGRTMIN+4" + "SIGRTMIN+5" "SIGRTMIN+6" "SIGRTMIN+7" "SIGRTMIN+8" "SIGRTMIN+9" "SIGRTMIN+10" "SIGRTMIN+11" + "SIGRTMIN+12" "SIGRTMIN+13" "SIGRTMIN+14" "SIGRTMIN+15" "SIGRTMAX-14" "SIGRTMAX-13" + "SIGRTMAX-12" "SIGRTMAX-11" "SIGRTMAX-10" "SIGRTMAX-9" "SIGRTMAX-8" "SIGRTMAX-7" "SIGRTMAX-6" + "SIGRTMAX-5" "SIGRTMAX-4" "SIGRTMAX-3" "SIGRTMAX-2" "SIGRTMAX-1" "SIGRTMAX")) + +((word) @constant.builtin.boolean + (#any-of? @constant.builtin.boolean "true" "false")) + +(comment) @comment + +(test_operator) @operator + +(command_substitution + "$(" @punctuation.special + ")" @punctuation.special) + +(process_substitution + [ + "<(" + ">(" + ] @punctuation.special + ")" @punctuation.special) + +(arithmetic_expansion + [ + "$((" + "((" + ] @punctuation.special + "))" @punctuation.special) + +(arithmetic_expansion + "," @punctuation.delimiter) + +(ternary_expression + [ + "?" + ":" + ] @keyword.control.conditional) + +(binary_expression + operator: _ @operator) + +(unary_expression + operator: _ @operator) + +(postfix_expression + operator: _ @operator) + +(function_definition + name: (word) @function) + +(command_name + (word) @function) + +(command_name + (word) @function.builtin + (#any-of? @function.builtin + "." ":" "alias" "bg" "bind" "break" "builtin" "caller" "cd" "command" "compgen" "complete" + "compopt" "continue" "coproc" "dirs" "disown" "echo" "enable" "eval" "exec" "exit" "false" "fc" + "fg" "getopts" "hash" "help" "history" "jobs" "kill" "let" "logout" "mapfile" "popd" "printf" + "pushd" "pwd" "read" "readarray" "return" "set" "shift" "shopt" "source" "suspend" "test" "time" + "times" "trap" "true" "type" "typeset" "ulimit" "umask" "unalias" "wait")) + +(command + argument: [ + (word) @variable.parameter + (concatenation + (word) @variable.parameter) + ]) + +(declaration_command + (word) @variable.parameter) + +(unset_command + (word) @variable.parameter) + +(number) @constant.numeric + +(file_redirect + (word) @string.special.path) + +(herestring_redirect + (word) @string) + +(file_descriptor) @operator + +(simple_expansion + "$" @punctuation.special) @none + +(expansion + "${" @punctuation.special + "}" @punctuation.special) @none + +(expansion + operator: _ @punctuation.special) + +(expansion + "@" + . + operator: _ @constant.character) + +((expansion + (subscript + index: (word) @constant.character)) + (#any-of? @constant.character "@" "*")) + +"``" @punctuation.special + +(variable_name) @variable + +((variable_name) @constant + (#match? @constant "^[A-Z][A-Z_0-9]*$")) + +((variable_name) @variable.builtin + (#any-of? @variable.builtin + ; https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Variables.html + "CDPATH" "HOME" "IFS" "MAIL" "MAILPATH" "OPTARG" "OPTIND" "PATH" "PS1" "PS2" + ; https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html + "_" "BASH" "BASHOPTS" "BASHPID" "BASH_ALIASES" "BASH_ARGC" "BASH_ARGV" "BASH_ARGV0" "BASH_CMDS" + "BASH_COMMAND" "BASH_COMPAT" "BASH_ENV" "BASH_EXECUTION_STRING" "BASH_LINENO" + "BASH_LOADABLES_PATH" "BASH_REMATCH" "BASH_SOURCE" "BASH_SUBSHELL" "BASH_VERSINFO" + "BASH_VERSION" "BASH_XTRACEFD" "CHILD_MAX" "COLUMNS" "COMP_CWORD" "COMP_LINE" "COMP_POINT" + "COMP_TYPE" "COMP_KEY" "COMP_WORDBREAKS" "COMP_WORDS" "COMPREPLY" "COPROC" "DIRSTACK" "EMACS" + "ENV" "EPOCHREALTIME" "EPOCHSECONDS" "EUID" "EXECIGNORE" "FCEDIT" "FIGNORE" "FUNCNAME" + "FUNCNEST" "GLOBIGNORE" "GROUPS" "histchars" "HISTCMD" "HISTCONTROL" "HISTFILE" "HISTFILESIZE" + "HISTIGNORE" "HISTSIZE" "HISTTIMEFORMAT" "HOSTFILE" "HOSTNAME" "HOSTTYPE" "IGNOREEOF" "INPUTRC" + "INSIDE_EMACS" "LANG" "LC_ALL" "LC_COLLATE" "LC_CTYPE" "LC_MESSAGES" "LC_NUMERIC" "LC_TIME" + "LINENO" "LINES" "MACHTYPE" "MAILCHECK" "MAPFILE" "OLDPWD" "OPTERR" "OSTYPE" "PIPESTATUS" + "POSIXLY_CORRECT" "PPID" "PROMPT_COMMAND" "PROMPT_DIRTRIM" "PS0" "PS3" "PS4" "PWD" "RANDOM" + "READLINE_ARGUMENT" "READLINE_LINE" "READLINE_MARK" "READLINE_POINT" "REPLY" "SECONDS" "SHELL" + "SHELLOPTS" "SHLVL" "SRANDOM" "TIMEFORMAT" "TMOUT" "TMPDIR" "UID")) + +(case_item + value: (word) @variable.parameter) + +[ + (regex) + (extglob_pattern) +] @string.regexp diff --git a/queries/bash/injections.scm b/queries/bash/injections.scm new file mode 100644 index 0000000..bf50c06 --- /dev/null +++ b/queries/bash/injections.scm @@ -0,0 +1,38 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +(command + name: (command_name (word) @_command) + argument: (raw_string) @injection.content + (#match? @_command "^[gnm]?awk$") + (#set! injection.language "awk")) + +((regex) @injection.content + (#set! injection.language "regex")) + +(command + name: (command_name (word) @_command (#any-of? @_command "jq" "jaq")) + argument: [ + (raw_string) @injection.content + (string (string_content) @injection.content) + ] + (#set! injection.language "jq")) + +(command + name: (command_name (word) @_command (#eq? @_command "alias")) + argument: (concatenation + (word) + [ + (raw_string) @injection.content + (string (string_content) @injection.content) + ]) + (#set! injection.language "bash")) + +(command + name: (command_name (word) @_command (#any-of? @_command "eval" "trap")) + . + argument: [ + (raw_string) @injection.content + (string (string_content) @injection.content) + ] + (#set! injection.language "bash")) diff --git a/queries/c/highlights.scm b/queries/c/highlights.scm new file mode 100644 index 0000000..8e499dd --- /dev/null +++ b/queries/c/highlights.scm @@ -0,0 +1,167 @@ + +(identifier) @variable + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + +"sizeof" @keyword + +[ + "enum" + "struct" + "typedef" + "union" +] @keyword.storage.type + +[ + (type_qualifier) + (storage_class_specifier) +] @keyword.storage.modifier + +[ + "goto" + "break" + "continue" +] @keyword.control + +[ + "do" + "for" + "while" +] @keyword.control.repeat + +[ + "if" + "else" + "switch" + "case" + "default" +] @keyword.control.conditional + +"return" @keyword.control.return + +[ + "defined" + "#define" + "#elif" + "#else" + "#endif" + "#if" + "#ifdef" + "#ifndef" + "#include" + (preproc_directive) +] @keyword.directive + +"..." @punctuation + +["," "." ":" "::" ";" "->"] @punctuation.delimiter + +["(" ")" "[" "]" "{" "}" "[[" "]]"] @punctuation.bracket + +[ + "+" + "-" + "*" + "/" + "++" + "--" + "%" + "==" + "!=" + ">" + "<" + ">=" + "<=" + "&&" + "||" + "!" + "&" + "|" + "^" + "~" + "<<" + ">>" + "=" + "+=" + "-=" + "*=" + "/=" + "%=" + "<<=" + ">>=" + "&=" + "^=" + "|=" + "?" +] @operator + +(conditional_expression ":" @operator) ; After punctuation + +(pointer_declarator "*" @type.builtin) ; After Operators +(abstract_pointer_declarator "*" @type.builtin) + + +[(true) (false)] @constant.builtin.boolean + +(enumerator name: (identifier) @type.enum.variant) + +(string_literal) @string +(system_lib_string) @string + +(null) @constant +(number_literal) @constant.numeric +(char_literal) @constant.character +(escape_sequence) @constant.character.escape + +(field_identifier) @variable.other.member +(statement_identifier) @label +(type_identifier) @type +(primitive_type) @type.builtin +(sized_type_specifier) @type.builtin + +(call_expression + function: (identifier) @function) +(call_expression + function: (field_expression + field: (field_identifier) @function)) +(call_expression (argument_list (identifier) @variable)) +(function_declarator + declarator: [(identifier) (field_identifier)] @function) + +; Up to 6 layers of declarators +(parameter_declaration + declarator: (identifier) @variable.parameter) +(parameter_declaration + (_ + (identifier) @variable.parameter)) +(parameter_declaration + (_ + (_ + (identifier) @variable.parameter))) +(parameter_declaration + (_ + (_ + (_ + (identifier) @variable.parameter)))) +(parameter_declaration + (_ + (_ + (_ + (_ + (identifier) @variable.parameter))))) +(parameter_declaration + (_ + (_ + (_ + (_ + (_ + (identifier) @variable.parameter)))))) + +(preproc_function_def + name: (identifier) @function.special) + +(attribute + name: (identifier) @attribute) + +(comment) @comment diff --git a/queries/c/injections.scm b/queries/c/injections.scm new file mode 100644 index 0000000..321c90a --- /dev/null +++ b/queries/c/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/queries/c/locals.scm b/queries/c/locals.scm new file mode 100644 index 0000000..bc672c5 --- /dev/null +++ b/queries/c/locals.scm @@ -0,0 +1,38 @@ +;; Scopes +(function_definition) @local.scope + +;; Definitions + +; Parameters +; Up to 6 layers of declarators +(parameter_declaration + (identifier) @local.definition.variable.parameter) +(parameter_declaration + (_ + (identifier) @local.definition.variable.parameter)) +(parameter_declaration + (_ + (_ + (identifier) @local.definition.variable.parameter))) +(parameter_declaration + (_ + (_ + (_ + (identifier) @local.definition.variable.parameter)))) +(parameter_declaration + (_ + (_ + (_ + (_ + (identifier) @local.definition.variable.parameter))))) +(parameter_declaration + (_ + (_ + (_ + (_ + (_ + (identifier) @local.definition.variable.parameter)))))) + +;; References + +(identifier) @local.reference diff --git a/queries/css/highlights.scm b/queries/css/highlights.scm new file mode 100644 index 0000000..6cf5e0e --- /dev/null +++ b/queries/css/highlights.scm @@ -0,0 +1,99 @@ +(comment) @comment + +[ + (tag_name) + (nesting_selector) + (universal_selector) +] @tag + +[ + "~" + ">" + "+" + "-" + "*" + "/" + "=" + "^=" + "|=" + "~=" + "$=" + "*=" +] @operator + +[ + "and" + "not" + "only" + "or" +] @keyword.operator + +(attribute_selector (plain_value) @string) + +(property_name) @variable.other.member +(plain_value) @constant + +((property_name) @variable + (#match? @variable "^--")) +((plain_value) @variable + (#match? @variable "^--")) + +(class_name) @label +(feature_name) @variable.other.member +(function_name) @function +(id_name) @label +(namespace_name) @namespace + +(attribute_name) @attribute +(pseudo_element_selector (tag_name) @attribute) +(pseudo_class_selector (class_name) @attribute) + +[ + "@charset" + "@import" + "@keyframes" + "@media" + "@namespace" + "@supports" + (at_keyword) + (from) + (important) + (to) + (keyword_query) + (keyframes_name) + (unit) +] @keyword + +; @apply something; +(at_rule + . (at_keyword) @keyword + . (keyword_query) @constant + (#eq? @keyword "@apply")) + +[ + "#" + "." +] @punctuation + +(string_value) @string +(color_value "#" @string.special) +(color_value) @string.special + +(integer_value) @constant.numeric.integer +(float_value) @constant.numeric.float + +[ + ")" + "(" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "," + ";" + ":" + "::" +] @punctuation.delimiter diff --git a/queries/css/injections.scm b/queries/css/injections.scm new file mode 100644 index 0000000..321c90a --- /dev/null +++ b/queries/css/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/queries/ecma/highlights.scm b/queries/ecma/highlights.scm new file mode 100644 index 0000000..6013821 --- /dev/null +++ b/queries/ecma/highlights.scm @@ -0,0 +1,288 @@ +; Tokens +;------- + +[ + ";" + (optional_chain) ; ?. + "." + "," +] @punctuation.delimiter + +[ + "-" + "--" + "-=" + "+" + "++" + "+=" + "*" + "*=" + "**" + "**=" + "/" + "/=" + "%" + "%=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "===" + "!" + "!=" + "!==" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "~" + "^" + "&" + "|" + "^=" + "&=" + "|=" + "&&" + "||" + "??" + "&&=" + "||=" + "??=" + "..." +] @operator + +(ternary_expression ["?" ":"] @operator) + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(template_substitution + "${" @punctuation.special + "}" @punctuation.special) @embedded + +[ + "async" + "debugger" + "extends" + "from" + "get" + "new" + "set" + "target" + "with" +] @keyword + +[ + "of" + "as" + "in" + "delete" + "typeof" + "instanceof" + "void" +] @keyword.operator + +[ + "function" +] @keyword.function + +[ + "class" + "let" + "var" +] @keyword.storage.type + +[ + "const" + "static" +] @keyword.storage.modifier + +[ + "default" + "yield" + "finally" + "do" + "await" +] @keyword.control + +[ + "if" + "else" + "switch" + "case" +] @keyword.control.conditional + +[ + "while" + "for" +] @keyword.control.repeat + +[ + "import" + "export" +] @keyword.control.import + +[ + "return" + "break" + "continue" +] @keyword.control.return + +[ + "throw" + "try" + "catch" +] @keyword.control.exception + +; Variables +;---------- + +(identifier) @variable + +; Properties +;----------- + +(property_identifier) @variable.other.member +(private_property_identifier) @variable.other.member.private +(shorthand_property_identifier) @variable.other.member +(shorthand_property_identifier_pattern) @variable.other.member + +; Function and method definitions +;-------------------------------- + +(function_expression + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) +(method_definition + name: (private_property_identifier) @function.method.private) + +(pair + key: (property_identifier) @function.method + value: [(function_expression) (arrow_function)]) +(pair + key: (private_property_identifier) @function.method.private + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (member_expression + property: (property_identifier) @function.method) + right: [(function_expression) (arrow_function)]) +(assignment_expression + left: (member_expression + property: (private_property_identifier) @function.method.private) + right: [(function_expression) (arrow_function)]) + +(variable_declarator + name: (identifier) @function + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (identifier) @function + right: [(function_expression) (arrow_function)]) + +; Function and method parameters +;------------------------------- + +; Arrow function parameters in the form `p => ...` are supported by both +; javascript and typescript grammars without conflicts. +(arrow_function + parameter: (identifier) @variable.parameter) + +; Function and method calls +;-------------------------- + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) +(call_expression + function: (member_expression + property: (private_property_identifier) @function.method.private)) + +; Literals +;--------- + +(this) @variable.builtin +(super) @variable.builtin + +[ + (null) + (undefined) +] @constant.builtin + +[ + (true) + (false) +] @constant.builtin.boolean + +(comment) @comment + +[ + (string) + (template_string) +] @string + +(escape_sequence) @constant.character.escape + +(regex) @string.regexp +(number) @constant.numeric.integer + +; Special identifiers +;-------------------- + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +([ + (identifier) + (shorthand_property_identifier) + (shorthand_property_identifier_pattern) + ] @constant + (#match? @constant "^[A-Z_][A-Z\\d_]+$")) + +((identifier) @variable.builtin + (#match? @variable.builtin "^(arguments|module|console|window|document)$") + (#is-not? local)) + +(call_expression + (identifier) @function.builtin + (#any-of? @function.builtin + "eval" + "fetch" + "isFinite" + "isNaN" + "parseFloat" + "parseInt" + "decodeURI" + "decodeURIComponent" + "encodeURI" + "encodeURIComponent" + "require" + "alert" + "prompt" + "btoa" + "atob" + "confirm" + "structuredClone" + "setTimeout" + "clearTimeout" + "setInterval" + "clearInterval" + "queueMicrotask") + (#is-not? local)) diff --git a/queries/ecma/injections.scm b/queries/ecma/injections.scm new file mode 100644 index 0000000..5265c5a --- /dev/null +++ b/queries/ecma/injections.scm @@ -0,0 +1,100 @@ +; Parse the contents of tagged template literals using +; a language inferred from the tag. + +(call_expression + function: [ + (identifier) @injection.language + (member_expression + property: (property_identifier) @injection.language) + ] + arguments: (template_string) @injection.content + (#any-of? @injection.language "html" "css" "json" "sql" "js" "ts" "bash")) + +; Parse the contents of $ template literals as shell commands + +(call_expression + function: [ + (identifier) @_template_function_name + (member_expression + property: (property_identifier) @_template_function_name) + ] + arguments: (template_string) @injection.content + (#eq? @_template_function_name "$") + (#set! injection.language "bash")) + +; GraphQL detection generally matches the rules provided by the 'GraphQL: Syntax Highlighting' +; VSCode extension: https://github.com/graphql/graphiql/blob/8f25b38f4ab14dc99c046109f255fb283bccde52/packages/vscode-graphql-syntax/grammars/graphql.js.json + +; Parse the contents of 'gql' and 'graphql' template literals and function calls +( + (call_expression + function: (identifier) @_template_function_name + arguments: [ + ; Tagged template literal: NAME`` + (template_string (string_fragment) @injection.content) + ( + arguments . [ + ; Function call containing a string literal: NAME('') + (string (string_fragment) @injection.content) + ; Function call containing a template literal: NAME(``) + (template_string (string_fragment) @injection.content) + ] + ) + ] + ) + (#any-of? @_template_function_name "gql" "graphql") + (#set! injection.language "graphql") +) + +; Parse the contents of strings and tagged template literals that begin with a GraphQL comment '#graphql' +( + [ + (string (string_fragment) @injection.content) + (template_string (string_fragment) @injection.content) + ] + (#match? @injection.content "^\\s*#graphql") + (#set! injection.language "graphql") +) + +; Parse the contents of strings and tagged template literals with leading ECMAScript comments '/* GraphQL */' +( + ((comment) @_ecma_comment [ + (string (string_fragment) @injection.content) + (template_string (string_fragment) @injection.content) + ]) + (#eq? @_ecma_comment "/* GraphQL */") + (#set! injection.language "graphql") +) + +; Parse regex syntax within regex literals + +((regex_pattern) @injection.content + (#set! injection.language "regex")) + +; Parse JSDoc annotations in multiline comments + +((comment) @injection.content + (#set! injection.language "jsdoc") + (#match? @injection.content "^/\\*+")) + +; Parse general tags in single line comments + +((comment) @injection.content + (#set! injection.language "comment") + (#match? @injection.content "^//")) + +; Match string literals passed to standard browser API methods that expects a +; css selector as argument. +; - https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector +; - https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll +; - https://developer.mozilla.org/en-US/docs/Web/API/Element/closest +; - https://developer.mozilla.org/en-US/docs/Web/API/Element/matches +; e.g. +; `const el = document.querySelector("div.user-panel.main input[name='login']");` +(call_expression + function: (member_expression + object: (identifier) @_object + property: (property_identifier) @_property (#any-of? @_property "querySelector" "querySelectorAll" "closest" "matches")) + arguments: (arguments + (string (string_fragment) @injection.content)) + (#set! injection.language "css")) diff --git a/queries/ecma/locals.scm b/queries/ecma/locals.scm new file mode 100644 index 0000000..594a5f5 --- /dev/null +++ b/queries/ecma/locals.scm @@ -0,0 +1,26 @@ +; Scopes +;------- + +[ + (statement_block) + (arrow_function) + (function_expression) + (function_declaration) + (method_definition) + (for_statement) + (for_in_statement) + (catch_clause) + (finally_clause) +] @local.scope + +; Definitions +;------------ + +; i => ... +(arrow_function + parameter: (identifier) @local.definition.variable.parameter) + +; References +;------------ + +(identifier) @local.reference diff --git a/queries/go/highlights.scm b/queries/go/highlights.scm new file mode 100644 index 0000000..be9efea --- /dev/null +++ b/queries/go/highlights.scm @@ -0,0 +1,236 @@ + +; Identifiers + +(field_identifier) @variable.other.member + +(identifier) @variable + +(package_identifier) @namespace + +(const_spec + name: (identifier) @constant) + +(type_spec + name: (type_identifier) @constructor) + +(keyed_element . (literal_element (identifier) @variable.other.member)) +(field_declaration + name: (field_identifier) @variable.other.member) + +(parameter_declaration (identifier) @variable.parameter) +(variadic_parameter_declaration (identifier) @variable.parameter) + +(label_name) @label + +(const_spec + name: (identifier) @constant) + +; Function calls + +(call_expression + function: (identifier) @function) + +(call_expression + function: (selector_expression + field: (field_identifier) @function.method)) + +(call_expression + function: (identifier) @function.builtin + (#match? @function.builtin "^(append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover|min|max|clear)$")) + +; Types + +(type_identifier) @type + +(type_parameter_list + (type_parameter_declaration + name: (identifier) @type.parameter)) + +((type_identifier) @type.builtin + (#match? @type.builtin "^(any|bool|byte|comparable|complex128|complex64|error|float32|float64|int|int16|int32|int64|int8|rune|string|uint|uint16|uint32|uint64|uint8|uintptr)$")) + +; Function definitions + +(function_declaration + name: (identifier) @function) + +(method_declaration + name: (field_identifier) @function.method) + +(method_elem + name: (field_identifier) @function.method) + +; Operators + +[ + "--" + "-" + "-=" + ":=" + "!" + "!=" + "..." + "*" + "*" + "*=" + "/" + "/=" + "&" + "&&" + "&=" + "%" + "%=" + "^" + "^=" + "+" + "++" + "+=" + "<-" + "<" + "<<" + "<<=" + "<=" + "=" + "==" + ">" + ">=" + ">>" + ">>=" + "|" + "|=" + "||" + "&^" + "&^=" + "~" +] @operator + +; Keywords + +[ + "default" + "type" +] @keyword + +[ + "defer" + "go" + "goto" +] @keyword.control + +[ + "if" + "else" + "switch" + "select" + "case" +] @keyword.control.conditional + +[ + "for" + "range" +] @keyword.control.repeat + +[ + "import" + "package" +] @keyword.control.import + +[ + "return" + "continue" + "break" + "fallthrough" +] @keyword.control.return + +[ + "func" +] @keyword.function + +[ + "var" + "chan" + "interface" + "map" + "struct" +] @keyword.storage.type + +[ + "const" +] @keyword.storage.modifier + +; Delimiters + +[ + ":" + "." + "," + ";" +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +; Literals + +[ + (interpreted_string_literal) + (raw_string_literal) +] @string + +(rune_literal) @constant.character + +(escape_sequence) @constant.character.escape + +[ + (int_literal) +] @constant.numeric.integer + +[ + (float_literal) + (imaginary_literal) +] @constant.numeric.float + +[ + (true) + (false) +] @constant.builtin.boolean + +[ + (nil) + (iota) +] @constant.builtin + +; Comments + +(comment) @comment + +; Doc Comments +(source_file + . + (comment)+ @comment.block.documentation) + +(source_file + (comment)+ @comment.block.documentation + . + (const_declaration)) + +(source_file + (comment)+ @comment.block.documentation + . + (function_declaration)) + +(source_file + (comment)+ @comment.block.documentation + . + (type_declaration)) + +(source_file + (comment)+ @comment.block.documentation + . + (var_declaration)) diff --git a/queries/go/injections.scm b/queries/go/injections.scm new file mode 100644 index 0000000..c97d62a --- /dev/null +++ b/queries/go/injections.scm @@ -0,0 +1,92 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +; Inject markdown into documentation comments +; +; Go's comments are documentation comments when they are directly followed +; by one of Go's statements (e.g. `type`, `func`, `const`) +; +; This is only a partial implementation, which covers only +; block comments. For line comments (which are more common), +; upstream changes to the grammar are required. +( + (comment) @injection.content . (comment)* . [ + (package_clause) ; `package` + (type_declaration) ; `type` + (function_declaration) ; `func` + (method_declaration) ; `func` + (var_declaration) ; `var` + (const_declaration) ; `const` + ; var ( + ; A = 1 + ; B = 2 + ; ) + (const_spec) + ; const ( + ; A = 1 + ; B = 2 + ; ) + (var_spec) + ] + (#set! injection.language "markdown")) + +((comment) @injection.content + (#match? @injection.content "^//go:generate") + (#set! injection.language "bash")) + +(call_expression + (selector_expression) @_function + (#any-of? @_function "regexp.Match" "regexp.MatchReader" "regexp.MatchString" "regexp.Compile" "regexp.CompilePOSIX" "regexp.MustCompile" "regexp.MustCompilePOSIX") + (argument_list + . + [ + (raw_string_literal) + (interpreted_string_literal) + ] @injection.content + (#set! injection.language "regex"))) + +; https://pkg.go.dev/fmt#Printf +; https://pkg.go.dev/fmt#Sprintf +; https://pkg.go.dev/fmt#Scanf +; https://pkg.go.dev/fmt#Errorf +((call_expression + function: (selector_expression + operand: (identifier) @_module + field: (field_identifier) @_func) + arguments: (argument_list + . (interpreted_string_literal) @injection.content)) + (#eq? @_module "fmt") + (#any-of? @_func "Printf" "Sprintf" "Scanf" "Errorf") + (#set! injection.language "go-format-string")) + +; https://pkg.go.dev/fmt#Fprintf +; https://pkg.go.dev/fmt#Fscanf +; https://pkg.go.dev/fmt#Sscanf +((call_expression + function: (selector_expression + operand: (identifier) @_module + field: (field_identifier) @_func) + arguments: (argument_list + ; [(identifier) (interpreted_string_literal)] + (_) + ; (identifier) + . + (interpreted_string_literal) @injection.content)) + (#eq? @_module "fmt") + (#any-of? @_func "Fprintf" "Fscanf" "Sscanf") + (#set! injection.language "go-format-string")) + +; https://pkg.go.dev/log#Printf +; https://pkg.go.dev/log#Fatalf +; https://pkg.go.dev/log#Panicf +; https://pkg.go.dev/log#Logger.Printf +; https://pkg.go.dev/log#Logger.Fatalf +; https://pkg.go.dev/log#Logger.Panicf +((call_expression + function: (selector_expression + operand: (identifier) + field: (field_identifier) @_func) + arguments: (argument_list + . (interpreted_string_literal) @injection.content)) + (#any-of? @_func "Printf" "Fatalf" "Panicf") + (#set! injection.language "go-format-string")) diff --git a/queries/go/locals.scm b/queries/go/locals.scm new file mode 100644 index 0000000..2ba63be --- /dev/null +++ b/queries/go/locals.scm @@ -0,0 +1,25 @@ +; Scopes + +[ + (function_declaration) + (method_declaration) + (type_declaration) + (block) +] @local.scope + +; Definitions + +(parameter_declaration (identifier) @local.definition.variable.parameter) +(variadic_parameter_declaration (identifier) @local.definition.variable.parameter) + +(const_declaration + (const_spec + name: (identifier) @local.definition.constant)) + +; References + +(identifier) @local.reference + +; Field names in struct literals are identifier rather than field_identifier, +; these cannot be locals. +(keyed_element . (literal_element (identifier) @variable.other.member)) diff --git a/queries/html/highlights.scm b/queries/html/highlights.scm new file mode 100644 index 0000000..9227bfc --- /dev/null +++ b/queries/html/highlights.scm @@ -0,0 +1,47 @@ +(tag_name) @tag +(erroneous_end_tag_name) @error +(doctype) @constant +(attribute_name) @attribute +(entity) @string.special.symbol +(comment) @comment + +((attribute + (attribute_name) @attribute + (quoted_attribute_value (attribute_value) @markup.link.url)) + (#any-of? @attribute "href" "src")) + +((element + (start_tag + (tag_name) @tag) + (text) @markup.link.label) + (#eq? @tag "a")) + +(attribute [(attribute_value) (quoted_attribute_value)] @string) + +((element + (start_tag + (tag_name) @tag) + (text) @markup.bold) + (#any-of? @tag "strong" "b")) + +((element + (start_tag + (tag_name) @tag) + (text) @markup.italic) + (#any-of? @tag "em" "i")) + +((element + (start_tag + (tag_name) @tag) + (text) @markup.strikethrough) + (#any-of? @tag "s" "del")) + +[ + "<" + ">" + "" + "" + "+=" + "<" + "<<" + "<<=" + "<=" + "<>" + "=" + ":=" + "==" + ">" + ">=" + ">>" + ">>=" + "|" + "|=" + "~" + "@=" +] @operator + +; ------- +; Variables +; ------- + +(identifier) @variable + +; - Member +(attribute attribute: (identifier) @variable.other.member) + +; - Parameter +(parameters (identifier) @variable.parameter) +(parameters (typed_parameter (identifier) @variable.parameter)) +(parameters (default_parameter name: (identifier) @variable.parameter)) +(parameters (typed_default_parameter name: (identifier) @variable.parameter)) +(parameters + (list_splat_pattern ; *args + (identifier) @variable.parameter)) +(parameters + (dictionary_splat_pattern ; **kwargs + (identifier) @variable.parameter)) + +(lambda_parameters + (identifier) @variable.parameter) + +(keyword_argument + name: (identifier) @variable.parameter) + +; - Builtin +((identifier) @variable.builtin + (#any-of? @variable.builtin "self" "cls")) + +; ------- +; Keywords +; ------- + +[ + "async" + "class" + "exec" + "global" + "nonlocal" + "print" + "type" +] @keyword + +; Operators +[ + "and" + "or" + "not in" + "in" ; Has to be before loop keywords because "in" is overloaded + "not" + "del" + "is not" + "is" +] @keyword.operator + +; Control +[ + "as" + "assert" + "await" + "from" + "pass" + + "with" +] @keyword.control + +; Conditionals +[ + "if" + "elif" + "else" + "match" + "case" +] @keyword.control.conditional + +; Exceptions +[ + "raise" + "try" + "except" + "finally" +] @keyword.control.exception +(raise_statement "from" @keyword.control.exception) + +; Functions +[ + "def" + "lambda" +] @keyword.function + +; Import +"import" @keyword.control.import + +; Loops +[ + "while" + "for" + "break" + "continue" +] @keyword.control.repeat + +(for_statement "in" @keyword.control.repeat) +(for_in_clause "in" @keyword.control.repeat) + +; Return +[ + "return" + "yield" +] @keyword.control.return +(yield "from" @keyword.control.return) + +; ------- +; Imports +; ------- + +(dotted_name + (identifier)* @namespace) + +(aliased_import + alias: (identifier) @namespace) + +; - Builtins +(none) @constant.builtin ; Has to be before types + +; ------- +; Types +; ------- + +((identifier) @type + (#match? @type "^[A-Z]")) ; Has to be before constructor due to this being a more general match + +; In type hints make everything types to catch non-conforming identifiers +; (e.g., datetime.datetime) and None +(type [(identifier) (none)] @type) +; Handle [] . and | nesting 4 levels deep +(type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type))))) + +; Classes +(class_definition name: (identifier) @type) +(class_definition superclasses: (argument_list (identifier) @type)) + +; ------- +; Functions +; ------- + +(function_definition + name: (identifier) @function) + +(call + function: (identifier) @function) + +; Decorators +(decorator) @function +(decorator (identifier) @function) +(decorator (attribute attribute: (identifier) @function)) +(decorator (call + function: (attribute attribute: (identifier) @function))) + +; Methods +(call + function: (attribute attribute: (identifier) @function.method)) + +; Builtin functions +((call + function: (identifier) @function.builtin) + (#any-of? + @function.builtin + "abs" "all" "any" "ascii" "bin" "breakpoint" "bytearray" "callable" "chr" + "classmethod" "compile" "complex" "delattr" "dir" "divmod" "enumerate" + "eval" "exec" "filter" "format" "getattr" "globals" "hasattr" "hash" "help" + "hex" "id" "input" "isinstance" "issubclass" "iter" "len" "locals" "map" + "max" "memoryview" "min" "next" "object" "oct" "open" "ord" "pow" "print" + "property" "range" "repr" "reversed" "round" "setattr" "slice" "sorted" + "staticmethod" "sum" "super" "type" "vars" "zip" "__import__")) + +; Constructors +(call + function: (attribute attribute: (identifier) @constructor) + (#any-of? + @constructor + "__new__" "__init__")) + +((call + function: (identifier) @constructor) + (#any-of? + @constructor + "__new__" "__init__")) + +(function_definition + name: (identifier) @constructor + (#any-of? @constructor "__new__" "__init__")) + +(call + function: (attribute attribute: (identifier) @constructor) + (#match? @constructor "^[A-Z]")) +(call + function: (identifier) @constructor + (#match? @constructor "^[A-Z]")) + +; Builtin types +((identifier) @type.builtin ; Has to be after functions due to broad matching + (#any-of? + @type.builtin + "bool" "bytes" "dict" "float" "frozenset" "int" "list" "set" "str" "tuple")) + +; Builtin error types +((identifier) @type.builtin ; Has to be after constructors due to broad matching of constructor + (#any-of? @type.builtin + "BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" + "AssertionError" "AttributeError" "EOFError" "FloatingPointError" "GeneratorExit" + "ImportError" "ModuleNotFoundError" "IndexError" "KeyError" "KeyboardInterrupt" + "MemoryError" "NameError" "NotImplementedError" "OSError" "OverflowError" + "RecursionError" "ReferenceError" "RuntimeError" "StopIteration" "StopAsyncIteration" + "SyntaxError" "IndentationError" "TabError" "SystemError" "SystemExit" "TypeError" + "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" "UnicodeDecodeError" + "UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" + "IOError" "WindowsError" "BlockingIOError" "ChildProcessError" "ConnectionError" + "BrokenPipeError" "ConnectionAbortedError" "ConnectionRefusedError" + "ConnectionResetError" "FileExistsError" "FileNotFoundError" "InterruptedError" + "IsADirectoryError" "NotADirectoryError" "PermissionError" "ProcessLookupError" + "TimeoutError" "Warning" "UserWarning" "DeprecationWarning" "PendingDeprecationWarning" + "SyntaxWarning" "RuntimeWarning" "FutureWarning" "ImportWarning" "UnicodeWarning" + "BytesWarning" "ResourceWarning")) + +; ------- +; Constants +; ------- + +((identifier) @constant + (#match? @constant "^_*[A-Z][A-Z\\d_]*$")) + +(escape_sequence) @constant.character.escape + +[ + (true) + (false) +] @constant.builtin.boolean + + +; - Numbers +(integer) @constant.numeric.integer +(float) @constant.numeric.float + +; ------- +; Other literals +; ------- + +(comment) @comment +(string) @string diff --git a/queries/python/injections.scm b/queries/python/injections.scm new file mode 100644 index 0000000..19a22c3 --- /dev/null +++ b/queries/python/injections.scm @@ -0,0 +1,14 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +; Match all 9 functions in the `re` module from the standard library that +; that takes a regex pattern as first argument. +; https://docs.python.org/3/library/re.html#functions +(call + function: (attribute + object: (identifier) @_module (#eq? @_module "re") + attribute: (identifier) @_function (#any-of? @_function "compile" "search" "match" "fullmatch" "sub" "subn" "findall" "finditer" "split")) + arguments: (argument_list + . (string + (string_content) @injection.content)) + (#set! injection.language "regex")) diff --git a/queries/python/locals.scm b/queries/python/locals.scm new file mode 100644 index 0000000..955ebc5 --- /dev/null +++ b/queries/python/locals.scm @@ -0,0 +1,50 @@ +;; Scopes + +[ + (module) + (function_definition) + (lambda) +] @local.scope + +;; Definitions + +; Parameters +(parameters + (identifier) @local.definition.variable.parameter) +(parameters + (typed_parameter + (identifier) @local.definition.variable.parameter)) +(parameters + (default_parameter + name: (identifier) @local.definition.variable.parameter)) +(parameters + (typed_default_parameter + name: (identifier) @local.definition.variable.parameter)) +(parameters + (list_splat_pattern ; *args + (identifier) @local.definition.variable.parameter)) +(parameters + (dictionary_splat_pattern ; **kwargs + (identifier) @local.definition.variable.parameter)) +(parameters + (identifier) @local.definition.variable.builtin + (#any-of? @local.definition.variable.builtin "self" "cls")) ; label self/cls as builtin + +(lambda_parameters + (identifier) @local.definition.variable.parameter) + +; Imports +(import_statement + name: (dotted_name + (identifier) @local.definition.namespace)) + +(aliased_import + alias: (identifier) @local.definition.namespace) + +;; References + +(identifier) @local.reference + +; don't make the name of kwargs locals +(keyword_argument + name: (identifier) @variable.parameter) diff --git a/queries/rust/highlights.scm b/queries/rust/highlights.scm new file mode 100644 index 0000000..cc8380c --- /dev/null +++ b/queries/rust/highlights.scm @@ -0,0 +1,514 @@ +; ------- +; Basic identifiers +; ------- + +; We do not style ? as an operator on purpose as it allows styling ? differently, as many highlighters do. @operator.special might have been a better scope, but @special is already documented so the change would break themes (including the intent of the default theme) +"?" @special + +(type_identifier) @type +(identifier) @variable +(field_identifier) @variable.other.member + +; ------- +; Operators +; ------- + +[ + "*" + "'" + "->" + "=>" + "<=" + "=" + "==" + "!" + "!=" + "%" + "%=" + "&" + "&=" + "&&" + "|" + "|=" + "||" + "^" + "^=" + "*" + "*=" + "-" + "-=" + "+" + "+=" + "/" + "/=" + ">" + "<" + ">=" + ">>" + "<<" + ">>=" + "<<=" + "@" + ".." + "..=" + "'" +] @operator + +; ------- +; Paths +; ------- + +(use_declaration + argument: (identifier) @namespace) +(use_wildcard + (identifier) @namespace) +(extern_crate_declaration + name: (identifier) @namespace + alias: (identifier)? @namespace) +(mod_item + name: (identifier) @namespace) +(scoped_use_list + path: (identifier)? @namespace) +(use_list + (identifier) @namespace) +(use_as_clause + path: (identifier)? @namespace + alias: (identifier) @namespace) + +; ------- +; Types +; ------- + +(type_parameter + name: (type_identifier) @type.parameter) +((type_arguments (type_identifier) @constant) + (#match? @constant "^[A-Z_]+$")) +(type_arguments (type_identifier) @type) +; `_` in `(_, _)` +(tuple_struct_pattern "_" @comment.unused) +; `_` in `Vec<_>` +((type_arguments (type_identifier) @comment.unused) + (#eq? @comment.unused "_")) +; `_` in `Rc<[_]>` +((array_type (type_identifier) @comment.unused) + (#eq? @comment.unused "_")) + +; --- +; Primitives +; --- + +(escape_sequence) @constant.character.escape +(primitive_type) @type.builtin +(boolean_literal) @constant.builtin.boolean +(integer_literal) @constant.numeric.integer +(float_literal) @constant.numeric.float +(char_literal) @constant.character +[ + (string_literal) + (raw_string_literal) +] @string + +; ------- +; Comments +; ------- + +(shebang) @comment +(line_comment) @comment.line +(block_comment) @comment.block + +; Doc Comments +(line_comment + (outer_doc_comment_marker "/" @comment.line.documentation) + (doc_comment)) @comment.line.documentation +(line_comment + (inner_doc_comment_marker "!" @comment.line.documentation) + (doc_comment)) @comment.line.documentation + +(block_comment + (outer_doc_comment_marker) @comment.block.documentation + (doc_comment) "*/" @comment.block.documentation) @comment.block.documentation +(block_comment + (inner_doc_comment_marker) @comment.block.documentation + (doc_comment) "*/" @comment.block.documentation) @comment.block.documentation + +; --- +; Extraneous +; --- + +(self) @variable.builtin + +(field_initializer + (field_identifier) @variable.other.member) +(shorthand_field_initializer + (identifier) @variable.other.member) +(shorthand_field_identifier) @variable.other.member + +(lifetime + "'" @label + (identifier) @label) +(label + "'" @label + (identifier) @label) + +; --- +; Punctuation +; --- + +[ + "::" + "." + ";" + "," + ":" +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" + "{" + "}" + "#" +] @punctuation.bracket +(type_arguments + [ + "<" + ">" + ] @punctuation.bracket) +(type_parameters + [ + "<" + ">" + ] @punctuation.bracket) +(for_lifetimes ["<" ">"] @punctuation.bracket) +(closure_parameters + "|" @punctuation.bracket) +(bracketed_type ["<" ">"] @punctuation.bracket) + +; --- +; Variables +; --- + +(let_declaration + pattern: [ + ((identifier) @variable) + ((tuple_pattern + (identifier) @variable)) + ]) + +; It needs to be anonymous to not conflict with `call_expression` further below. +(_ + value: (field_expression + value: (identifier)? @variable + field: (field_identifier) @variable.other.member)) + +(parameter + pattern: (identifier) @variable.parameter) +(closure_parameters + (identifier) @variable.parameter) + +; ------- +; Keywords +; ------- + +"in" @keyword.control + +[ + "match" + "if" + "else" + "try" +] @keyword.control.conditional + +[ + "while" + "loop" +] @keyword.control.repeat + +[ + "break" + "continue" + "return" + "await" + "yield" +] @keyword.control.return + +"use" @keyword.control.import +(mod_item "mod" @keyword.control.import !body) +(use_as_clause "as" @keyword.control.import) + +(type_cast_expression "as" @keyword.operator) + +[ + (crate) + (super) + "as" + "pub" + "mod" + "extern" + + "impl" + "where" + "trait" + "for" + + "default" + "async" +] @keyword + +(for_expression + "for" @keyword.control.repeat) +(gen_block "gen" @keyword.control) + +[ + "struct" + "enum" + "union" + "type" +] @keyword.storage.type + +"let" @keyword.storage +"fn" @keyword.function +"unsafe" @keyword.special +"macro_rules!" @function.macro + +(mutable_specifier) @keyword.storage.modifier.mut + +(reference_type "&" @keyword.storage.modifier.ref) +(self_parameter "&" @keyword.storage.modifier.ref) + +[ + "static" + "const" + "raw" + "ref" + "move" + "dyn" +] @keyword.storage.modifier + +; TODO: variable.mut to highlight mutable identifiers via locals.scm + +; --- +; Remaining Paths +; --- + +(scoped_identifier + path: (identifier)? @namespace + name: (identifier) @namespace) +(scoped_type_identifier + path: (identifier) @namespace) + +; ------- +; Functions +; ------- + +; highlight `baz` in `any_function(foo::bar::baz)` as function +; This generically works for an unlimited number of path segments: +; +; - `f(foo::bar)` +; - `f(foo::bar::baz)` +; - `f(foo::bar::baz::quux)` +; +; We know that in the above examples, the last component of each path is a function +; as the only other valid thing (following Rust naming conventions) would be a module at +; that position, however you cannot pass modules as arguments +(call_expression + function: _ + arguments: (arguments + (scoped_identifier + path: _ + name: (identifier) @function))) + +(call_expression + function: [ + ((identifier) @function) + (scoped_identifier + name: (identifier) @function) + (field_expression + field: (field_identifier) @function) + ]) +(generic_function + function: [ + ((identifier) @function) + (scoped_identifier + name: (identifier) @function) + (field_expression + field: (field_identifier) @function.method) + ]) + +(function_item + name: (identifier) @function) + +(function_signature_item + name: (identifier) @function) + +; ------- +; Guess Other Types +; ------- +; Other PascalCase identifiers are assumed to be structs. + +((identifier) @type + (#match? @type "^[A-Z]")) + +(never_type "!" @type) + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + +; --- +; PascalCase identifiers in call_expressions (e.g. `Ok()`) +; are assumed to be enum constructors. +; --- + +(call_expression + function: [ + ((identifier) @constructor + (#match? @constructor "^[A-Z]")) + (scoped_identifier + name: ((identifier) @constructor + (#match? @constructor "^[A-Z]"))) + ]) + +; --- +; PascalCase identifiers under a path which is also PascalCase +; are assumed to be constructors if they have methods or fields. +; --- + +(field_expression + value: (scoped_identifier + path: [ + (identifier) @type + (scoped_identifier + name: (identifier) @type) + ] + name: (identifier) @constructor + (#match? @type "^[A-Z]") + (#match? @constructor "^[A-Z]"))) + +(enum_variant (identifier) @type.enum.variant) + + +; ------- +; Constructors +; ------- +; TODO: this is largely guesswork, remove it once we get actual info from locals.scm or r-a + +(struct_expression + name: (type_identifier) @constructor) + +(tuple_struct_pattern + type: [ + (identifier) @constructor + (scoped_identifier + name: (identifier) @constructor) + ]) +(struct_pattern + type: [ + ((type_identifier) @constructor) + (scoped_type_identifier + name: (type_identifier) @constructor) + ]) +(match_pattern + ((identifier) @constructor) (#match? @constructor "^[A-Z]")) +(or_pattern + ((identifier) @constructor) + ((identifier) @constructor) + (#match? @constructor "^[A-Z]")) + +; --- +; Macros +; --- + +(attribute + (identifier) @function.macro) +(inner_attribute_item "!" @punctuation) +(attribute + [ + (identifier) @function.macro + (scoped_identifier + name: (identifier) @function.macro) + ] + (token_tree (identifier) @function.macro)?) + +(inner_attribute_item) @attribute + +(macro_definition + name: (identifier) @function.macro) +(macro_invocation + macro: [ + ((identifier) @function.macro) + (scoped_identifier + name: (identifier) @function.macro) + ] + "!" @function.macro) + +(metavariable) @variable.parameter +(fragment_specifier) @type + +(attribute + (identifier) @special + arguments: (token_tree (identifier) @type) + (#eq? @special "derive") +) + +(token_repetition_pattern) @punctuation.delimiter +(token_repetition_pattern [")" "(" "$"] @punctuation.special) +(token_repetition_pattern "?" @operator) + +; --- +; Prelude +; --- + +((identifier) @type.enum.variant.builtin + (#any-of? @type.enum.variant.builtin "Some" "None" "Ok" "Err")) + + +(call_expression + (identifier) @function.builtin + (#any-of? @function.builtin + "drop" + "size_of" + "size_of_val" + "align_of" + "align_of_val")) + +((type_identifier) @type.builtin + (#any-of? + @type.builtin + "Send" + "Sized" + "Sync" + "Unpin" + "Drop" + "Fn" + "FnMut" + "FnOnce" + "AsMut" + "AsRef" + "From" + "Into" + "DoubleEndedIterator" + "ExactSizeIterator" + "Extend" + "IntoIterator" + "Iterator" + "Option" + "Result" + "Clone" + "Copy" + "Debug" + "Default" + "Eq" + "Hash" + "Ord" + "PartialEq" + "PartialOrd" + "ToOwned" + "Box" + "String" + "ToString" + "Vec" + "FromIterator" + "TryFrom" + "TryInto")) diff --git a/queries/rust/injections.scm b/queries/rust/injections.scm new file mode 100644 index 0000000..51e9ed9 --- /dev/null +++ b/queries/rust/injections.scm @@ -0,0 +1,217 @@ +([(line_comment !doc) (block_comment !doc)] @injection.content + (#set! injection.language "comment")) + +((doc_comment) @injection.content + (#set! injection.language "markdown-rustdoc") + (#set! injection.combined)) + +((macro_invocation + (token_tree) @injection.content) + (#set! injection.language "rust") + (#set! injection.include-children)) + +((macro_rule + (token_tree) @injection.content) + (#set! injection.language "rust") + (#set! injection.include-children)) + +((macro_invocation + macro: + [ + (scoped_identifier + name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree) @injection.content) + (#eq? @_macro_name "html") + (#set! injection.language "html") + (#set! injection.include-children)) + +((macro_invocation + macro: + [ + (scoped_identifier + name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree) @injection.content) + (#eq? @_macro_name "slint") + (#set! injection.language "slint") + (#set! injection.include-children)) + +((macro_invocation + macro: + [ + (scoped_identifier name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree + (token_tree . "{" "}" .) @injection.content)) + (#eq? @_macro_name "json") + (#set! injection.language "json") + (#set! injection.include-children)) + +(call_expression + function: (scoped_identifier + path: (identifier) @_regex (#any-of? @_regex "Regex" "RegexBuilder") + name: (identifier) @_new (#eq? @_new "new")) + arguments: + (arguments + [ + (string_literal (string_content) @injection.content) + (raw_string_literal (string_content) @injection.content) + ]) + (#set! injection.language "regex")) + +(call_expression + function: (scoped_identifier + path: (scoped_identifier (identifier) @_regex (#any-of? @_regex "Regex" "RegexBuilder") .) + name: (identifier) @_new (#eq? @_new "new")) + arguments: + (arguments + [ + (string_literal (string_content) @injection.content) + (raw_string_literal (string_content) @injection.content) + ]) + (#set! injection.language "regex")) + +; Highlight SQL in `sqlx::query!()`, `sqlx::query_scalar!()`, and `sqlx::query_scalar_unchecked!()` +(macro_invocation + macro: (scoped_identifier + path: (identifier) @_sqlx (#eq? @_sqlx "sqlx") + name: (identifier) @_query (#match? @_query "^query(_scalar|_scalar_unchecked)?$")) + (token_tree + ; Only the first argument is SQL + . + [ + (string_literal (string_content) @injection.content) + (raw_string_literal (string_content) @injection.content) + ] + ) + (#set! injection.language "sql")) + +; Highlight SQL in `sqlx::query_as!()` and `sqlx::query_as_unchecked!()` +(macro_invocation + macro: (scoped_identifier + path: (identifier) @_sqlx (#eq? @_sqlx "sqlx") + name: (identifier) @_query_as (#match? @_query_as "^query_as(_unchecked)?$")) + (token_tree + ; Only the second argument is SQL + . + ; Allow anything as the first argument in case the user has lower case type + ; names for some reason + (_) + [ + (string_literal (string_content) @injection.content) + (raw_string_literal (string_content) @injection.content) + ] + ) + (#set! injection.language "sql")) + +; Highlight SQL in `sqlx::query*` and `sqlx::raw_sql` functions +(call_expression + function: (scoped_identifier + path: (identifier) @_sqlx + (#eq? @_sqlx "sqlx") + name: (identifier) @_query_function) + (#match? @_query_function "^query.*|raw_sql$") + arguments: (arguments + . + [ + (string_literal + (string_content) @injection.content) + (raw_string_literal + (string_content) @injection.content) + ]) + (#set! injection.language "sql")) + +; Special language `tree-sitter-rust-format-args` for Rust macros, +; which use `format_args!` under the hood and therefore have +; the `format_args!` syntax. +; +; This language is injected into a hard-coded set of macros. +( + (macro_invocation + macro: + [ + (scoped_identifier + name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree) @injection.content + ) + (#any-of? @_macro_name + ; 1st argument is `format_args!` + + ; std + "print" "println" "eprint" "eprintln" + "format" "format_args" "todo" "panic" + "unreachable" "unimplemented" "compile_error" + ; log + "crit" "trace" "debug" "info" "warn" "error" + ; anyhow + "anyhow" "bail" + ; syn + "format_ident" + ; indoc + "formatdoc" "printdoc" "eprintdoc" "writedoc" + ; iced + "text" + ; ratatui + "span" + ; eyre + "eyre" + ; miette + "miette" + + ; 2nd argument is `format_args!` + + ; std + "write" "writeln" "assert" "debug_assert" + ; defmt + "expect" "unwrap" + ; ratatui + "span" + + ; 3rd argument is `format_args!` + + ; std + "assert_eq" "debug_assert_eq" "assert_ne" "debug_assert_ne" + + ; Dioxus's rsx! macro accepts string interpolation in all + ; strings, across the entire token tree + "rsx" + ) + (#set! injection.language "rust-format-args-macro") + (#set! injection.include-children) +) + +; for some queries (e.g. when you have generic table names) you need to wrap it in `AssertSqlSafe` +; after `format!` so it can overwrite `format!` formatting correctly. +(call_expression + function: [ + (scoped_identifier + path: (identifier) @_sqlx + (#eq? @_sqlx "sqlx") + name: (identifier) @_AssertSqlSafe) + (identifier) @_AssertSqlSafe + ] + (#eq? @_AssertSqlSafe "AssertSqlSafe") + arguments: (arguments + [ + (string_literal + (string_content) @injection.content) + (raw_string_literal + (string_content) @injection.content) + (macro_invocation + macro: (identifier) @_format + (#eq? @_format "format") + (token_tree + [ + (string_literal + (string_content) @injection.content) + (raw_string_literal + (string_content) @injection.content) + ])) + ]) + (#set! injection.language "sql")) diff --git a/queries/rust/locals.scm b/queries/rust/locals.scm new file mode 100644 index 0000000..b8b918d --- /dev/null +++ b/queries/rust/locals.scm @@ -0,0 +1,28 @@ +; Scopes + +[ + (function_item) + (struct_item) + (enum_item) + (union_item) + (type_item) + (trait_item) + (impl_item) + (closure_expression) + (block) +] @local.scope + +; Definitions + +(function_item + (parameters + (parameter + pattern: (identifier) @local.definition.variable.parameter))) + +(closure_parameters (identifier) @local.definition.variable.parameter) + +; References +(identifier) @local.reference +; lifetimes / labels +(lifetime (identifier) @label) +(label (identifier) @label) diff --git a/queries/toml/highlights.scm b/queries/toml/highlights.scm new file mode 100644 index 0000000..e0a3d6a --- /dev/null +++ b/queries/toml/highlights.scm @@ -0,0 +1,48 @@ +; Properties +;----------- + +(table [ + (bare_key) + (dotted_key) + (quoted_key) +] @type) + +(table_array_element [ + (bare_key) + (dotted_key) + (quoted_key) +] @type) + +(pair [ + (bare_key) + (dotted_key) + (quoted_key) +] @variable.other.member) + +; Literals +;--------- + +(boolean) @constant.builtin.boolean +(comment) @comment +(string) @string +(integer) @constant.numeric.integer +(float) @constant.numeric.float +(offset_date_time) @string.special +(local_date_time) @string.special +(local_date) @string.special +(local_time) @string.special + +; Punctuation +;------------ + +"." @punctuation.delimiter +"," @punctuation.delimiter + +"=" @operator + +"[" @punctuation.bracket +"]" @punctuation.bracket +"[[" @punctuation.bracket +"]]" @punctuation.bracket +"{" @punctuation.bracket +"}" @punctuation.bracket diff --git a/queries/toml/injections.scm b/queries/toml/injections.scm new file mode 100644 index 0000000..321c90a --- /dev/null +++ b/queries/toml/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/queries/typescript/highlights.scm b/queries/typescript/highlights.scm new file mode 100644 index 0000000..dbe6665 --- /dev/null +++ b/queries/typescript/highlights.scm @@ -0,0 +1,3 @@ +; See runtime/queries/ecma/README.md for more info. + +; inherits: ecma,_typescript diff --git a/queries/typescript/injections.scm b/queries/typescript/injections.scm new file mode 100644 index 0000000..5b8c8f2 --- /dev/null +++ b/queries/typescript/injections.scm @@ -0,0 +1,3 @@ +; See runtime/queries/ecma/README.md for more info. + +; inherits: _typescript,ecma diff --git a/queries/typescript/locals.scm b/queries/typescript/locals.scm new file mode 100644 index 0000000..5b8c8f2 --- /dev/null +++ b/queries/typescript/locals.scm @@ -0,0 +1,3 @@ +; See runtime/queries/ecma/README.md for more info. + +; inherits: _typescript,ecma diff --git a/queries/yaml/highlights.scm b/queries/yaml/highlights.scm new file mode 100644 index 0000000..3c39cf1 --- /dev/null +++ b/queries/yaml/highlights.scm @@ -0,0 +1,42 @@ +(boolean_scalar) @constant.builtin.boolean +(null_scalar) @constant.builtin +(double_quote_scalar) @string +(single_quote_scalar) @string +(block_scalar) @string +(string_scalar) @string +(escape_sequence) @constant.character.escape +(integer_scalar) @constant.numeric.integer +(float_scalar) @constant.numeric.float +(comment) @comment +(anchor_name) @type +(alias_name) @type +(tag) @type +(yaml_directive) @keyword + +(block_mapping_pair + key: (flow_node [(double_quote_scalar) (single_quote_scalar)] @variable.other.member)) +(block_mapping_pair + key: (flow_node (plain_scalar (string_scalar) @variable.other.member))) + +(flow_mapping + (_ key: (flow_node [(double_quote_scalar) (single_quote_scalar)] @variable.other.member))) +(flow_mapping + (_ key: (flow_node (plain_scalar (string_scalar) @variable.other.member)))) + +[ +"," +"-" +":" +">" +"?" +"|" +] @punctuation.delimiter + +[ +"[" +"]" +"{" +"}" +] @punctuation.bracket + +["*" "&" "---" "..."] @punctuation.special diff --git a/queries/yaml/injections.scm b/queries/yaml/injections.scm new file mode 100644 index 0000000..17e41ea --- /dev/null +++ b/queries/yaml/injections.scm @@ -0,0 +1,57 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +; The following code in this file until the ";;; END nvim-treesitter LICENSED CODE" +; marker incorporates work covered by the following copyright and permission notice: +; +; Copyright 2023 the nvim-treesitter authors +; +; 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. + +; Modified for Helix from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/yaml/injections.scm + +;; GitHub actions: run +;; Buildkite: command, commands +(block_mapping_pair + key: (flow_node) @_run (#any-of? @_run "run" "command" "commands") + value: (flow_node + (plain_scalar + (string_scalar) @injection.content) + (#set! injection.language "bash"))) + +(block_mapping_pair + key: (flow_node) @_run (#any-of? @_run "run" "command" "commands") + value: (block_node + (block_scalar) @injection.content + (#set! injection.language "bash"))) + +(block_mapping_pair + key: (flow_node) @_run (#any-of? @_run "run" "command" "commands") + value: (block_node + (block_sequence + (block_sequence_item + (flow_node + (plain_scalar + (string_scalar) @injection.content)) + (#set! injection.language "bash"))))) + +(block_mapping_pair + key: (flow_node) @_run (#any-of? @_run "run" "command" "commands") + value: (block_node + (block_sequence + (block_sequence_item + (block_node + (block_scalar) @injection.content + (#set! injection.language "bash")))))) + +;;; END nvim-treesitter LICENSED CODE