@gram-data/tree-sitter-gram 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bindings/node/binding_test.js +18 -19
- package/editors/zed/Cargo.toml +20 -0
- package/editors/zed/README.md +23 -5
- package/editors/zed/build.rs +26 -0
- package/editors/zed/extension.toml +7 -2
- package/editors/zed/languages/gram/config.toml +2 -2
- package/editors/zed/languages/gram/highlights.scm +28 -10
- package/editors/zed/languages/gram/locals.scm +9 -0
- package/editors/zed/src/lib.rs +156 -0
- package/grammar.js +13 -4
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/darwin-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/linux-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/linux-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/win32-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/win32-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/queries/highlights.scm +28 -10
- package/queries/locals.scm +9 -0
- package/src/grammar.json +83 -5
- package/src/node-types.json +60 -24
- package/src/parser.c +1847 -2061
- package/src/tree_sitter/array.h +68 -124
- package/tree-sitter-gram.wasm +0 -0
- package/tree-sitter.json +5 -4
|
@@ -8,30 +8,29 @@ test("can load grammar", () => {
|
|
|
8
8
|
assert.doesNotThrow(() => parser.setLanguage(require(".")));
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
test("
|
|
11
|
+
test("parses a simple node pattern", () => {
|
|
12
12
|
const Parser = require("tree-sitter");
|
|
13
13
|
const GramLang = require(".");
|
|
14
14
|
const parser = new Parser();
|
|
15
15
|
parser.setLanguage(GramLang);
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const tree = parser.parse("(a)");
|
|
18
|
+
const pattern = tree.rootNode.child(0);
|
|
19
|
+
assert(pattern, "root should have a pattern child");
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
// Find the symbol 'a' in the pattern
|
|
22
|
+
function findSymbol(node, text) {
|
|
23
|
+
if (node.isNamed && node.type === "symbol" && node.text === text) {
|
|
24
|
+
return node;
|
|
25
|
+
}
|
|
26
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
27
|
+
const result = findSymbol(node.child(i), text);
|
|
28
|
+
if (result) return result;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
27
32
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
assert(
|
|
31
|
-
const annotations2 = ap2.childForFieldName("annotations");
|
|
32
|
-
assert(annotations2, "annotations node should exist");
|
|
33
|
-
const first2 = annotations2.child(0);
|
|
34
|
-
assert.strictEqual(first2?.type, "property_annotation", "@ form should be property_annotation");
|
|
35
|
-
assert(first2?.childForFieldName("key"), "property_annotation should have key field");
|
|
36
|
-
assert(first2?.childForFieldName("value"), "property_annotation should have value field");
|
|
33
|
+
const symbol = findSymbol(pattern, "a");
|
|
34
|
+
assert(symbol, "pattern should contain symbol 'a'");
|
|
35
|
+
assert.strictEqual(symbol.type, "symbol");
|
|
37
36
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "gram_zed_extension"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
publish = false
|
|
7
|
+
repository = "https://github.com/gram-data/tree-sitter-gram"
|
|
8
|
+
build = "build.rs"
|
|
9
|
+
|
|
10
|
+
[lib]
|
|
11
|
+
path = "src/lib.rs"
|
|
12
|
+
crate-type = ["cdylib"]
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
zed_extension_api = "0.7"
|
|
16
|
+
|
|
17
|
+
# Standalone workspace root so this crate is not treated as a stray member of the
|
|
18
|
+
# repository workspace (see root `Cargo.toml` `[workspace]`).
|
|
19
|
+
[workspace]
|
|
20
|
+
members = ["."]
|
package/editors/zed/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A [Zed](https://zed.dev) extension providing syntax highlighting and language su
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Syntax Highlighting**: Full syntax highlighting for all Gram constructs including subjects, nodes, relationships, and data types
|
|
8
|
+
- **Language server**: When [`gram-lsp`](../../tools/lsp/) is on your `PATH`, Zed starts it for `.gram` files (diagnostics, hover, definitions, references, completions)
|
|
8
9
|
- **Subject Pattern Matching**: Automatic matching for `()`, `[]`, and `{}`
|
|
9
10
|
- **File Type Detection**: Automatic recognition of `.gram` files
|
|
10
11
|
- **Smart Indentation**: Proper indentation handling for nested structures
|
|
@@ -40,7 +41,7 @@ Then restart Zed.
|
|
|
40
41
|
|
|
41
42
|
## Usage
|
|
42
43
|
|
|
43
|
-
Once installed, the extension
|
|
44
|
+
Once installed, the extension provides syntax highlighting for `.gram` files. With `gram-lsp` installed and on `PATH`, Zed also attaches the language server automatically.
|
|
44
45
|
|
|
45
46
|
### Example Gram Syntax
|
|
46
47
|
|
|
@@ -108,14 +109,25 @@ To work on this extension:
|
|
|
108
109
|
- Select the `editors/zed` directory
|
|
109
110
|
- Restart Zed
|
|
110
111
|
|
|
111
|
-
3.
|
|
112
|
-
|
|
112
|
+
3. Build the Wasm extension once after Rust changes (Zed loads the cdylib):
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
rustup target add wasm32-wasip1
|
|
116
|
+
cd editors/zed && cargo check --target wasm32-wasip1
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
4. Make changes to the extension files
|
|
120
|
+
5. Restart Zed to see changes
|
|
113
121
|
|
|
114
122
|
### Extension Structure
|
|
115
123
|
|
|
116
124
|
```
|
|
117
125
|
editors/zed/
|
|
118
|
-
├──
|
|
126
|
+
├── Cargo.toml # Wasm extension crate (zed_extension_api)
|
|
127
|
+
├── build.rs # Embeds `extension.toml` version for release asset lookup
|
|
128
|
+
├── Cargo.lock
|
|
129
|
+
├── src/lib.rs # `language_server_command`: PATH, then GitHub release download
|
|
130
|
+
├── extension.toml # Extension metadata; grammar repo + `[language_servers.gram-lsp]`
|
|
119
131
|
├── languages/
|
|
120
132
|
│ └── gram/
|
|
121
133
|
│ ├── config.toml # Zed language config (brackets, suffixes, etc.)
|
|
@@ -144,6 +156,12 @@ After either command, `extension.toml` is updated in place. For local dev you ty
|
|
|
144
156
|
|
|
145
157
|
**If Zed shows an old version (e.g. 0.1.11) after installing the dev extension:** Zed may be using a cached clone of the grammar (at an old rev) or an older copy of the extension. Try: (1) Uninstall the Gram extension from Zed’s Extensions panel. (2) Delete the grammar cache: remove `editors/zed/grammars/` if it exists (Zed recreates it when needed). (3) Run `npm run zed:dev` again so `extension.toml` has the current version and rev. (4) In Zed, run “Install Dev Extension” and select `editors/zed` again. Restart Zed and recheck the extension version.
|
|
146
158
|
|
|
159
|
+
### Bundled `gram-lsp` (GitHub Releases)
|
|
160
|
+
|
|
161
|
+
Zed extensions ship a **Wasm** adapter only; native `gram-lsp` binaries cannot be embedded in that bundle. Instead, when `gram-lsp` is **not** on `PATH`, the extension downloads a platform archive from **this repo’s GitHub Release** whose tag is **`v` + `version` from `extension.toml`** (for example `v0.3.5` for `version = "0.3.5"`).
|
|
162
|
+
|
|
163
|
+
Maintainers: pushing a **`v*`** tag runs **`.github/workflows/gram-lsp-release-assets.yml`**, which builds `gram-lsp` for common targets and uploads `gram-lsp-{target}.tar.gz` to the matching GitHub Release. Filenames must stay in sync with `editors/zed/src/lib.rs`. Keep `extension.toml`’s `version` aligned with the tag you ship to the Zed extension registry (for example tag `v0.3.5` and `version = "0.3.5"`) so installs download the intended binaries.
|
|
164
|
+
|
|
147
165
|
## Contributing
|
|
148
166
|
|
|
149
167
|
Contributions are welcome! Please see the main [repository](https://github.com/gram-data/tree-sitter-gram) for contribution guidelines.
|
|
@@ -156,7 +174,7 @@ To improve syntax highlighting and editor behavior:
|
|
|
156
174
|
|
|
157
175
|
## License
|
|
158
176
|
|
|
159
|
-
This extension is part of the tree-sitter-gram project and is licensed under the
|
|
177
|
+
This extension is part of the tree-sitter-gram project and is licensed under the MIT License. See the main repository's [LICENSE](../../LICENSE) file for details.
|
|
160
178
|
|
|
161
179
|
## Learn More
|
|
162
180
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//! Expose `extension.toml`'s `version = "…"` as `env!("GRAM_EXT_VERSION")` for release lookups.
|
|
2
|
+
|
|
3
|
+
use std::env;
|
|
4
|
+
use std::fs;
|
|
5
|
+
use std::path::PathBuf;
|
|
6
|
+
|
|
7
|
+
fn main() {
|
|
8
|
+
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
|
|
9
|
+
let ext_toml = manifest_dir.join("extension.toml");
|
|
10
|
+
println!("cargo:rerun-if-changed={}", ext_toml.display());
|
|
11
|
+
|
|
12
|
+
let content = fs::read_to_string(&ext_toml).unwrap_or_else(|e| panic!("read {}: {e}", ext_toml.display()));
|
|
13
|
+
let version = parse_version(&content)
|
|
14
|
+
.unwrap_or_else(|| panic!("{}: missing `version = \"…\"` line", ext_toml.display()));
|
|
15
|
+
println!("cargo:rustc-env=GRAM_EXT_VERSION={version}");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn parse_version(toml: &str) -> Option<String> {
|
|
19
|
+
for line in toml.lines() {
|
|
20
|
+
let line = line.trim();
|
|
21
|
+
if let Some(rest) = line.strip_prefix("version = \"") {
|
|
22
|
+
return rest.split('"').next().map(str::to_string);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
None
|
|
26
|
+
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
id = "gram"
|
|
2
2
|
name = "Gram Language Support"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.6"
|
|
4
4
|
schema_version = 1
|
|
5
5
|
authors = ["Gram Data Contributors"]
|
|
6
6
|
description = "Support for Gram notation - composable data patterns"
|
|
7
7
|
|
|
8
|
+
capabilities = [
|
|
9
|
+
{ kind = "process:exec", command = "*", args = ["stdio"] },
|
|
10
|
+
{ kind = "download_file", host = "github.com", path = ["gram-data", "tree-sitter-gram", "**"] },
|
|
11
|
+
]
|
|
12
|
+
|
|
8
13
|
# path = "grammars/tree-sitter-gram"
|
|
9
14
|
[grammars.gram]
|
|
10
15
|
repository = "https://github.com/gram-data/tree-sitter-gram"
|
|
11
|
-
rev = "
|
|
16
|
+
rev = "184b524f4a0653bee3a07c44907dc266d698cb6e"
|
|
@@ -12,5 +12,5 @@ word_characters = ["_"]
|
|
|
12
12
|
[prettier]
|
|
13
13
|
allowed = false
|
|
14
14
|
|
|
15
|
-
# [language_servers]
|
|
16
|
-
#
|
|
15
|
+
# Language servers are declared in extension.toml (`[language_servers.gram-lsp]`)
|
|
16
|
+
# and started from `src/lib.rs`. Per-server options go in Zed settings.json under `lsp`.
|
|
@@ -21,30 +21,48 @@
|
|
|
21
21
|
; Reference identifier: pattern_reference (FR-001)
|
|
22
22
|
(pattern_reference identifier: (_) @variable)
|
|
23
23
|
|
|
24
|
-
;
|
|
24
|
+
; Symbols and identifiers (generic; definition/reference/tag captured above)
|
|
25
|
+
(symbol) @variable
|
|
26
|
+
|
|
27
|
+
; Definition-like identifiers and labels (FR-001): @type
|
|
28
|
+
; These must come AFTER generic symbol rule to take priority
|
|
29
|
+
|
|
30
|
+
; Labels (symbols and quoted names in labels nodes)
|
|
31
|
+
(labels (symbol) @type)
|
|
32
|
+
(labels (quoted_name) @type)
|
|
33
|
+
|
|
34
|
+
; Annotation identifiers and labels
|
|
35
|
+
(identified_annotation identifier: (_) @type)
|
|
36
|
+
(identified_annotation labels: (labels (symbol) @type))
|
|
37
|
+
(identified_annotation labels: (labels (quoted_name) @type))
|
|
38
|
+
|
|
39
|
+
; Subject, node, and relationship pattern definitions (FR-001): @type
|
|
25
40
|
; subject/node subject is _subject (use wildcard _ as it may be hidden in some runtimes)
|
|
26
41
|
(subject_pattern subject: (_ identifier: (_) @type))
|
|
27
42
|
(subject_pattern subject: (_ labels: (labels (symbol) @type)))
|
|
43
|
+
(subject_pattern subject: (_ labels: (labels (quoted_name) @type)))
|
|
28
44
|
(node_pattern subject: (_ identifier: (_) @type))
|
|
29
45
|
(node_pattern subject: (_ labels: (labels (symbol) @type)))
|
|
46
|
+
(node_pattern subject: (_ labels: (labels (quoted_name) @type)))
|
|
30
47
|
(relationship_pattern left: (node_pattern subject: (_ identifier: (_) @type)))
|
|
31
48
|
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @type))))
|
|
49
|
+
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
|
|
32
50
|
(relationship_pattern right: (node_pattern subject: (_ identifier: (_) @type)))
|
|
33
51
|
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @type))))
|
|
52
|
+
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
|
|
34
53
|
; Arrow kind: subject is inside optional brackets on the arrow
|
|
35
54
|
(relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @type)))
|
|
36
55
|
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
56
|
+
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
37
57
|
(relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @type)))
|
|
38
58
|
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
59
|
+
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
39
60
|
(relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @type)))
|
|
40
61
|
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
62
|
+
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
41
63
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @type)))
|
|
42
64
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
43
|
-
(
|
|
44
|
-
(identified_annotation labels: (labels (symbol) @type))
|
|
45
|
-
|
|
46
|
-
; Symbols and identifiers (generic; definition/reference/tag captured above)
|
|
47
|
-
(symbol) @variable
|
|
65
|
+
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
48
66
|
|
|
49
67
|
; Keywords and operators
|
|
50
68
|
[
|
|
@@ -71,11 +89,11 @@
|
|
|
71
89
|
|
|
72
90
|
; Field names in records and maps
|
|
73
91
|
(record_property key: (symbol) @property)
|
|
74
|
-
(record_property key: (
|
|
75
|
-
(record_property key: (
|
|
92
|
+
(record_property key: (quoted_name) @property)
|
|
93
|
+
(record_property key: (double_quoted_name) @property)
|
|
76
94
|
(map_entry key: (symbol) @property)
|
|
77
|
-
(map_entry key: (
|
|
78
|
-
(map_entry key: (
|
|
95
|
+
(map_entry key: (quoted_name) @property)
|
|
96
|
+
(map_entry key: (double_quoted_name) @property)
|
|
79
97
|
|
|
80
98
|
; Annotation keys (property-style) and headers (identified/label-style)
|
|
81
99
|
(property_annotation key: (symbol) @attribute)
|
|
@@ -7,22 +7,31 @@
|
|
|
7
7
|
; Definitions: identifiers that define a pattern or annotation
|
|
8
8
|
(subject_pattern subject: (_ identifier: (_) @local.definition))
|
|
9
9
|
(subject_pattern subject: (_ labels: (labels (symbol) @local.definition)))
|
|
10
|
+
(subject_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
|
|
10
11
|
(node_pattern subject: (_ identifier: (_) @local.definition))
|
|
11
12
|
(node_pattern subject: (_ labels: (labels (symbol) @local.definition)))
|
|
13
|
+
(node_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
|
|
12
14
|
(relationship_pattern left: (node_pattern subject: (_ identifier: (_) @local.definition)))
|
|
13
15
|
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
|
|
16
|
+
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
14
17
|
(relationship_pattern right: (node_pattern subject: (_ identifier: (_) @local.definition)))
|
|
15
18
|
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
|
|
19
|
+
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
16
20
|
(relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @local.definition)))
|
|
17
21
|
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
22
|
+
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
18
23
|
(relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @local.definition)))
|
|
19
24
|
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
25
|
+
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
20
26
|
(relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @local.definition)))
|
|
21
27
|
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
28
|
+
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
22
29
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @local.definition)))
|
|
23
30
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
31
|
+
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
24
32
|
(identified_annotation identifier: (_) @local.definition)
|
|
25
33
|
(identified_annotation labels: (labels (symbol) @local.definition))
|
|
34
|
+
(identified_annotation labels: (labels (quoted_name) @local.definition))
|
|
26
35
|
|
|
27
36
|
; References: pattern_reference identifier
|
|
28
37
|
(pattern_reference identifier: (_) @local.reference)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//! Zed extension host glue: starts `gram-lsp` from `PATH` or downloads a release asset.
|
|
2
|
+
|
|
3
|
+
use zed_extension_api::{
|
|
4
|
+
self as zed,
|
|
5
|
+
github_release_by_tag_name,
|
|
6
|
+
set_language_server_installation_status,
|
|
7
|
+
Architecture, Command, DownloadedFileType, Extension, LanguageServerId,
|
|
8
|
+
LanguageServerInstallationStatus, Os, Result, Worktree, current_platform, download_file,
|
|
9
|
+
make_file_executable,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const GRAM_REPO: &str = "gram-data/tree-sitter-gram";
|
|
13
|
+
|
|
14
|
+
struct GramExtension {
|
|
15
|
+
/// Relative path (under the extension work dir) or absolute path from `which`.
|
|
16
|
+
cached_binary: Option<String>,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl GramExtension {
|
|
20
|
+
fn rust_target_triple() -> Result<&'static str> {
|
|
21
|
+
match current_platform() {
|
|
22
|
+
(Os::Mac, Architecture::Aarch64) => Ok("aarch64-apple-darwin"),
|
|
23
|
+
(Os::Mac, Architecture::X8664) => Ok("x86_64-apple-darwin"),
|
|
24
|
+
(Os::Linux, Architecture::Aarch64) => Ok("aarch64-unknown-linux-gnu"),
|
|
25
|
+
(Os::Linux, Architecture::X8664) => Ok("x86_64-unknown-linux-gnu"),
|
|
26
|
+
(Os::Windows, Architecture::Aarch64) => Ok("aarch64-pc-windows-msvc"),
|
|
27
|
+
(Os::Windows, Architecture::X8664) => Ok("x86_64-pc-windows-msvc"),
|
|
28
|
+
(Os::Linux, Architecture::X86) | (Os::Windows, Architecture::X86) => Err(
|
|
29
|
+
"gram-lsp: 32-bit platforms are not supported; install gram-lsp on PATH manually"
|
|
30
|
+
.into(),
|
|
31
|
+
),
|
|
32
|
+
(Os::Mac, Architecture::X86) => Err(
|
|
33
|
+
"gram-lsp: unexpected macOS x86 architecture; install gram-lsp on PATH manually"
|
|
34
|
+
.into(),
|
|
35
|
+
),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fn gram_lsp_bin_name(os: Os) -> &'static str {
|
|
40
|
+
match os {
|
|
41
|
+
Os::Windows => "gram-lsp.exe",
|
|
42
|
+
Os::Mac | Os::Linux => "gram-lsp",
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn ensure_downloaded(
|
|
47
|
+
&mut self,
|
|
48
|
+
language_server_id: &LanguageServerId,
|
|
49
|
+
) -> Result<String> {
|
|
50
|
+
let version = env!("GRAM_EXT_VERSION");
|
|
51
|
+
let extract_dir = format!("gram-lsp-{version}");
|
|
52
|
+
let (os, _) = current_platform();
|
|
53
|
+
let bin_name = Self::gram_lsp_bin_name(os);
|
|
54
|
+
let relative_binary = format!("{extract_dir}/{bin_name}");
|
|
55
|
+
|
|
56
|
+
let triple = Self::rust_target_triple()?;
|
|
57
|
+
let asset_name = format!("gram-lsp-{triple}.tar.gz");
|
|
58
|
+
let tag = format!("v{version}");
|
|
59
|
+
|
|
60
|
+
set_language_server_installation_status(
|
|
61
|
+
language_server_id,
|
|
62
|
+
&LanguageServerInstallationStatus::Downloading,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
let release = match github_release_by_tag_name(GRAM_REPO, &tag) {
|
|
66
|
+
Ok(r) => r,
|
|
67
|
+
Err(e) => {
|
|
68
|
+
let detail = format!(
|
|
69
|
+
"GitHub release {tag}: {e}. Install `gram-lsp` on PATH or publish release assets (see .github/workflows/gram-lsp-release-assets.yml)."
|
|
70
|
+
);
|
|
71
|
+
set_language_server_installation_status(
|
|
72
|
+
language_server_id,
|
|
73
|
+
&LanguageServerInstallationStatus::Failed(detail.clone()),
|
|
74
|
+
);
|
|
75
|
+
return Err(format!("gram-lsp: no GitHub release for {tag}: {e}"));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let asset = match release.assets.iter().find(|a| a.name == asset_name) {
|
|
80
|
+
Some(a) => a,
|
|
81
|
+
None => {
|
|
82
|
+
let msg = format!(
|
|
83
|
+
"gram-lsp: release {tag} has no asset {asset_name}. Build with the gram-lsp-release-assets workflow."
|
|
84
|
+
);
|
|
85
|
+
set_language_server_installation_status(
|
|
86
|
+
language_server_id,
|
|
87
|
+
&LanguageServerInstallationStatus::Failed(msg.clone()),
|
|
88
|
+
);
|
|
89
|
+
return Err(msg);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if let Err(e) = download_file(
|
|
94
|
+
&asset.download_url,
|
|
95
|
+
&extract_dir,
|
|
96
|
+
DownloadedFileType::GzipTar,
|
|
97
|
+
) {
|
|
98
|
+
set_language_server_installation_status(
|
|
99
|
+
language_server_id,
|
|
100
|
+
&LanguageServerInstallationStatus::Failed(e.clone()),
|
|
101
|
+
);
|
|
102
|
+
return Err(format!("gram-lsp: download failed: {e}"));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if let Err(e) = make_file_executable(&relative_binary) {
|
|
106
|
+
set_language_server_installation_status(
|
|
107
|
+
language_server_id,
|
|
108
|
+
&LanguageServerInstallationStatus::Failed(e.clone()),
|
|
109
|
+
);
|
|
110
|
+
return Err(format!("gram-lsp: chmod failed: {e}"));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set_language_server_installation_status(
|
|
114
|
+
language_server_id,
|
|
115
|
+
&LanguageServerInstallationStatus::None,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
self.cached_binary = Some(relative_binary.clone());
|
|
119
|
+
Ok(relative_binary)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
impl Extension for GramExtension {
|
|
124
|
+
fn new() -> Self {
|
|
125
|
+
Self {
|
|
126
|
+
cached_binary: None,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fn language_server_command(
|
|
131
|
+
&mut self,
|
|
132
|
+
language_server_id: &LanguageServerId,
|
|
133
|
+
worktree: &Worktree,
|
|
134
|
+
) -> Result<Command> {
|
|
135
|
+
if language_server_id.as_ref() != "gram-lsp" {
|
|
136
|
+
return Err(format!(
|
|
137
|
+
"unsupported language server id: {}",
|
|
138
|
+
language_server_id.as_ref()
|
|
139
|
+
));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if let Some(path) = &self.cached_binary {
|
|
143
|
+
return Ok(Command::new(path).arg("stdio"));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if let Some(path) = worktree.which("gram-lsp") {
|
|
147
|
+
self.cached_binary = Some(path.clone());
|
|
148
|
+
return Ok(Command::new(path).arg("stdio"));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let path = self.ensure_downloaded(language_server_id)?;
|
|
152
|
+
Ok(Command::new(path).arg("stdio"))
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
zed::register_extension!(GramExtension);
|
package/grammar.js
CHANGED
|
@@ -69,7 +69,7 @@ module.exports = grammar({
|
|
|
69
69
|
|
|
70
70
|
pattern_reference: ($) => field("identifier", $._identifier),
|
|
71
71
|
|
|
72
|
-
_identifier: ($) => choice($.symbol, $.
|
|
72
|
+
_identifier: ($) => choice($.symbol, $.quoted_name, $.integer),
|
|
73
73
|
|
|
74
74
|
_subject: ($) =>
|
|
75
75
|
choice(
|
|
@@ -114,13 +114,13 @@ module.exports = grammar({
|
|
|
114
114
|
|
|
115
115
|
labels: ($) => repeat1($._label),
|
|
116
116
|
|
|
117
|
-
_label: ($) => seq(choice(":", "::"), $.symbol),
|
|
117
|
+
_label: ($) => seq(choice(":", "::"), choice($.symbol, $.quoted_name)),
|
|
118
118
|
|
|
119
119
|
record: ($) => seq("{", commaSep($.record_property), "}"),
|
|
120
120
|
|
|
121
121
|
record_property: ($) =>
|
|
122
122
|
seq(
|
|
123
|
-
field("key", $.
|
|
123
|
+
field("key", $._key_name),
|
|
124
124
|
choice(":", "::"),
|
|
125
125
|
field("value", $._value),
|
|
126
126
|
),
|
|
@@ -128,7 +128,7 @@ module.exports = grammar({
|
|
|
128
128
|
map: ($) => seq("{", commaSep($.map_entry), "}"),
|
|
129
129
|
|
|
130
130
|
map_entry: ($) =>
|
|
131
|
-
seq(field("key", $.
|
|
131
|
+
seq(field("key", $._key_name), ":", field("value", $._scalar_value)),
|
|
132
132
|
|
|
133
133
|
symbol: ($) => token(/[a-zA-Z_][0-9a-zA-Z_.\-@]*/),
|
|
134
134
|
|
|
@@ -174,6 +174,15 @@ module.exports = grammar({
|
|
|
174
174
|
return token(measurement);
|
|
175
175
|
},
|
|
176
176
|
|
|
177
|
+
quoted_name: ($) =>
|
|
178
|
+
delimit_string(alias($._backticked_text, $.string_content), "`"),
|
|
179
|
+
|
|
180
|
+
double_quoted_name: ($) =>
|
|
181
|
+
delimit_string(alias($._double_quoted_text, $.string_content), '"'),
|
|
182
|
+
|
|
183
|
+
_key_name: ($) =>
|
|
184
|
+
choice($.symbol, $.quoted_name, $.double_quoted_name),
|
|
185
|
+
|
|
177
186
|
string_literal: ($) =>
|
|
178
187
|
choice(
|
|
179
188
|
$._single_quoted_string,
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/queries/highlights.scm
CHANGED
|
@@ -21,30 +21,48 @@
|
|
|
21
21
|
; Reference identifier: pattern_reference (FR-001)
|
|
22
22
|
(pattern_reference identifier: (_) @variable)
|
|
23
23
|
|
|
24
|
-
;
|
|
24
|
+
; Symbols and identifiers (generic; definition/reference/tag captured above)
|
|
25
|
+
(symbol) @variable
|
|
26
|
+
|
|
27
|
+
; Definition-like identifiers and labels (FR-001): @type
|
|
28
|
+
; These must come AFTER generic symbol rule to take priority
|
|
29
|
+
|
|
30
|
+
; Labels (symbols and quoted names in labels nodes)
|
|
31
|
+
(labels (symbol) @type)
|
|
32
|
+
(labels (quoted_name) @type)
|
|
33
|
+
|
|
34
|
+
; Annotation identifiers and labels
|
|
35
|
+
(identified_annotation identifier: (_) @type)
|
|
36
|
+
(identified_annotation labels: (labels (symbol) @type))
|
|
37
|
+
(identified_annotation labels: (labels (quoted_name) @type))
|
|
38
|
+
|
|
39
|
+
; Subject, node, and relationship pattern definitions (FR-001): @type
|
|
25
40
|
; subject/node subject is _subject (use wildcard _ as it may be hidden in some runtimes)
|
|
26
41
|
(subject_pattern subject: (_ identifier: (_) @type))
|
|
27
42
|
(subject_pattern subject: (_ labels: (labels (symbol) @type)))
|
|
43
|
+
(subject_pattern subject: (_ labels: (labels (quoted_name) @type)))
|
|
28
44
|
(node_pattern subject: (_ identifier: (_) @type))
|
|
29
45
|
(node_pattern subject: (_ labels: (labels (symbol) @type)))
|
|
46
|
+
(node_pattern subject: (_ labels: (labels (quoted_name) @type)))
|
|
30
47
|
(relationship_pattern left: (node_pattern subject: (_ identifier: (_) @type)))
|
|
31
48
|
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @type))))
|
|
49
|
+
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
|
|
32
50
|
(relationship_pattern right: (node_pattern subject: (_ identifier: (_) @type)))
|
|
33
51
|
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @type))))
|
|
52
|
+
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
|
|
34
53
|
; Arrow kind: subject is inside optional brackets on the arrow
|
|
35
54
|
(relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @type)))
|
|
36
55
|
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
56
|
+
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
37
57
|
(relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @type)))
|
|
38
58
|
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
59
|
+
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
39
60
|
(relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @type)))
|
|
40
61
|
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
62
|
+
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
41
63
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @type)))
|
|
42
64
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @type))))
|
|
43
|
-
(
|
|
44
|
-
(identified_annotation labels: (labels (symbol) @type))
|
|
45
|
-
|
|
46
|
-
; Symbols and identifiers (generic; definition/reference/tag captured above)
|
|
47
|
-
(symbol) @variable
|
|
65
|
+
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @type))))
|
|
48
66
|
|
|
49
67
|
; Keywords and operators
|
|
50
68
|
[
|
|
@@ -71,11 +89,11 @@
|
|
|
71
89
|
|
|
72
90
|
; Field names in records and maps
|
|
73
91
|
(record_property key: (symbol) @property)
|
|
74
|
-
(record_property key: (
|
|
75
|
-
(record_property key: (
|
|
92
|
+
(record_property key: (quoted_name) @property)
|
|
93
|
+
(record_property key: (double_quoted_name) @property)
|
|
76
94
|
(map_entry key: (symbol) @property)
|
|
77
|
-
(map_entry key: (
|
|
78
|
-
(map_entry key: (
|
|
95
|
+
(map_entry key: (quoted_name) @property)
|
|
96
|
+
(map_entry key: (double_quoted_name) @property)
|
|
79
97
|
|
|
80
98
|
; Annotation keys (property-style) and headers (identified/label-style)
|
|
81
99
|
(property_annotation key: (symbol) @attribute)
|
package/queries/locals.scm
CHANGED
|
@@ -7,22 +7,31 @@
|
|
|
7
7
|
; Definitions: identifiers that define a pattern or annotation
|
|
8
8
|
(subject_pattern subject: (_ identifier: (_) @local.definition))
|
|
9
9
|
(subject_pattern subject: (_ labels: (labels (symbol) @local.definition)))
|
|
10
|
+
(subject_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
|
|
10
11
|
(node_pattern subject: (_ identifier: (_) @local.definition))
|
|
11
12
|
(node_pattern subject: (_ labels: (labels (symbol) @local.definition)))
|
|
13
|
+
(node_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
|
|
12
14
|
(relationship_pattern left: (node_pattern subject: (_ identifier: (_) @local.definition)))
|
|
13
15
|
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
|
|
16
|
+
(relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
14
17
|
(relationship_pattern right: (node_pattern subject: (_ identifier: (_) @local.definition)))
|
|
15
18
|
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
|
|
19
|
+
(relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
16
20
|
(relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @local.definition)))
|
|
17
21
|
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
22
|
+
(relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
18
23
|
(relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @local.definition)))
|
|
19
24
|
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
25
|
+
(relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
20
26
|
(relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @local.definition)))
|
|
21
27
|
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
28
|
+
(relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
22
29
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @local.definition)))
|
|
23
30
|
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @local.definition))))
|
|
31
|
+
(relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
|
|
24
32
|
(identified_annotation identifier: (_) @local.definition)
|
|
25
33
|
(identified_annotation labels: (labels (symbol) @local.definition))
|
|
34
|
+
(identified_annotation labels: (labels (quoted_name) @local.definition))
|
|
26
35
|
|
|
27
36
|
; References: pattern_reference identifier
|
|
28
37
|
(pattern_reference identifier: (_) @local.reference)
|