garlic-vscode 0.1.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/.vscode/launch.json +16 -0
- package/.vscode/tasks.json +13 -0
- package/.vscodeignore +5 -0
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/examples/add.srk +11 -0
- package/language-configuration.json +110 -0
- package/package.json +72 -0
- package/src/extension.ts +61 -0
- package/syntaxes/garlic.tmLanguage.json +104 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"args": [
|
|
6
|
+
"--extensionDevelopmentPath=${workspaceFolder}"
|
|
7
|
+
],
|
|
8
|
+
"name": "Launch Extension",
|
|
9
|
+
"outFiles": [
|
|
10
|
+
"${workspaceFolder}/out/**/*.js"
|
|
11
|
+
],
|
|
12
|
+
"request": "launch",
|
|
13
|
+
"type": "extensionHost"
|
|
14
|
+
},
|
|
15
|
+
]
|
|
16
|
+
}
|
package/.vscodeignore
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FallingShrimp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# garlic-vscode
|
|
2
|
+
|
|
3
|
+
## **这个文档是AI写的!!!**
|
|
4
|
+
|
|
5
|
+
[Garlic](https://github.com/Shrimp-VM/garlic-language) DSL 的 VSCode 扩展,为 ShrimpVM 的 `.srk` 脚本提供语言支持。
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
- **语法高亮**:TextMate 语法定义(`source.garlic`)
|
|
10
|
+
- **智能补全**:节点名、属性键、值、数组槽位按上下文精准补全
|
|
11
|
+
- **Hover 文档**:节点与属性的说明
|
|
12
|
+
- **实时诊断**:基于 Godot 侧 structuredErrors 的语法错误提示
|
|
13
|
+
|
|
14
|
+
## 前置条件
|
|
15
|
+
|
|
16
|
+
语言服务器运行在 Godot 编辑器进程内(由 ShrimpVM 插件自动启动),因此使用本扩展前需要:
|
|
17
|
+
|
|
18
|
+
1. 用 Godot 4.6 打开启用了 ShrimpVM 插件的项目
|
|
19
|
+
2. 确认 LSP 监听 `127.0.0.1:6009`(可在 ProjectSettings `shrimpvm/garlic/lsp_port` 修改)
|
|
20
|
+
|
|
21
|
+
扩展与服务器之间是 LSP base protocol 经 TCP 的字节透传,无需额外进程。
|
|
22
|
+
|
|
23
|
+
## 使用
|
|
24
|
+
|
|
25
|
+
### 开发调试
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install
|
|
29
|
+
npm run compile
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
用 VSCode 打开本文件夹,按 `F5` 启动扩展开发宿主,打开任意 `.srk` 文件即可。
|
|
33
|
+
|
|
34
|
+
### 打包安装
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx @vscode/vsce package
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
安装生成的 `.vsix`,打开 `.srk` 文件即生效。
|
|
41
|
+
|
|
42
|
+
## 设置
|
|
43
|
+
|
|
44
|
+
| 配置项 | 默认值 | 说明 |
|
|
45
|
+
|------------------|-------------|------------------------------------|
|
|
46
|
+
| `garlicLsp.host` | `127.0.0.1` | LSP 服务器所在主机(Godot 编辑器) |
|
|
47
|
+
| `garlicLsp.port` | `6009` | LSP 服务器 TCP 端口 |
|
|
48
|
+
|
|
49
|
+
修改配置后扩展会自动重启语言客户端;连接失败时按 1 秒间隔重试 5 次,适配 Godot 编辑器启动慢于 VSCode 的场景。
|
|
50
|
+
|
|
51
|
+
## 目录结构
|
|
52
|
+
|
|
53
|
+
```plain
|
|
54
|
+
src/extension.ts 客户端入口:TCP 连接、重试、配置变更自动重启
|
|
55
|
+
syntaxes/garlic.tmLanguage.json TextMate 语法
|
|
56
|
+
language-configuration.json 括号配对、注释、自动缩进规则
|
|
57
|
+
examples/add.srk 示例脚本
|
|
58
|
+
```
|
package/examples/add.srk
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"comments": {
|
|
3
|
+
"blockComment": [
|
|
4
|
+
"<",
|
|
5
|
+
">"
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"brackets": [
|
|
9
|
+
[
|
|
10
|
+
"(",
|
|
11
|
+
")"
|
|
12
|
+
],
|
|
13
|
+
[
|
|
14
|
+
"{",
|
|
15
|
+
"}"
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"[",
|
|
19
|
+
"]"
|
|
20
|
+
]
|
|
21
|
+
],
|
|
22
|
+
"autoClosingPairs": [
|
|
23
|
+
{
|
|
24
|
+
"open": "(",
|
|
25
|
+
"close": ")"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"open": "{",
|
|
29
|
+
"close": "}"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"open": "[",
|
|
33
|
+
"close": "]"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"open": "\"",
|
|
37
|
+
"close": "\"",
|
|
38
|
+
"notIn": [
|
|
39
|
+
"string",
|
|
40
|
+
"comment"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"open": "'",
|
|
45
|
+
"close": "'",
|
|
46
|
+
"notIn": [
|
|
47
|
+
"string",
|
|
48
|
+
"comment"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"open": "“",
|
|
53
|
+
"close": "”",
|
|
54
|
+
"notIn": [
|
|
55
|
+
"string",
|
|
56
|
+
"comment"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"open": "`",
|
|
61
|
+
"close": "`",
|
|
62
|
+
"notIn": [
|
|
63
|
+
"string",
|
|
64
|
+
"comment"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"open": "「",
|
|
69
|
+
"close": "」",
|
|
70
|
+
"notIn": [
|
|
71
|
+
"string",
|
|
72
|
+
"comment"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"surroundingPairs": [
|
|
77
|
+
[
|
|
78
|
+
"(",
|
|
79
|
+
")"
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
"{",
|
|
83
|
+
"}"
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
"[",
|
|
87
|
+
"]"
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"\"",
|
|
91
|
+
"\""
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
"'",
|
|
95
|
+
"'"
|
|
96
|
+
],
|
|
97
|
+
[
|
|
98
|
+
"“",
|
|
99
|
+
"”"
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
"`",
|
|
103
|
+
"`"
|
|
104
|
+
],
|
|
105
|
+
[
|
|
106
|
+
"「",
|
|
107
|
+
"」"
|
|
108
|
+
]
|
|
109
|
+
]
|
|
110
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "garlic-vscode",
|
|
3
|
+
"displayName": "Garlic",
|
|
4
|
+
"description": "Garlic DSL language support for ShrimpVM (.srk)",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"publisher": "Rundll86",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Rundll86/garlic-vscode"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"vscode": "^1.138.0"
|
|
14
|
+
},
|
|
15
|
+
"categories": [
|
|
16
|
+
"Programming Languages"
|
|
17
|
+
],
|
|
18
|
+
"activationEvents": [],
|
|
19
|
+
"main": "./out/extension.js",
|
|
20
|
+
"contributes": {
|
|
21
|
+
"languages": [
|
|
22
|
+
{
|
|
23
|
+
"id": "garlic",
|
|
24
|
+
"aliases": [
|
|
25
|
+
"Garlic",
|
|
26
|
+
"garlic"
|
|
27
|
+
],
|
|
28
|
+
"extensions": [
|
|
29
|
+
".srk"
|
|
30
|
+
],
|
|
31
|
+
"configuration": "./language-configuration.json"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"grammars": [
|
|
35
|
+
{
|
|
36
|
+
"language": "garlic",
|
|
37
|
+
"scopeName": "source.garlic",
|
|
38
|
+
"path": "./syntaxes/garlic.tmLanguage.json"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"configuration": {
|
|
42
|
+
"title": "Garlic",
|
|
43
|
+
"properties": {
|
|
44
|
+
"garlicLsp.host": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"default": "127.0.0.1",
|
|
47
|
+
"description": "Host running the Garlic LSP server (inside the Godot editor)."
|
|
48
|
+
},
|
|
49
|
+
"garlicLsp.port": {
|
|
50
|
+
"type": "number",
|
|
51
|
+
"default": 6009,
|
|
52
|
+
"description": "TCP port of the Garlic LSP server."
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"compile": "tsc",
|
|
59
|
+
"watch": "tsc -watch",
|
|
60
|
+
"prepublishOnly": "run-s vscode:prepublish",
|
|
61
|
+
"vscode:prepublish": "run-s compile"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"vscode-languageclient": "^9.0.1"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/node": "^20.19.43",
|
|
68
|
+
"@types/vscode": "^1.138.0",
|
|
69
|
+
"npm-run-all": "^4.1.5",
|
|
70
|
+
"typescript": "^5.9.3"
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/extension.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import * as vscode from 'vscode';
|
|
3
|
+
import { LanguageClient, LanguageClientOptions, ServerOptions, StreamInfo } from 'vscode-languageclient/node';
|
|
4
|
+
|
|
5
|
+
let client: LanguageClient | undefined;
|
|
6
|
+
let restarting = false;
|
|
7
|
+
|
|
8
|
+
export function activate(context: vscode.ExtensionContext) {
|
|
9
|
+
client = createClient();
|
|
10
|
+
context.subscriptions.push(client);
|
|
11
|
+
client.start();
|
|
12
|
+
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((event: vscode.ConfigurationChangeEvent) => {
|
|
13
|
+
if (event.affectsConfiguration('garlicLsp.host') || event.affectsConfiguration('garlicLsp.port')) {
|
|
14
|
+
restart(context);
|
|
15
|
+
}
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function restart(context: vscode.ExtensionContext) {
|
|
20
|
+
if (restarting) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
restarting = true;
|
|
24
|
+
try {
|
|
25
|
+
await client?.stop();
|
|
26
|
+
client = createClient();
|
|
27
|
+
context.subscriptions.push(client);
|
|
28
|
+
client.start();
|
|
29
|
+
} finally {
|
|
30
|
+
restarting = false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createClient(): LanguageClient {
|
|
35
|
+
const config = vscode.workspace.getConfiguration('garlicLsp');
|
|
36
|
+
const host = config.get<string>('host', '127.0.0.1');
|
|
37
|
+
const port = config.get<number>('port', 6009);
|
|
38
|
+
const serverOptions: ServerOptions = async (): Promise<StreamInfo> => {
|
|
39
|
+
let lastError: unknown;
|
|
40
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
41
|
+
try {
|
|
42
|
+
return await new Promise<StreamInfo>((resolve, reject) => {
|
|
43
|
+
const socket = net.connect({ host, port }, () => resolve({ reader: socket, writer: socket }));
|
|
44
|
+
socket.on('error', reject);
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
lastError = error;
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw lastError ?? new Error(`cannot connect to Garlic LSP at ${host}:${port}`);
|
|
52
|
+
};
|
|
53
|
+
const clientOptions: LanguageClientOptions = {
|
|
54
|
+
documentSelector: [{ language: 'garlic' }]
|
|
55
|
+
};
|
|
56
|
+
return new LanguageClient('garlicLsp', 'Garlic LSP', serverOptions, clientOptions);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function deactivate(): Thenable<void> | undefined {
|
|
60
|
+
return client?.stop();
|
|
61
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
|
3
|
+
"name": "Garlic",
|
|
4
|
+
"scopeName": "source.garlic",
|
|
5
|
+
"patterns": [
|
|
6
|
+
{
|
|
7
|
+
"include": "#comment"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"include": "#stringname"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"include": "#strings"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"include": "#node"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"include": "#attribute"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"include": "#number"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"include": "#boolean"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"include": "#punctuation"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"comment": {
|
|
33
|
+
"begin": "<",
|
|
34
|
+
"end": ">",
|
|
35
|
+
"name": "comment.block.garlic",
|
|
36
|
+
"patterns": [
|
|
37
|
+
{
|
|
38
|
+
"include": "#comment"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"strings": {
|
|
43
|
+
"patterns": [
|
|
44
|
+
{
|
|
45
|
+
"begin": "\"",
|
|
46
|
+
"end": "\"",
|
|
47
|
+
"name": "string.quoted.double.garlic",
|
|
48
|
+
"patterns": [
|
|
49
|
+
{
|
|
50
|
+
"match": "\\\\.",
|
|
51
|
+
"name": "constant.character.escape.garlic"
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"begin": "'",
|
|
57
|
+
"end": "'",
|
|
58
|
+
"name": "string.quoted.single.garlic",
|
|
59
|
+
"patterns": [
|
|
60
|
+
{
|
|
61
|
+
"match": "\\\\.",
|
|
62
|
+
"name": "constant.character.escape.garlic"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"begin": "“",
|
|
68
|
+
"end": "”",
|
|
69
|
+
"name": "string.quoted.other.garlic"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"begin": "`",
|
|
73
|
+
"end": "`",
|
|
74
|
+
"name": "string.quoted.other.garlic"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"stringname": {
|
|
79
|
+
"begin": "「",
|
|
80
|
+
"end": "」",
|
|
81
|
+
"name": "string.quoted.stringname.garlic"
|
|
82
|
+
},
|
|
83
|
+
"node": {
|
|
84
|
+
"match": "\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()",
|
|
85
|
+
"name": "entity.name.function.garlic"
|
|
86
|
+
},
|
|
87
|
+
"attribute": {
|
|
88
|
+
"match": "\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*=)",
|
|
89
|
+
"name": "entity.other.attribute-name.garlic"
|
|
90
|
+
},
|
|
91
|
+
"number": {
|
|
92
|
+
"match": "-?\\b\\d+(\\.\\d+)?\\b",
|
|
93
|
+
"name": "constant.numeric.garlic"
|
|
94
|
+
},
|
|
95
|
+
"boolean": {
|
|
96
|
+
"match": "\\b(true|false)\\b",
|
|
97
|
+
"name": "constant.language.garlic"
|
|
98
|
+
},
|
|
99
|
+
"punctuation": {
|
|
100
|
+
"match": "[()\\[\\]{},=;]",
|
|
101
|
+
"name": "punctuation.separator.garlic"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "commonjs",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": [
|
|
6
|
+
"ES2022"
|
|
7
|
+
],
|
|
8
|
+
"outDir": "out",
|
|
9
|
+
"rootDir": "src",
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"skipLibCheck": true
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"src"
|
|
17
|
+
]
|
|
18
|
+
}
|