Unnamed repository; edit this file 'description' to name the repository.
Add spade support (#11448)
Co-authored-by: Michael Davis <[email protected]>
Frans Skarman 2024-11-21
parent 2f6a113 · commit 310bc04
-rw-r--r--book/src/generated/lang-support.md1
-rw-r--r--languages.toml26
-rw-r--r--pr.md24
-rw-r--r--runtime/queries/spade/highlights.scm130
-rw-r--r--runtime/queries/spade/indents.scm27
5 files changed, 208 insertions, 0 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index 2a01ec37..18570695 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -189,6 +189,7 @@
| sml | ✓ | | | |
| snakemake | ✓ | | ✓ | `pylsp` |
| solidity | ✓ | ✓ | | `solc` |
+| spade | ✓ | | ✓ | `spade-language-server` |
| spicedb | ✓ | | | |
| sql | ✓ | ✓ | | |
| sshclientconfig | ✓ | | | |
diff --git a/languages.toml b/languages.toml
index c92b7893..3c96d49f 100644
--- a/languages.toml
+++ b/languages.toml
@@ -94,6 +94,7 @@ slint-lsp = { command = "slint-lsp", args = [] }
solargraph = { command = "solargraph", args = ["stdio"] }
solc = { command = "solc", args = ["--lsp"] }
sourcekit-lsp = { command = "sourcekit-lsp" }
+spade-language-server = {command = "spade-language-server"}
svlangserver = { command = "svlangserver", args = [] }
swipl = { command = "swipl", args = [ "-g", "use_module(library(lsp_server))", "-g", "lsp_server:main", "-t", "halt", "--", "stdio" ] }
superhtml = { command = "superhtml", args = ["lsp"]}
@@ -3876,3 +3877,28 @@ indent = { tab-width = 4, unit = " " }
[[grammar]]
name = "cylc"
source = { git = "https://github.com/elliotfontaine/tree-sitter-cylc", rev = "30dd40d9bf23912e4aefa93eeb4c7090bda3d0f6" }
+
+[[language]]
+name = "spade"
+scope = "source.spade"
+roots = ["swim.toml"]
+file-types = ['spade']
+injection-regex = "spade"
+comment-tokens = ["//", "///"]
+block-comment-tokens = [
+ { start = "/*", end = "*/" },
+ { start = "/**", end = "*/" },
+]
+language-servers = [ "spade-language-server" ]
+indent = { tab-width = 4, unit = " " }
+
+[language.auto-pairs]
+'(' = ')'
+'{' = '}'
+'[' = ']'
+'"' = '"'
+'<' = '>'
+
+[[grammar]]
+name = "spade"
+source = { git = "https://gitlab.com/spade-lang/tree-sitter-spade/", rev = "4d5b141017c61fe7e168e0a5c5721ee62b0d9572" }
diff --git a/pr.md b/pr.md
new file mode 100644
index 00000000..0ea65a5a
--- /dev/null
+++ b/pr.md
@@ -0,0 +1,24 @@
+Syntax symbol pickers
+==
+
+This adds two new symbol picker commands that use tree-sitter rather than LSP. We run a new `symbols.scm` query across the file and extract tagged things like function definitions, types, classes, etc. For languages with unambiguous syntax this behaves roughly the same as the LSP symbol picker (`<space>s`). It's less precise though since we don't have semantic info about the language. For example it can easily produce false positives for C/C++ because of preprocessor magic.
+
+The hope is to start introducing LSP-like features for navigation that can work without installing or running a language server. I made these two pickers in particular because I don't like LSP equivalents in ErlangLS - the document symbol picker can take a long time to show up during boot and the workspace symbol picker only searches for module names. The other motivation is to have some navigation features in cases when running a language server is too cumbersome - either to set up or because of resource constraints. For example `clangd` needs a fair amount of setup (`compile_commands.json`) that you might not want to do when quickly reading through a codebase.
+
+GitHub already uses tree-sitter like this to provide [imprecise code navigation](https://docs.github.com/en/repositories/working-with-files/using-files/navigating-code-on-github#about-navigating-code-on-github). It should be possible to find definitions and references as well like `gd` and `gr` - this is left as a follow-up.
+
+This PR also adds commands that either open the LSP symbol picker or the syntax one if a language server is not available. This way you can customize a language to not use the LSP symbol pickers, for example:
+
+```toml
+[[language]]
+name = "erlang"
+language-servers = [{ name = "erlang-ls", except-features = ["document-symbols", "workspace-symbols"] }]
+```
+
+and `<space>s` will use the syntax symbol picker, while `<space>s` on a Rust file will still prefer the language server.
+
+---
+
+Outstanding question - how closely should we try to match LSP symbol kind? Not at all? Should we have markup specific symbol kinds? (For example see markdown's `symbols.scm`).
+
+Also this PR needs docs on writing `symbols.scm` queries.
diff --git a/runtime/queries/spade/highlights.scm b/runtime/queries/spade/highlights.scm
new file mode 100644
index 00000000..08511b85
--- /dev/null
+++ b/runtime/queries/spade/highlights.scm
@@ -0,0 +1,130 @@
+(self) @variable.builtin
+
+(unit_definition (identifier) @function)
+
+(parameter (identifier) @variable.parameter)
+
+((pipeline_reg_marker) @keyword)
+
+(scoped_identifier
+ path: (identifier) @namespace)
+(scoped_identifier
+ (scoped_identifier
+ name: (identifier) @namespace))
+
+((builtin_type) @type.builtin)
+
+((identifier) @type.builtin
+ (#any-of?
+ @type.builtin
+ "uint"
+ "Option"
+ "Memory"))
+
+((identifier) @type.enum.variant.builtin
+ (#any-of? @type.enum.variant.builtin "Some" "None"))
+
+((pipeline_stage_name) @label)
+
+((stage_reference
+ stage: (identifier) @label))
+
+[
+ "pipeline"
+ "let"
+ "set"
+ "entity"
+ "fn"
+ "reg"
+ "reset"
+ "initial"
+ "inst"
+ "assert"
+ "struct"
+ "enum"
+ "stage"
+ "impl"
+ "port"
+ "decl"
+ "mod"
+ "where"
+ "trait"
+] @keyword
+
+[
+ "use"
+] @keyword.import
+
+[
+ "$if"
+ "$else"
+ "$config"
+] @keyword.directive
+
+((comptime_if ["{" "}"] @keyword.directive))
+((comptime_else ["{" "}"] @keyword.directive))
+
+((attribute) ["#" "[" "]"] @punctuation.delimiter)
+
+[
+ "else"
+ "if"
+ "match"
+] @keyword.control.conditional
+
+(bool_literal) @constant.builtin.boolean
+(int_literal) @constant.numeric.integer
+
+[
+ "&"
+ "inv"
+ "-"
+ "=>"
+ ">"
+ "<"
+ "::<"
+ "::$<"
+ "="
+ "->"
+ "~"
+ "!"
+] @operator
+
+
+((op_add) @operator)
+((op_sub) @operator)
+((op_mul) @operator)
+((op_equals) @operator)
+((op_lt) @operator)
+((op_gt) @operator)
+((op_le) @operator)
+((op_ge) @operator)
+((op_lshift) @operator)
+((op_rshift) @operator)
+((op_bitwise_and) @operator)
+((op_bitwise_xor) @operator)
+((op_bitwise_or) @operator)
+((op_logical_and) @operator)
+((op_logical_or) @operator)
+
+
+[
+ (line_comment)
+ (block_comment)
+] @comment
+
+[
+ (doc_comment)
+] @comment.block.documentation
+
+
+((identifier) @type
+ (#match? @type "[A-Z]"))
+
+((scoped_identifier
+ name: (identifier) @type)
+ (#match? @type "^[A-Z]"))
+
+((identifier) @constant
+ (#match? @constant "^[A-Z][A-Z\\d_]*$"))
+
diff --git a/runtime/queries/spade/indents.scm b/runtime/queries/spade/indents.scm
new file mode 100644
index 00000000..dc30bdc3
--- /dev/null
+++ b/runtime/queries/spade/indents.scm
@@ -0,0 +1,27 @@
+
+[
+ (unit_definition)
+ (struct_definition)
+ (enum_definition)
+ (enum_member)
+ (impl)
+ (mod)
+ (argument_list)
+ (let_binding)
+ (block)
+ (tuple_literal)
+ (array_literal)
+ (paren_expression)
+ (turbofish)
+ (generic_parameters)
+ (named_unpack)
+ (positional_unpack)
+ (tuple_pattern)
+] @indent
+
+[
+ "}"
+ "]"
+ ")"
+] @outdent
+