Skip to content

Commit 15c5c1c

Browse files
committed
feat: add mcpp.toml syntax highlighting
1 parent eb64724 commit 15c5c1c

5 files changed

Lines changed: 187 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
## 0.2.3
44

5-
- 为精确文件名 `build.mcpp` 增加 C++ 语言关联,复用 VS Code 内置 C++ 高亮和现有模块语法注入;不扩大到所有 `*.mcpp` 文件。
5+
- 为精确文件名 `build.mcpp` 增加 C++ 语言关联,复用 VS Code 内置 C++ 高亮和现有模块
6+
语法注入;不扩大到所有 `*.mcpp` 文件。
7+
- 为精确文件名 `mcpp.toml` 内置独立 TOML 语法高亮,不依赖额外扩展,也不接管普通
8+
`*.toml` 文件。
69

710
## 0.2.2
811

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mcpp CLI 操作;它不实现新的 C++ 语言服务器,也不替代 mcpp 的
1717
| 能力 | LLVM/Clang | GCC | MSVC |
1818
| --- | --- | --- | --- |
1919
| 识别 mcpp 工程 | 支持 | 支持 | 支持 |
20+
| `mcpp.toml` TOML 语法高亮 | 支持 | 支持 | 支持 |
2021
| `build.mcpp``.cppm``.ixx``.mpp``.ccm` 文件关联 | 支持 | 支持 | 支持 |
2122
| `module``export module``import` 语法高亮 | 支持 | 支持 | 支持 |
2223
| 构建、运行、测试、清理命令 | 支持 | 支持 | 支持 |
@@ -78,8 +79,10 @@ xlings 安装。
7879

7980
扩展激活本身不会静默运行 `mcpp build`,也不会自动下载、安装或切换工具链。
8081

81-
### C++ 模块语法高亮
82+
### 语法高亮
8283

84+
- 将精确文件名 `mcpp.toml` 识别为独立的 mcpp TOML 语言,内置表、键、字符串、数字、
85+
布尔、日期时间和注释高亮。
8386
-`build.mcpp``.cppm``.ixx``.mpp``.ccm` 关联到 VS Code 内置 `cpp` 语言。
8487
-`source.cpp` 注入模块语法规则。
8588
- 覆盖 `module``export module``import``export import`、模块名和模块分区。

package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@
132132
}
133133
}
134134
},
135+
"languages": [
136+
{
137+
"id": "mcpp-toml",
138+
"aliases": [
139+
"mcpp TOML",
140+
"mcpp.toml"
141+
],
142+
"filenames": [
143+
"mcpp.toml"
144+
]
145+
}
146+
],
135147
"configurationDefaults": {
136148
"files.associations": {
137149
"build.mcpp": "cpp",
@@ -142,6 +154,11 @@
142154
}
143155
},
144156
"grammars": [
157+
{
158+
"language": "mcpp-toml",
159+
"scopeName": "source.toml.mcpp",
160+
"path": "./syntaxes/mcpp-toml.tmLanguage.json"
161+
},
145162
{
146163
"scopeName": "source.cpp.mcpp-modules",
147164
"injectTo": [

syntaxes/mcpp-toml.tmLanguage.json

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3+
"name": "mcpp TOML",
4+
"scopeName": "source.toml.mcpp",
5+
"patterns": [
6+
{
7+
"include": "#comment"
8+
},
9+
{
10+
"include": "#table"
11+
},
12+
{
13+
"include": "#key"
14+
},
15+
{
16+
"include": "#string"
17+
},
18+
{
19+
"include": "#datetime"
20+
},
21+
{
22+
"include": "#number"
23+
},
24+
{
25+
"include": "#boolean"
26+
},
27+
{
28+
"include": "#punctuation"
29+
}
30+
],
31+
"repository": {
32+
"comment": {
33+
"match": "#.*$",
34+
"name": "comment.line.number-sign.toml"
35+
},
36+
"table": {
37+
"match": "^\\s*(\\[\\[?)([^\\]\\r\\n]+?)(\\]\\]?)\\s*(?=#|$)",
38+
"captures": {
39+
"1": {
40+
"name": "punctuation.definition.table.begin.toml"
41+
},
42+
"2": {
43+
"name": "entity.name.section.toml"
44+
},
45+
"3": {
46+
"name": "punctuation.definition.table.end.toml"
47+
}
48+
}
49+
},
50+
"key": {
51+
"match": "^\\s*((?:[A-Za-z0-9_-]+|\"[^\"]+\"|'[^']+')(?:\\s*\\.\\s*(?:[A-Za-z0-9_-]+|\"[^\"]+\"|'[^']+'))*)\\s*(=)",
52+
"captures": {
53+
"1": {
54+
"name": "variable.other.key.toml"
55+
},
56+
"2": {
57+
"name": "keyword.operator.assignment.toml"
58+
}
59+
}
60+
},
61+
"string": {
62+
"patterns": [
63+
{
64+
"begin": "\"\"\"",
65+
"end": "\"\"\"",
66+
"name": "string.quoted.triple.basic.toml",
67+
"patterns": [
68+
{
69+
"include": "#escape"
70+
}
71+
]
72+
},
73+
{
74+
"begin": "'''",
75+
"end": "'''",
76+
"name": "string.quoted.triple.literal.toml"
77+
},
78+
{
79+
"begin": "\"",
80+
"end": "\"",
81+
"name": "string.quoted.double.toml",
82+
"patterns": [
83+
{
84+
"include": "#escape"
85+
}
86+
]
87+
},
88+
{
89+
"begin": "'",
90+
"end": "'",
91+
"name": "string.quoted.single.toml"
92+
}
93+
]
94+
},
95+
"escape": {
96+
"match": "\\\\(?:[btnfr\"\\\\]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})",
97+
"name": "constant.character.escape.toml"
98+
},
99+
"datetime": {
100+
"match": "(?<![A-Za-z0-9_-])(?:\\d{4}-\\d{2}-\\d{2}(?:[Tt ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:[Zz]|[+-]\\d{2}:\\d{2})?)?|\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?)(?![A-Za-z0-9_-])",
101+
"name": "constant.other.datetime.toml"
102+
},
103+
"number": {
104+
"match": "(?<![A-Za-z0-9_-])[-+]?(?:0x[0-9A-Fa-f](?:_?[0-9A-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:\\d(?:_?\\d)*)(?:\\.\\d(?:_?\\d)*)?(?:[eE][-+]?\\d(?:_?\\d)*)?|inf|nan)(?![A-Za-z0-9_-])",
105+
"name": "constant.numeric.toml"
106+
},
107+
"boolean": {
108+
"match": "(?<![A-Za-z0-9_-])(?:true|false)(?![A-Za-z0-9_-])",
109+
"name": "constant.language.boolean.toml"
110+
},
111+
"punctuation": {
112+
"match": "[\\[\\]{},.]",
113+
"name": "punctuation.separator.toml"
114+
}
115+
}
116+
}

test/artifacts.test.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ interface PackageManifest {
1616
commands?: Array<{ command: string }>;
1717
configuration?: { properties?: Record<string, unknown> };
1818
configurationDefaults?: Record<string, unknown>;
19-
grammars?: Array<{ scopeName: string; injectTo?: string[]; path: string }>;
19+
languages?: Array<{ id: string; aliases?: string[]; filenames?: string[] }>;
20+
grammars?: Array<{ language?: string; scopeName: string; injectTo?: string[]; path: string }>;
2021
};
2122
}
2223

@@ -70,6 +71,50 @@ test("associates the build.mcpp file with the C++ language", () => {
7071
assert.equal(associations?.["*.mcpp"], undefined);
7172
});
7273

74+
test("ships TOML highlighting for the exact mcpp.toml filename", () => {
75+
const manifest = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")) as PackageManifest;
76+
const language = manifest.contributes?.languages?.find((item) => item.id === "mcpp-toml");
77+
assert.deepEqual(language, {
78+
id: "mcpp-toml",
79+
aliases: ["mcpp TOML", "mcpp.toml"],
80+
filenames: ["mcpp.toml"],
81+
});
82+
83+
const grammar = manifest.contributes?.grammars?.find((item) => item.language === "mcpp-toml");
84+
assert.deepEqual(grammar, {
85+
language: "mcpp-toml",
86+
scopeName: "source.toml.mcpp",
87+
path: "./syntaxes/mcpp-toml.tmLanguage.json",
88+
});
89+
90+
const grammarText = readFileSync(path.join(root, "syntaxes/mcpp-toml.tmLanguage.json"), "utf8");
91+
const grammarDocument = JSON.parse(grammarText) as {
92+
repository?: Record<string, { match?: string }>;
93+
};
94+
for (const key of ["comment", "table", "key", "string", "datetime", "number", "boolean", "punctuation"]) {
95+
assert.ok(grammarDocument.repository?.[key], `missing TOML grammar rule: ${key}`);
96+
}
97+
98+
const tablePattern = new RegExp(grammarDocument.repository?.table.match ?? "");
99+
assert.match("[package]", tablePattern);
100+
assert.match("[[target.generated]]", tablePattern);
101+
102+
const keyPattern = new RegExp(grammarDocument.repository?.key.match ?? "");
103+
assert.match('standard = "c++23"', keyPattern);
104+
assert.match('"quoted.key" = true', keyPattern);
105+
106+
for (const scope of [
107+
"comment.line.number-sign.toml",
108+
"entity.name.section.toml",
109+
"variable.other.key.toml",
110+
"string.quoted.double.toml",
111+
"constant.numeric.toml",
112+
"constant.language.boolean.toml",
113+
]) {
114+
assert.match(grammarText, new RegExp(scope.replaceAll(".", "\\.")));
115+
}
116+
});
117+
73118
test("ships an injection grammar with module-specific scopes", () => {
74119
const manifest = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")) as PackageManifest;
75120
const grammar = manifest.contributes?.grammars?.find((item) => item.scopeName === "source.cpp.mcpp-modules");

0 commit comments

Comments
 (0)