tree-sitter-ucode 0.1.2 → 0.3.0
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/README.md +64 -25
- package/grammar.js +2 -23
- package/package.json +3 -3
- package/prebuilds/darwin-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-x64/tree-sitter-ucode.node +0 -0
- package/prebuilds/win32-x64/tree-sitter-ucode.node +0 -0
- package/queries/folds.scm +38 -0
- package/queries/highlights.scm +6 -5
- package/queries/indents.scm +63 -0
- package/queries/locals.scm +2 -7
- package/queries/tags.scm +0 -13
- package/queries/textobjects.scm +84 -0
- package/src/grammar.json +6 -81
- package/src/node-types.json +0 -55
- package/src/parser.c +19148 -20592
- package/tmpl/grammar.js +2 -1
- package/tmpl/queries/folds.scm +4 -0
- package/tmpl/queries/indents.scm +5 -0
- package/tmpl/src/grammar.json +8 -0
- package/tmpl/src/node-types.json +8 -0
- package/tmpl/src/parser.c +43 -26
- package/tmpl/src/scanner.c +5 -0
- package/tree-sitter-ucode.wasm +0 -0
- package/tree-sitter-ucode_tmpl.wasm +0 -0
- package/tree-sitter.json +22 -21
package/README.md
CHANGED
|
@@ -7,7 +7,12 @@ Two grammars are provided:
|
|
|
7
7
|
| Grammar | Scope | File types |
|
|
8
8
|
|---------|-------|------------|
|
|
9
9
|
| `ucode` | `source.uc` | `.uc` |
|
|
10
|
-
| `ucode_tmpl` | `source.uc.tmpl` | `.uc
|
|
10
|
+
| `ucode_tmpl` | `source.uc.tmpl` | `.uc` (template files — detected by content) |
|
|
11
|
+
|
|
12
|
+
Both grammars use the `.uc` extension. Template files are distinguished from plain
|
|
13
|
+
code files by content: any `.uc` file whose first tag opener (`{%`, `{{`, or `{#`)
|
|
14
|
+
appears at the start of a line is automatically parsed by `ucode_tmpl`. Plain code
|
|
15
|
+
files fall back to `ucode`. See [File-type detection](#file-type-detection) below.
|
|
11
16
|
|
|
12
17
|
## Ucode vs JavaScript
|
|
13
18
|
|
|
@@ -17,13 +22,12 @@ Ucode is an ECMAScript subset with OpenWrt-specific extensions. Key differences:
|
|
|
17
22
|
|---------|-------|------------|
|
|
18
23
|
| Alternative block syntax | `if/elif/else/endif`, `for/endfor`, `while/endwhile`, `function/endfunction` | Not supported |
|
|
19
24
|
| Two-variable for-in | `for (k, v in obj)` | Single variable only |
|
|
20
|
-
|
|
|
21
|
-
| Removed
|
|
22
|
-
| Removed features | Destructuring, `for...of`, `do-while`, generators | All supported |
|
|
25
|
+
| Removed keywords | `var`, `new`, `throw`, `typeof`, `void`, `class`, `instanceof`, `do`, `async`, `await`, `yield` | All supported |
|
|
26
|
+
| Removed features | Destructuring, `for...of`, `do-while`, generators, forward declarations, dynamic `import()` | All supported |
|
|
23
27
|
| Added number literals | `0177` (C octal), `0x1.8` (hex float), `0B`/`0O` prefixes | Standard only |
|
|
24
28
|
| Added escape sequences | `\e` (ESC), `\a` (BEL), octal `\177` | Standard only |
|
|
25
29
|
| Regex flags | `g`, `i`, `s` only | Full set |
|
|
26
|
-
| Module system | Static `import`/`export
|
|
30
|
+
| Module system | Static `import`/`export` only; no `from` on re-exports | Full ES modules |
|
|
27
31
|
|
|
28
32
|
## Requirements
|
|
29
33
|
|
|
@@ -56,10 +60,18 @@ npm test # runs tree-sitter test for ucode and ucode_tmpl
|
|
|
56
60
|
To filter by corpus file name:
|
|
57
61
|
|
|
58
62
|
```sh
|
|
59
|
-
npx tree-sitter test --file-name control_flow
|
|
63
|
+
npx tree-sitter test --lib-path ucode.so --lang-name ucode --file-name control_flow
|
|
60
64
|
npx tree-sitter test -p tmpl --file-name template
|
|
61
65
|
```
|
|
62
66
|
|
|
67
|
+
## File-type detection
|
|
68
|
+
|
|
69
|
+
Both grammars claim the `.uc` extension. Tools that respect `content-regex` in
|
|
70
|
+
`tree-sitter.json` (including the tree-sitter CLI ≥ 0.24) automatically route
|
|
71
|
+
template files to `ucode_tmpl` when a tag opener appears at the start of a line.
|
|
72
|
+
Editors that manage their own filetype dispatch (Neovim, Helix) need an explicit
|
|
73
|
+
rule — see the editor sections below.
|
|
74
|
+
|
|
63
75
|
## Use in Neovim (nvim-treesitter)
|
|
64
76
|
|
|
65
77
|
Add to your nvim-treesitter config (e.g. `~/.config/nvim/lua/plugins/treesitter.lua`):
|
|
@@ -86,15 +98,26 @@ parser_config.ucode_tmpl = {
|
|
|
86
98
|
}
|
|
87
99
|
```
|
|
88
100
|
|
|
89
|
-
Associate `.uc`
|
|
101
|
+
Associate `.uc` files with the right filetype. Since nvim-treesitter does not
|
|
102
|
+
use `content-regex`, the mapping must be done with a `BufRead` autocmd or a
|
|
103
|
+
filetype function that inspects the file content:
|
|
90
104
|
|
|
91
105
|
```lua
|
|
92
106
|
vim.filetype.add({
|
|
93
107
|
extension = {
|
|
94
|
-
uc
|
|
95
|
-
|
|
108
|
+
uc = function(path)
|
|
109
|
+
-- Files whose first tag opener is at the start of a line are templates
|
|
110
|
+
local f = io.open(path, "r")
|
|
111
|
+
if f then
|
|
112
|
+
local content = f:read("*a")
|
|
113
|
+
f:close()
|
|
114
|
+
if content:find("^%s*{[%%{#]", 1, false) or content:find("\n%s*{[%%{#]") then
|
|
115
|
+
return "ucode_tmpl"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
return "ucode"
|
|
119
|
+
end,
|
|
96
120
|
},
|
|
97
|
-
pattern = { [".*%.uc%.tmpl"] = "ucode_tmpl" },
|
|
98
121
|
})
|
|
99
122
|
```
|
|
100
123
|
|
|
@@ -104,32 +127,38 @@ Add to `~/.config/helix/languages.toml`:
|
|
|
104
127
|
|
|
105
128
|
```toml
|
|
106
129
|
[[language]]
|
|
107
|
-
name
|
|
108
|
-
scope
|
|
109
|
-
file-types
|
|
130
|
+
name = "ucode"
|
|
131
|
+
scope = "source.uc"
|
|
132
|
+
file-types = [{ glob = "*.uc" }]
|
|
110
133
|
comment-token = "//"
|
|
111
|
-
indent
|
|
112
|
-
grammar
|
|
134
|
+
indent = { tab-width = 2, unit = " " }
|
|
135
|
+
grammar = "ucode"
|
|
113
136
|
|
|
114
137
|
[[language]]
|
|
115
|
-
name
|
|
116
|
-
scope
|
|
117
|
-
|
|
118
|
-
|
|
138
|
+
name = "ucode-tmpl"
|
|
139
|
+
scope = "source.uc.tmpl"
|
|
140
|
+
comment-token = "{#"
|
|
141
|
+
indent = { tab-width = 2, unit = " " }
|
|
142
|
+
grammar = "ucode_tmpl"
|
|
119
143
|
|
|
120
144
|
[[grammar]]
|
|
121
145
|
name = "ucode"
|
|
122
|
-
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "
|
|
146
|
+
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.3.0" }
|
|
123
147
|
|
|
124
148
|
[[grammar]]
|
|
125
149
|
name = "ucode_tmpl"
|
|
126
|
-
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "
|
|
150
|
+
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.3.0", subpath = "tmpl" }
|
|
127
151
|
```
|
|
128
152
|
|
|
129
|
-
|
|
153
|
+
Helix does not support content-based filetype detection. To open a `.uc`
|
|
154
|
+
template file as `ucode-tmpl`, use `:set-language ucode-tmpl` in command mode,
|
|
155
|
+
or configure a file-specific override via a `.helix/languages.toml` in your
|
|
156
|
+
project.
|
|
157
|
+
|
|
158
|
+
## Template files
|
|
130
159
|
|
|
131
|
-
Template files mix raw text with code tags. The `ucode_tmpl` grammar produces
|
|
132
|
-
|
|
160
|
+
Template files mix raw text with code tags. The `ucode_tmpl` grammar produces a
|
|
161
|
+
`document` tree; editors use language injection to apply ucode highlighting
|
|
133
162
|
inside the code and expression tags.
|
|
134
163
|
|
|
135
164
|
| Tag | Purpose |
|
|
@@ -142,7 +171,17 @@ inside the code and expression tags.
|
|
|
142
171
|
| `{%+ ... %}` | Statement block — suppress `lstrip_blocks` stripping |
|
|
143
172
|
| `{#- ... -#}` | Comment — strip whitespace on both sides |
|
|
144
173
|
|
|
145
|
-
Opener and closer markers are independent: any opener variant may be combined
|
|
174
|
+
Opener and closer markers are independent: any opener variant may be combined
|
|
175
|
+
with any closer variant. `{%-` / `{{-` / `{#-` strip the preceding raw text;
|
|
176
|
+
`-%}` / `-}}` / `-#}` strip the following raw text. `{%+` suppresses
|
|
177
|
+
`lstrip_blocks` stripping and may be combined with `-%}`.
|
|
178
|
+
|
|
179
|
+
**EOF-implicit close**: a `{%` statement tag that reaches end-of-file without
|
|
180
|
+
an explicit `%}` is treated as implicitly closed. This supports the common
|
|
181
|
+
OpenWrt pattern of a file that opens one `{%` block at the top and contains
|
|
182
|
+
only ucode code, with no closing `%}`. The parse tree shows an `(eof_close)`
|
|
183
|
+
node in the `close` field. Expression (`{{`) and comment (`{#`) tags still
|
|
184
|
+
require explicit closers.
|
|
146
185
|
|
|
147
186
|
Example:
|
|
148
187
|
|
package/grammar.js
CHANGED
|
@@ -46,6 +46,7 @@ module.exports = grammar({
|
|
|
46
46
|
'if',
|
|
47
47
|
'import',
|
|
48
48
|
'in',
|
|
49
|
+
'let',
|
|
49
50
|
'null',
|
|
50
51
|
'return',
|
|
51
52
|
'switch',
|
|
@@ -99,7 +100,6 @@ module.exports = grammar({
|
|
|
99
100
|
['member', 'call', $.expression],
|
|
100
101
|
['declaration', 'literal'],
|
|
101
102
|
[$.primary_expression, $.statement_block, 'object'],
|
|
102
|
-
[$.import_statement, $.import],
|
|
103
103
|
[$.export_statement, $.primary_expression],
|
|
104
104
|
[$.lexical_declaration, $.primary_expression],
|
|
105
105
|
],
|
|
@@ -143,7 +143,7 @@ module.exports = grammar({
|
|
|
143
143
|
'default',
|
|
144
144
|
seq(
|
|
145
145
|
field('value', $.expression),
|
|
146
|
-
|
|
146
|
+
';',
|
|
147
147
|
),
|
|
148
148
|
),
|
|
149
149
|
),
|
|
@@ -173,18 +173,14 @@ module.exports = grammar({
|
|
|
173
173
|
|
|
174
174
|
declaration: $ => choice(
|
|
175
175
|
$.function_declaration,
|
|
176
|
-
$.function_forward_declaration,
|
|
177
176
|
$.lexical_declaration,
|
|
178
177
|
),
|
|
179
178
|
|
|
180
179
|
//
|
|
181
180
|
// Import declarations
|
|
182
181
|
// Ucode keeps full ES module static import syntax.
|
|
183
|
-
// Also adds dynamic `import(path)` as a unary expression (see import_expression).
|
|
184
182
|
//
|
|
185
183
|
|
|
186
|
-
import: _ => token('import'),
|
|
187
|
-
|
|
188
184
|
import_statement: $ => seq(
|
|
189
185
|
'import',
|
|
190
186
|
choice(
|
|
@@ -461,7 +457,6 @@ module.exports = grammar({
|
|
|
461
457
|
$.binary_expression,
|
|
462
458
|
$.ternary_expression,
|
|
463
459
|
$.update_expression,
|
|
464
|
-
$.import_expression,
|
|
465
460
|
),
|
|
466
461
|
|
|
467
462
|
primary_expression: $ => choice(
|
|
@@ -485,14 +480,6 @@ module.exports = grammar({
|
|
|
485
480
|
$.call_expression,
|
|
486
481
|
),
|
|
487
482
|
|
|
488
|
-
// Dynamic import expression: `let m = import("./mod.uc")`
|
|
489
|
-
import_expression: $ => prec('call', seq(
|
|
490
|
-
$.import,
|
|
491
|
-
'(',
|
|
492
|
-
field('source', $.expression),
|
|
493
|
-
')',
|
|
494
|
-
)),
|
|
495
|
-
|
|
496
483
|
object: $ => prec('object', seq(
|
|
497
484
|
'{',
|
|
498
485
|
commaSep(optional(choice(
|
|
@@ -662,13 +649,6 @@ module.exports = grammar({
|
|
|
662
649
|
optional($._automatic_semicolon),
|
|
663
650
|
)),
|
|
664
651
|
|
|
665
|
-
// Forward declaration: `function name;`
|
|
666
|
-
function_forward_declaration: $ => seq(
|
|
667
|
-
'function',
|
|
668
|
-
field('name', $.identifier),
|
|
669
|
-
';',
|
|
670
|
-
),
|
|
671
|
-
|
|
672
652
|
arrow_function: $ => seq(
|
|
673
653
|
choice(
|
|
674
654
|
field('parameter', choice(
|
|
@@ -857,7 +837,6 @@ module.exports = grammar({
|
|
|
857
837
|
_reserved_identifier: _ => choice(
|
|
858
838
|
'get',
|
|
859
839
|
'set',
|
|
860
|
-
'let',
|
|
861
840
|
),
|
|
862
841
|
|
|
863
842
|
_semicolon: $ => choice($._automatic_semicolon, ';'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tree-sitter-ucode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Ucode grammar for tree-sitter",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"prebuildify": "^6.0.1",
|
|
38
|
-
"tree-sitter-cli": "
|
|
38
|
+
"tree-sitter-cli": "0.26.9"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"tree-sitter": "^0.22.0"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"scripts": {
|
|
49
49
|
"install": "node-gyp-build",
|
|
50
50
|
"build": "tree-sitter generate && tree-sitter generate tmpl/grammar.js --output tmpl/src && node-gyp-build && tree-sitter build --output ucode.so . && tree-sitter build --output ucode_tmpl.so ./tmpl",
|
|
51
|
-
"test": "
|
|
51
|
+
"test": "node scripts/run-tests.js",
|
|
52
52
|
"prestart": "tree-sitter build --wasm",
|
|
53
53
|
"start": "tree-sitter playground"
|
|
54
54
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
; Fold queries for ucode.
|
|
2
|
+
; Each captured node becomes a collapsible fold region.
|
|
3
|
+
|
|
4
|
+
; -------------------------------------------------------------------------
|
|
5
|
+
; Brace-delimited blocks
|
|
6
|
+
;
|
|
7
|
+
; statement_block covers brace-body function_declaration, function_expression,
|
|
8
|
+
; and arrow_function bodies — the signature line stays visible because the
|
|
9
|
+
; fold starts at '{', not at the 'function' keyword.
|
|
10
|
+
; -------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
[
|
|
13
|
+
(statement_block)
|
|
14
|
+
(switch_body)
|
|
15
|
+
(object)
|
|
16
|
+
(array)
|
|
17
|
+
] @fold
|
|
18
|
+
|
|
19
|
+
; -------------------------------------------------------------------------
|
|
20
|
+
; Alternative (colon/endif) syntax — fold the entire construct
|
|
21
|
+
; -------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
[
|
|
24
|
+
(if_alt_statement)
|
|
25
|
+
(for_alt_statement)
|
|
26
|
+
(for_in_alt_statement)
|
|
27
|
+
(while_alt_statement)
|
|
28
|
+
] @fold
|
|
29
|
+
|
|
30
|
+
; -------------------------------------------------------------------------
|
|
31
|
+
; Colon-body function declaration (function f(): ... endfunction)
|
|
32
|
+
;
|
|
33
|
+
; Brace-body function declarations are folded via (statement_block) above.
|
|
34
|
+
; The colon form has no statement_block, so we fold the whole declaration.
|
|
35
|
+
; We filter on "endfunction" so this pattern only matches the colon form.
|
|
36
|
+
; -------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
(function_declaration "endfunction") @fold
|
package/queries/highlights.scm
CHANGED
|
@@ -53,9 +53,6 @@
|
|
|
53
53
|
(function_declaration
|
|
54
54
|
name: (identifier) @function)
|
|
55
55
|
|
|
56
|
-
(function_forward_declaration
|
|
57
|
-
name: (identifier) @function)
|
|
58
|
-
|
|
59
56
|
(function_expression
|
|
60
57
|
name: (identifier) @function)
|
|
61
58
|
|
|
@@ -121,8 +118,12 @@
|
|
|
121
118
|
|
|
122
119
|
["import" "export"] @keyword.import
|
|
123
120
|
["as" "from"] @keyword.import
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
|
|
122
|
+
; 'default' in export context is a module keyword, not a conditional.
|
|
123
|
+
; These patterns are more specific than the generic ["switch" "case" "default"]
|
|
124
|
+
; below, so they take priority for 'default' tokens inside export constructs.
|
|
125
|
+
(export_statement "default" @keyword.import)
|
|
126
|
+
(export_specifier "default" @keyword.import)
|
|
126
127
|
|
|
127
128
|
; -------------------------------------------------------------------------
|
|
128
129
|
; Keywords — storage / operators
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
; Indentation queries for ucode.
|
|
2
|
+
; Capture names follow the nvim-treesitter standard.
|
|
3
|
+
|
|
4
|
+
; -------------------------------------------------------------------------
|
|
5
|
+
; Brace-delimited constructs — increase indent inside
|
|
6
|
+
; -------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
[
|
|
9
|
+
(statement_block)
|
|
10
|
+
(switch_body)
|
|
11
|
+
(object)
|
|
12
|
+
(array)
|
|
13
|
+
(arguments)
|
|
14
|
+
(formal_parameters)
|
|
15
|
+
] @indent.begin
|
|
16
|
+
|
|
17
|
+
; Closing delimiters — decrease indent
|
|
18
|
+
[
|
|
19
|
+
"}"
|
|
20
|
+
"]"
|
|
21
|
+
")"
|
|
22
|
+
] @indent.end
|
|
23
|
+
|
|
24
|
+
; -------------------------------------------------------------------------
|
|
25
|
+
; Alternative (colon/endif) syntax
|
|
26
|
+
; -------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
; The ':' after the condition opens the body
|
|
29
|
+
(if_alt_statement ":" @indent.begin)
|
|
30
|
+
(elif_clause ":" @indent.begin)
|
|
31
|
+
(for_alt_statement ":" @indent.begin)
|
|
32
|
+
(for_in_alt_statement ":" @indent.begin)
|
|
33
|
+
(while_alt_statement ":" @indent.begin)
|
|
34
|
+
(function_declaration ":" @indent.begin)
|
|
35
|
+
|
|
36
|
+
; Closing keywords close the body
|
|
37
|
+
[
|
|
38
|
+
"endif"
|
|
39
|
+
"endfor"
|
|
40
|
+
"endwhile"
|
|
41
|
+
"endfunction"
|
|
42
|
+
] @indent.end
|
|
43
|
+
|
|
44
|
+
; -------------------------------------------------------------------------
|
|
45
|
+
; Branch keywords (else/elif) — dedent keyword, indent following body
|
|
46
|
+
; -------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
(else_clause "else") @indent.branch
|
|
49
|
+
(else_alt_clause "else") @indent.branch
|
|
50
|
+
(elif_clause "elif") @indent.branch
|
|
51
|
+
|
|
52
|
+
; else_alt_clause has no ':' delimiter (grammar: 'else' repeat(statement)),
|
|
53
|
+
; so @indent.branch alone only dedents the 'else' keyword — it does not
|
|
54
|
+
; open an indent scope for the body. Add @indent.begin on the whole node
|
|
55
|
+
; so the body statements are indented one level relative to 'else'.
|
|
56
|
+
(else_alt_clause) @indent.begin
|
|
57
|
+
|
|
58
|
+
; -------------------------------------------------------------------------
|
|
59
|
+
; Switch
|
|
60
|
+
; -------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
(switch_case "case") @indent.branch
|
|
63
|
+
(switch_default "default") @indent.branch
|
package/queries/locals.scm
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
; -------------------------------------------------------------------------
|
|
7
7
|
|
|
8
8
|
(function_declaration) @local.scope
|
|
9
|
-
; function_forward_declaration has no body — it is a definition, not a scope
|
|
10
9
|
(function_expression) @local.scope
|
|
11
10
|
(arrow_function) @local.scope
|
|
12
11
|
; statement_block provides block scoping for let/const
|
|
@@ -23,16 +22,12 @@
|
|
|
23
22
|
; Definitions — functions
|
|
24
23
|
; -------------------------------------------------------------------------
|
|
25
24
|
|
|
26
|
-
;
|
|
27
|
-
;
|
|
25
|
+
; Function declaration names belong to the enclosing scope so that
|
|
26
|
+
; callers outside the function body can resolve them.
|
|
28
27
|
(function_declaration
|
|
29
28
|
name: (identifier) @local.definition.function
|
|
30
29
|
(#set! definition.function.scope parent))
|
|
31
30
|
|
|
32
|
-
(function_forward_declaration
|
|
33
|
-
name: (identifier) @local.definition.function
|
|
34
|
-
(#set! definition.function.scope parent))
|
|
35
|
-
|
|
36
31
|
; Named function expressions (let f = function foo() {}) keep their name
|
|
37
32
|
; *inside* the expression scope — foo is only visible for self-recursion,
|
|
38
33
|
; not to the surrounding block. No (#set! parent) here.
|
package/queries/tags.scm
CHANGED
|
@@ -14,19 +14,6 @@
|
|
|
14
14
|
(#select-adjacent! @doc @definition.function)
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
; -------------------------------------------------------------------------
|
|
18
|
-
; Function definitions — forward declarations: `function name;`
|
|
19
|
-
; -------------------------------------------------------------------------
|
|
20
|
-
|
|
21
|
-
(
|
|
22
|
-
(comment)* @doc
|
|
23
|
-
.
|
|
24
|
-
(function_forward_declaration
|
|
25
|
-
name: (identifier) @name) @definition.function
|
|
26
|
-
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
|
27
|
-
(#select-adjacent! @doc @definition.function)
|
|
28
|
-
)
|
|
29
|
-
|
|
30
17
|
; -------------------------------------------------------------------------
|
|
31
18
|
; Function definitions — named function expressions
|
|
32
19
|
; -------------------------------------------------------------------------
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
; Text-object queries for nvim-treesitter-textobjects.
|
|
2
|
+
; Provides @function, @parameter, @conditional, @loop, @call, and @block
|
|
3
|
+
; text objects for ucode source files.
|
|
4
|
+
|
|
5
|
+
; -------------------------------------------------------------------------
|
|
6
|
+
; Functions
|
|
7
|
+
; -------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
; Brace-body function declaration
|
|
10
|
+
(function_declaration
|
|
11
|
+
body: (statement_block) @function.inner) @function.outer
|
|
12
|
+
|
|
13
|
+
; Colon-body function declaration — outer only; no block node to target for inner
|
|
14
|
+
(function_declaration "endfunction") @function.outer
|
|
15
|
+
|
|
16
|
+
(function_expression
|
|
17
|
+
body: (statement_block) @function.inner) @function.outer
|
|
18
|
+
|
|
19
|
+
(arrow_function
|
|
20
|
+
body: (statement_block) @function.inner) @function.outer
|
|
21
|
+
|
|
22
|
+
; Arrow function with expression body (no braces).
|
|
23
|
+
; Uses the 'expression' supertype so all expression forms are matched
|
|
24
|
+
; without an explicit enumeration — including update_expression (x => x++),
|
|
25
|
+
; assignment_expression (x => y = 1), and any type added to the grammar later.
|
|
26
|
+
(arrow_function
|
|
27
|
+
body: (expression) @function.inner) @function.outer
|
|
28
|
+
|
|
29
|
+
; -------------------------------------------------------------------------
|
|
30
|
+
; Parameters
|
|
31
|
+
;
|
|
32
|
+
; @parameter.inner — the parameter node itself
|
|
33
|
+
; @parameter.outer — same node; nvim-treesitter-textobjects extends the
|
|
34
|
+
; selection to absorb adjacent ',' delimiters automatically when the
|
|
35
|
+
; capture name ends in .outer
|
|
36
|
+
; -------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
(formal_parameters (_) @parameter.inner)
|
|
39
|
+
(formal_parameters (_) @parameter.outer)
|
|
40
|
+
|
|
41
|
+
; -------------------------------------------------------------------------
|
|
42
|
+
; Conditionals
|
|
43
|
+
; -------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
(if_statement
|
|
46
|
+
consequence: (statement_block) @conditional.inner) @conditional.outer
|
|
47
|
+
|
|
48
|
+
(if_alt_statement) @conditional.outer
|
|
49
|
+
|
|
50
|
+
; -------------------------------------------------------------------------
|
|
51
|
+
; Loops
|
|
52
|
+
; -------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
(for_statement
|
|
55
|
+
body: (statement_block) @loop.inner) @loop.outer
|
|
56
|
+
|
|
57
|
+
(for_in_statement
|
|
58
|
+
body: (statement_block) @loop.inner) @loop.outer
|
|
59
|
+
|
|
60
|
+
(while_statement
|
|
61
|
+
body: (statement_block) @loop.inner) @loop.outer
|
|
62
|
+
|
|
63
|
+
(for_alt_statement) @loop.outer
|
|
64
|
+
(for_in_alt_statement) @loop.outer
|
|
65
|
+
(while_alt_statement) @loop.outer
|
|
66
|
+
|
|
67
|
+
; -------------------------------------------------------------------------
|
|
68
|
+
; Calls
|
|
69
|
+
; -------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
(call_expression
|
|
72
|
+
arguments: (arguments) @call.inner) @call.outer
|
|
73
|
+
|
|
74
|
+
; -------------------------------------------------------------------------
|
|
75
|
+
; Blocks
|
|
76
|
+
;
|
|
77
|
+
; @block.outer — the full statement_block including braces
|
|
78
|
+
; @block.inner — named children only; nvim-treesitter-textobjects selects
|
|
79
|
+
; from the first to the last captured child, covering the block interior
|
|
80
|
+
; without needing the deprecated #make-range! predicate
|
|
81
|
+
; -------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
(statement_block) @block.outer
|
|
84
|
+
(statement_block (_) @block.inner)
|
package/src/grammar.json
CHANGED
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
|
-
"type": "
|
|
92
|
-
"
|
|
91
|
+
"type": "STRING",
|
|
92
|
+
"value": ";"
|
|
93
93
|
}
|
|
94
94
|
]
|
|
95
95
|
}
|
|
@@ -221,23 +221,12 @@
|
|
|
221
221
|
"type": "SYMBOL",
|
|
222
222
|
"name": "function_declaration"
|
|
223
223
|
},
|
|
224
|
-
{
|
|
225
|
-
"type": "SYMBOL",
|
|
226
|
-
"name": "function_forward_declaration"
|
|
227
|
-
},
|
|
228
224
|
{
|
|
229
225
|
"type": "SYMBOL",
|
|
230
226
|
"name": "lexical_declaration"
|
|
231
227
|
}
|
|
232
228
|
]
|
|
233
229
|
},
|
|
234
|
-
"import": {
|
|
235
|
-
"type": "TOKEN",
|
|
236
|
-
"content": {
|
|
237
|
-
"type": "STRING",
|
|
238
|
-
"value": "import"
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
230
|
"import_statement": {
|
|
242
231
|
"type": "SEQ",
|
|
243
232
|
"members": [
|
|
@@ -1690,10 +1679,6 @@
|
|
|
1690
1679
|
{
|
|
1691
1680
|
"type": "SYMBOL",
|
|
1692
1681
|
"name": "update_expression"
|
|
1693
|
-
},
|
|
1694
|
-
{
|
|
1695
|
-
"type": "SYMBOL",
|
|
1696
|
-
"name": "import_expression"
|
|
1697
1682
|
}
|
|
1698
1683
|
]
|
|
1699
1684
|
},
|
|
@@ -1779,35 +1764,6 @@
|
|
|
1779
1764
|
}
|
|
1780
1765
|
]
|
|
1781
1766
|
},
|
|
1782
|
-
"import_expression": {
|
|
1783
|
-
"type": "PREC",
|
|
1784
|
-
"value": "call",
|
|
1785
|
-
"content": {
|
|
1786
|
-
"type": "SEQ",
|
|
1787
|
-
"members": [
|
|
1788
|
-
{
|
|
1789
|
-
"type": "SYMBOL",
|
|
1790
|
-
"name": "import"
|
|
1791
|
-
},
|
|
1792
|
-
{
|
|
1793
|
-
"type": "STRING",
|
|
1794
|
-
"value": "("
|
|
1795
|
-
},
|
|
1796
|
-
{
|
|
1797
|
-
"type": "FIELD",
|
|
1798
|
-
"name": "source",
|
|
1799
|
-
"content": {
|
|
1800
|
-
"type": "SYMBOL",
|
|
1801
|
-
"name": "expression"
|
|
1802
|
-
}
|
|
1803
|
-
},
|
|
1804
|
-
{
|
|
1805
|
-
"type": "STRING",
|
|
1806
|
-
"value": ")"
|
|
1807
|
-
}
|
|
1808
|
-
]
|
|
1809
|
-
}
|
|
1810
|
-
},
|
|
1811
1767
|
"object": {
|
|
1812
1768
|
"type": "PREC",
|
|
1813
1769
|
"value": "object",
|
|
@@ -3472,27 +3428,6 @@
|
|
|
3472
3428
|
]
|
|
3473
3429
|
}
|
|
3474
3430
|
},
|
|
3475
|
-
"function_forward_declaration": {
|
|
3476
|
-
"type": "SEQ",
|
|
3477
|
-
"members": [
|
|
3478
|
-
{
|
|
3479
|
-
"type": "STRING",
|
|
3480
|
-
"value": "function"
|
|
3481
|
-
},
|
|
3482
|
-
{
|
|
3483
|
-
"type": "FIELD",
|
|
3484
|
-
"name": "name",
|
|
3485
|
-
"content": {
|
|
3486
|
-
"type": "SYMBOL",
|
|
3487
|
-
"name": "identifier"
|
|
3488
|
-
}
|
|
3489
|
-
},
|
|
3490
|
-
{
|
|
3491
|
-
"type": "STRING",
|
|
3492
|
-
"value": ";"
|
|
3493
|
-
}
|
|
3494
|
-
]
|
|
3495
|
-
},
|
|
3496
3431
|
"arrow_function": {
|
|
3497
3432
|
"type": "SEQ",
|
|
3498
3433
|
"members": [
|
|
@@ -4666,10 +4601,6 @@
|
|
|
4666
4601
|
{
|
|
4667
4602
|
"type": "STRING",
|
|
4668
4603
|
"value": "set"
|
|
4669
|
-
},
|
|
4670
|
-
{
|
|
4671
|
-
"type": "STRING",
|
|
4672
|
-
"value": "let"
|
|
4673
4604
|
}
|
|
4674
4605
|
]
|
|
4675
4606
|
},
|
|
@@ -4842,16 +4773,6 @@
|
|
|
4842
4773
|
"value": "object"
|
|
4843
4774
|
}
|
|
4844
4775
|
],
|
|
4845
|
-
[
|
|
4846
|
-
{
|
|
4847
|
-
"type": "SYMBOL",
|
|
4848
|
-
"name": "import_statement"
|
|
4849
|
-
},
|
|
4850
|
-
{
|
|
4851
|
-
"type": "SYMBOL",
|
|
4852
|
-
"name": "import"
|
|
4853
|
-
}
|
|
4854
|
-
],
|
|
4855
4776
|
[
|
|
4856
4777
|
{
|
|
4857
4778
|
"type": "SYMBOL",
|
|
@@ -4984,6 +4905,10 @@
|
|
|
4984
4905
|
"type": "STRING",
|
|
4985
4906
|
"value": "in"
|
|
4986
4907
|
},
|
|
4908
|
+
{
|
|
4909
|
+
"type": "STRING",
|
|
4910
|
+
"value": "let"
|
|
4911
|
+
},
|
|
4987
4912
|
{
|
|
4988
4913
|
"type": "STRING",
|
|
4989
4914
|
"value": "null"
|