kimchilang 1.0.1
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/.github/workflows/ci.yml +66 -0
- package/README.md +1547 -0
- package/create-kimchi-app/README.md +44 -0
- package/create-kimchi-app/index.js +214 -0
- package/create-kimchi-app/package.json +22 -0
- package/editors/README.md +121 -0
- package/editors/sublime/KimchiLang.sublime-syntax +138 -0
- package/editors/vscode/README.md +90 -0
- package/editors/vscode/kimchilang-1.1.0.vsix +0 -0
- package/editors/vscode/language-configuration.json +37 -0
- package/editors/vscode/package.json +55 -0
- package/editors/vscode/src/extension.js +354 -0
- package/editors/vscode/syntaxes/kimchi.tmLanguage.json +215 -0
- package/examples/api/client.km +36 -0
- package/examples/async_pipe.km +58 -0
- package/examples/basic.kimchi +109 -0
- package/examples/cli_framework/README.md +92 -0
- package/examples/cli_framework/calculator.km +61 -0
- package/examples/cli_framework/deploy.km +126 -0
- package/examples/cli_framework/greeter.km +26 -0
- package/examples/config.static +27 -0
- package/examples/config.static.js +10 -0
- package/examples/env_test.km +37 -0
- package/examples/fibonacci.kimchi +17 -0
- package/examples/greeter.km +15 -0
- package/examples/hello.js +1 -0
- package/examples/hello.kimchi +3 -0
- package/examples/js_interop.km +42 -0
- package/examples/logger_example.km +34 -0
- package/examples/memo_fibonacci.km +17 -0
- package/examples/myapp/lib/http.js +14 -0
- package/examples/myapp/lib/http.km +16 -0
- package/examples/myapp/main.km +16 -0
- package/examples/myapp/main_with_mock.km +42 -0
- package/examples/myapp/services/api.js +18 -0
- package/examples/myapp/services/api.km +18 -0
- package/examples/new_features.kimchi +52 -0
- package/examples/project_example.static +20 -0
- package/examples/readme_examples.km +240 -0
- package/examples/reduce_pattern_match.km +85 -0
- package/examples/regex_match.km +46 -0
- package/examples/sample.js +45 -0
- package/examples/sample.km +39 -0
- package/examples/secrets.static +35 -0
- package/examples/secrets.static.js +30 -0
- package/examples/shell-example.mjs +144 -0
- package/examples/shell_example.km +19 -0
- package/examples/stdlib_test.km +22 -0
- package/examples/test_example.km +69 -0
- package/examples/testing/README.md +88 -0
- package/examples/testing/http_client.km +18 -0
- package/examples/testing/math.km +48 -0
- package/examples/testing/math.test.km +93 -0
- package/examples/testing/user_service.km +29 -0
- package/examples/testing/user_service.test.km +72 -0
- package/examples/use-config.mjs +141 -0
- package/examples/use_config.km +13 -0
- package/install.sh +59 -0
- package/package.json +29 -0
- package/pantry/acorn/index.km +1 -0
- package/pantry/is_number/index.km +1 -0
- package/pantry/is_odd/index.km +2 -0
- package/project.static +6 -0
- package/src/cli.js +1245 -0
- package/src/generator.js +1241 -0
- package/src/index.js +141 -0
- package/src/js2km.js +568 -0
- package/src/lexer.js +822 -0
- package/src/linter.js +810 -0
- package/src/package-manager.js +307 -0
- package/src/parser.js +1876 -0
- package/src/static-parser.js +500 -0
- package/src/typechecker.js +950 -0
- package/stdlib/array.km +0 -0
- package/stdlib/bitwise.km +38 -0
- package/stdlib/console.km +49 -0
- package/stdlib/date.km +97 -0
- package/stdlib/function.km +44 -0
- package/stdlib/http.km +197 -0
- package/stdlib/http.md +333 -0
- package/stdlib/index.km +26 -0
- package/stdlib/json.km +17 -0
- package/stdlib/logger.js +114 -0
- package/stdlib/logger.km +104 -0
- package/stdlib/math.km +120 -0
- package/stdlib/object.km +41 -0
- package/stdlib/promise.km +33 -0
- package/stdlib/string.km +93 -0
- package/stdlib/testing.md +265 -0
- package/test/test.js +599 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kimchilang",
|
|
3
|
+
"displayName": "KimchiLang",
|
|
4
|
+
"description": "Syntax highlighting, error checking, and language support for KimchiLang",
|
|
5
|
+
"version": "1.1.0",
|
|
6
|
+
"publisher": "kimchilang",
|
|
7
|
+
"engines": {
|
|
8
|
+
"vscode": "^1.60.0"
|
|
9
|
+
},
|
|
10
|
+
"categories": [
|
|
11
|
+
"Programming Languages",
|
|
12
|
+
"Linters"
|
|
13
|
+
],
|
|
14
|
+
"activationEvents": [
|
|
15
|
+
"onLanguage:kimchi"
|
|
16
|
+
],
|
|
17
|
+
"main": "./src/extension.js",
|
|
18
|
+
"contributes": {
|
|
19
|
+
"languages": [
|
|
20
|
+
{
|
|
21
|
+
"id": "kimchi",
|
|
22
|
+
"aliases": ["KimchiLang", "kimchi"],
|
|
23
|
+
"extensions": [".km", ".kimchi", ".kc", ".static"],
|
|
24
|
+
"configuration": "./language-configuration.json"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"grammars": [
|
|
28
|
+
{
|
|
29
|
+
"language": "kimchi",
|
|
30
|
+
"scopeName": "source.kimchi",
|
|
31
|
+
"path": "./syntaxes/kimchi.tmLanguage.json"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"configuration": {
|
|
35
|
+
"title": "KimchiLang",
|
|
36
|
+
"properties": {
|
|
37
|
+
"kimchi.validateOnSave": {
|
|
38
|
+
"type": "boolean",
|
|
39
|
+
"default": true,
|
|
40
|
+
"description": "Validate KimchiLang files on save"
|
|
41
|
+
},
|
|
42
|
+
"kimchi.validateOnChange": {
|
|
43
|
+
"type": "boolean",
|
|
44
|
+
"default": true,
|
|
45
|
+
"description": "Validate KimchiLang files as you type"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "https://github.com/kimchilang/kimchilang"
|
|
53
|
+
},
|
|
54
|
+
"license": "MIT"
|
|
55
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
const vscode = require('vscode');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
|
|
5
|
+
let diagnosticCollection;
|
|
6
|
+
|
|
7
|
+
function activate(context) {
|
|
8
|
+
console.log('KimchiLang extension activated');
|
|
9
|
+
|
|
10
|
+
// Create diagnostic collection for showing errors
|
|
11
|
+
diagnosticCollection = vscode.languages.createDiagnosticCollection('kimchi');
|
|
12
|
+
context.subscriptions.push(diagnosticCollection);
|
|
13
|
+
|
|
14
|
+
// Validate on document open
|
|
15
|
+
context.subscriptions.push(
|
|
16
|
+
vscode.workspace.onDidOpenTextDocument(validateDocument)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Validate on document save
|
|
20
|
+
context.subscriptions.push(
|
|
21
|
+
vscode.workspace.onDidSaveTextDocument(validateDocument)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Validate on document change (with debounce)
|
|
25
|
+
let timeout;
|
|
26
|
+
context.subscriptions.push(
|
|
27
|
+
vscode.workspace.onDidChangeTextDocument(event => {
|
|
28
|
+
clearTimeout(timeout);
|
|
29
|
+
timeout = setTimeout(() => validateDocument(event.document), 500);
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Validate all open kimchi documents on activation
|
|
34
|
+
vscode.workspace.textDocuments.forEach(validateDocument);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function deactivate() {
|
|
38
|
+
if (diagnosticCollection) {
|
|
39
|
+
diagnosticCollection.dispose();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function validateDocument(document) {
|
|
44
|
+
// Only validate kimchi files
|
|
45
|
+
if (!isKimchiFile(document)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const text = document.getText();
|
|
50
|
+
const uri = document.uri;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const errors = await runKimchiCheck(text, document.fileName);
|
|
54
|
+
const diagnostics = errors.map(error => createDiagnostic(error, document));
|
|
55
|
+
diagnosticCollection.set(uri, diagnostics);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('KimchiLang validation error:', err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function isKimchiFile(document) {
|
|
62
|
+
const ext = path.extname(document.fileName);
|
|
63
|
+
return ['.km', '.kimchi', '.kc', '.static'].includes(ext);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function runKimchiCheck(source, filePath) {
|
|
67
|
+
return new Promise((resolve) => {
|
|
68
|
+
// Try to find kimchi CLI
|
|
69
|
+
const kimchiPath = findKimchiCli(filePath);
|
|
70
|
+
|
|
71
|
+
if (!kimchiPath) {
|
|
72
|
+
// Fall back to inline validation
|
|
73
|
+
resolve(validateInline(source, filePath));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Write source to a temp file for the check command
|
|
78
|
+
const fs = require('fs');
|
|
79
|
+
const os = require('os');
|
|
80
|
+
const tempFile = path.join(os.tmpdir(), `kimchi_check_${Date.now()}.km`);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
fs.writeFileSync(tempFile, source);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
resolve(validateInline(source, filePath));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Run: node src/cli.js check <tempfile>
|
|
90
|
+
const proc = spawn('node', [kimchiPath, 'check', tempFile], {
|
|
91
|
+
cwd: path.dirname(kimchiPath).replace(/\/src$/, ''),
|
|
92
|
+
env: { ...process.env },
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
let stdout = '';
|
|
96
|
+
let stderr = '';
|
|
97
|
+
|
|
98
|
+
proc.stdout.on('data', (data) => {
|
|
99
|
+
stdout += data.toString();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
proc.stderr.on('data', (data) => {
|
|
103
|
+
stderr += data.toString();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
proc.on('close', (code) => {
|
|
107
|
+
// Clean up temp file
|
|
108
|
+
try { fs.unlinkSync(tempFile); } catch {}
|
|
109
|
+
|
|
110
|
+
const output = stdout + stderr;
|
|
111
|
+
if (output) {
|
|
112
|
+
try {
|
|
113
|
+
const result = JSON.parse(output);
|
|
114
|
+
resolve(result.errors || result || []);
|
|
115
|
+
} catch {
|
|
116
|
+
resolve(parseErrorOutput(output));
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
resolve([]);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
proc.on('error', () => {
|
|
124
|
+
try { fs.unlinkSync(tempFile); } catch {}
|
|
125
|
+
resolve(validateInline(source, filePath));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function findKimchiCli(filePath) {
|
|
131
|
+
const fs = require('fs');
|
|
132
|
+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath));
|
|
133
|
+
|
|
134
|
+
if (workspaceFolder) {
|
|
135
|
+
const wsPath = workspaceFolder.uri.fsPath;
|
|
136
|
+
|
|
137
|
+
// Try src/cli.js (KimchiLang project structure)
|
|
138
|
+
const srcCli = path.join(wsPath, 'src', 'cli.js');
|
|
139
|
+
if (fs.existsSync(srcCli)) {
|
|
140
|
+
return srcCli;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Try node_modules/.bin/kimchi
|
|
144
|
+
const localKimchi = path.join(wsPath, 'node_modules', '.bin', 'kimchi');
|
|
145
|
+
if (fs.existsSync(localKimchi)) {
|
|
146
|
+
return localKimchi;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Try global kimchi
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function validateInline(source, filePath) {
|
|
155
|
+
const errors = [];
|
|
156
|
+
|
|
157
|
+
// Try to import the compiler modules
|
|
158
|
+
try {
|
|
159
|
+
// Look for the compiler in the workspace
|
|
160
|
+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath));
|
|
161
|
+
let compilerPath;
|
|
162
|
+
|
|
163
|
+
if (workspaceFolder) {
|
|
164
|
+
compilerPath = path.join(workspaceFolder.uri.fsPath, 'src', 'index.js');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// This is a simplified inline check - parse errors only
|
|
168
|
+
// For full validation, the CLI should be used
|
|
169
|
+
const lines = source.split('\n');
|
|
170
|
+
|
|
171
|
+
// Check for common syntax issues
|
|
172
|
+
let braceCount = 0;
|
|
173
|
+
let bracketCount = 0;
|
|
174
|
+
let parenCount = 0;
|
|
175
|
+
let inString = false;
|
|
176
|
+
let stringChar = '';
|
|
177
|
+
|
|
178
|
+
for (let lineNum = 0; lineNum < lines.length; lineNum++) {
|
|
179
|
+
const line = lines[lineNum];
|
|
180
|
+
|
|
181
|
+
for (let col = 0; col < line.length; col++) {
|
|
182
|
+
const char = line[col];
|
|
183
|
+
const prevChar = col > 0 ? line[col - 1] : '';
|
|
184
|
+
|
|
185
|
+
// Track string state
|
|
186
|
+
if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
|
|
187
|
+
if (!inString) {
|
|
188
|
+
inString = true;
|
|
189
|
+
stringChar = char;
|
|
190
|
+
} else if (char === stringChar) {
|
|
191
|
+
inString = false;
|
|
192
|
+
stringChar = '';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!inString) {
|
|
197
|
+
if (char === '{') braceCount++;
|
|
198
|
+
if (char === '}') braceCount--;
|
|
199
|
+
if (char === '[') bracketCount++;
|
|
200
|
+
if (char === ']') bracketCount--;
|
|
201
|
+
if (char === '(') parenCount++;
|
|
202
|
+
if (char === ')') parenCount--;
|
|
203
|
+
|
|
204
|
+
// Check for unbalanced closing
|
|
205
|
+
if (braceCount < 0) {
|
|
206
|
+
errors.push({
|
|
207
|
+
line: lineNum + 1,
|
|
208
|
+
column: col + 1,
|
|
209
|
+
message: 'Unexpected closing brace }',
|
|
210
|
+
});
|
|
211
|
+
braceCount = 0;
|
|
212
|
+
}
|
|
213
|
+
if (bracketCount < 0) {
|
|
214
|
+
errors.push({
|
|
215
|
+
line: lineNum + 1,
|
|
216
|
+
column: col + 1,
|
|
217
|
+
message: 'Unexpected closing bracket ]',
|
|
218
|
+
});
|
|
219
|
+
bracketCount = 0;
|
|
220
|
+
}
|
|
221
|
+
if (parenCount < 0) {
|
|
222
|
+
errors.push({
|
|
223
|
+
line: lineNum + 1,
|
|
224
|
+
column: col + 1,
|
|
225
|
+
message: 'Unexpected closing parenthesis )',
|
|
226
|
+
});
|
|
227
|
+
parenCount = 0;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check for unclosed string on line
|
|
233
|
+
if (inString && stringChar !== '`') {
|
|
234
|
+
errors.push({
|
|
235
|
+
line: lineNum + 1,
|
|
236
|
+
column: line.length,
|
|
237
|
+
message: `Unclosed string literal`,
|
|
238
|
+
});
|
|
239
|
+
inString = false;
|
|
240
|
+
stringChar = '';
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Check for unclosed braces at end
|
|
245
|
+
if (braceCount > 0) {
|
|
246
|
+
errors.push({
|
|
247
|
+
line: lines.length,
|
|
248
|
+
column: 1,
|
|
249
|
+
message: `Unclosed brace: ${braceCount} opening { without matching }`,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
if (bracketCount > 0) {
|
|
253
|
+
errors.push({
|
|
254
|
+
line: lines.length,
|
|
255
|
+
column: 1,
|
|
256
|
+
message: `Unclosed bracket: ${bracketCount} opening [ without matching ]`,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
if (parenCount > 0) {
|
|
260
|
+
errors.push({
|
|
261
|
+
line: lines.length,
|
|
262
|
+
column: 1,
|
|
263
|
+
message: `Unclosed parenthesis: ${parenCount} opening ( without matching )`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
} catch (err) {
|
|
268
|
+
// Ignore import errors
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return errors;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function parseErrorOutput(output) {
|
|
275
|
+
const errors = [];
|
|
276
|
+
|
|
277
|
+
if (!output) return errors;
|
|
278
|
+
|
|
279
|
+
// Parse error messages in various formats
|
|
280
|
+
// Format 1: "Error at line:column: message"
|
|
281
|
+
// Format 2: "Parse Error at line:column: message"
|
|
282
|
+
// Format 3: "Type Error: message"
|
|
283
|
+
// Format 4: "Lint Error [rule]: message"
|
|
284
|
+
|
|
285
|
+
const patterns = [
|
|
286
|
+
/(?:Parse |Lexer |Type |Compile |Lint )?Error(?: \[[\w-]+\])? at (\d+):(\d+):\s*(.+)/gi,
|
|
287
|
+
/(\d+):(\d+):\s*(?:error|Error):\s*(.+)/gi,
|
|
288
|
+
/line (\d+)(?:, column (\d+))?:\s*(.+)/gi,
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
for (const pattern of patterns) {
|
|
292
|
+
let match;
|
|
293
|
+
while ((match = pattern.exec(output)) !== null) {
|
|
294
|
+
errors.push({
|
|
295
|
+
line: parseInt(match[1], 10),
|
|
296
|
+
column: parseInt(match[2], 10) || 1,
|
|
297
|
+
message: match[3].trim(),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// If no structured errors found, treat the whole output as an error
|
|
303
|
+
if (errors.length === 0 && output.trim()) {
|
|
304
|
+
const lines = output.trim().split('\n');
|
|
305
|
+
for (const line of lines) {
|
|
306
|
+
if (line.includes('Error') || line.includes('error')) {
|
|
307
|
+
errors.push({
|
|
308
|
+
line: 1,
|
|
309
|
+
column: 1,
|
|
310
|
+
message: line.trim(),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return errors;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function createDiagnostic(error, document) {
|
|
320
|
+
const line = Math.max(0, (error.line || 1) - 1);
|
|
321
|
+
const column = Math.max(0, (error.column || 1) - 1);
|
|
322
|
+
|
|
323
|
+
// Get the line text to determine range
|
|
324
|
+
let endColumn = column;
|
|
325
|
+
try {
|
|
326
|
+
const lineText = document.lineAt(line).text;
|
|
327
|
+
// Highlight to end of word or rest of line
|
|
328
|
+
const restOfLine = lineText.substring(column);
|
|
329
|
+
const wordMatch = restOfLine.match(/^\w+/);
|
|
330
|
+
if (wordMatch) {
|
|
331
|
+
endColumn = column + wordMatch[0].length;
|
|
332
|
+
} else {
|
|
333
|
+
endColumn = Math.min(column + 10, lineText.length);
|
|
334
|
+
}
|
|
335
|
+
} catch {
|
|
336
|
+
endColumn = column + 1;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const range = new vscode.Range(line, column, line, endColumn);
|
|
340
|
+
|
|
341
|
+
const severity = error.severity === 'warning'
|
|
342
|
+
? vscode.DiagnosticSeverity.Warning
|
|
343
|
+
: vscode.DiagnosticSeverity.Error;
|
|
344
|
+
|
|
345
|
+
const diagnostic = new vscode.Diagnostic(range, error.message, severity);
|
|
346
|
+
diagnostic.source = 'kimchi';
|
|
347
|
+
|
|
348
|
+
return diagnostic;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
module.exports = {
|
|
352
|
+
activate,
|
|
353
|
+
deactivate,
|
|
354
|
+
};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
|
3
|
+
"name": "KimchiLang",
|
|
4
|
+
"scopeName": "source.kimchi",
|
|
5
|
+
"patterns": [
|
|
6
|
+
{ "include": "#comments" },
|
|
7
|
+
{ "include": "#strings" },
|
|
8
|
+
{ "include": "#numbers" },
|
|
9
|
+
{ "include": "#keywords" },
|
|
10
|
+
{ "include": "#storage" },
|
|
11
|
+
{ "include": "#constants" },
|
|
12
|
+
{ "include": "#operators" },
|
|
13
|
+
{ "include": "#functions" },
|
|
14
|
+
{ "include": "#pattern-matching" },
|
|
15
|
+
{ "include": "#identifiers" }
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"comments": {
|
|
19
|
+
"patterns": [
|
|
20
|
+
{
|
|
21
|
+
"name": "comment.line.double-slash.kimchi",
|
|
22
|
+
"match": "//.*$"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "comment.block.kimchi",
|
|
26
|
+
"begin": "/\\*",
|
|
27
|
+
"end": "\\*/"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"strings": {
|
|
32
|
+
"patterns": [
|
|
33
|
+
{
|
|
34
|
+
"name": "string.quoted.double.kimchi",
|
|
35
|
+
"begin": "\"",
|
|
36
|
+
"end": "\"",
|
|
37
|
+
"patterns": [
|
|
38
|
+
{
|
|
39
|
+
"name": "constant.character.escape.kimchi",
|
|
40
|
+
"match": "\\\\."
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "string.quoted.single.kimchi",
|
|
46
|
+
"begin": "'",
|
|
47
|
+
"end": "'",
|
|
48
|
+
"patterns": [
|
|
49
|
+
{
|
|
50
|
+
"name": "constant.character.escape.kimchi",
|
|
51
|
+
"match": "\\\\."
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "string.template.kimchi",
|
|
57
|
+
"begin": "`",
|
|
58
|
+
"end": "`",
|
|
59
|
+
"patterns": [
|
|
60
|
+
{
|
|
61
|
+
"name": "constant.character.escape.kimchi",
|
|
62
|
+
"match": "\\\\."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "variable.other.template.kimchi",
|
|
66
|
+
"begin": "\\$\\{",
|
|
67
|
+
"end": "\\}"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"numbers": {
|
|
74
|
+
"patterns": [
|
|
75
|
+
{
|
|
76
|
+
"name": "constant.numeric.float.kimchi",
|
|
77
|
+
"match": "\\b\\d+\\.\\d+\\b"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "constant.numeric.integer.kimchi",
|
|
81
|
+
"match": "\\b\\d+\\b"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "constant.numeric.hex.kimchi",
|
|
85
|
+
"match": "\\b0x[0-9a-fA-F]+\\b"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"keywords": {
|
|
90
|
+
"patterns": [
|
|
91
|
+
{
|
|
92
|
+
"name": "keyword.control.kimchi",
|
|
93
|
+
"match": "\\b(if|else|for|while|return|try|catch|throw|in|await|async|break|continue)\\b"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "keyword.other.kimchi",
|
|
97
|
+
"match": "\\b(dep|arg|expose|print|new|shell|js|test|describe|expect|assert|secret|env|enum|is)\\b"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "keyword.operator.logical.kimchi",
|
|
101
|
+
"match": "\\b(and|or|not)\\b"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"storage": {
|
|
106
|
+
"patterns": [
|
|
107
|
+
{
|
|
108
|
+
"name": "storage.type.kimchi",
|
|
109
|
+
"match": "\\b(fn|memo|dec|as|var)\\b"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "storage.modifier.kimchi",
|
|
113
|
+
"match": "\\b(expose)\\b"
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
"constants": {
|
|
118
|
+
"patterns": [
|
|
119
|
+
{
|
|
120
|
+
"name": "constant.language.boolean.kimchi",
|
|
121
|
+
"match": "\\b(true|false)\\b"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "constant.language.null.kimchi",
|
|
125
|
+
"match": "\\b(null|undefined)\\b"
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
"operators": {
|
|
130
|
+
"patterns": [
|
|
131
|
+
{
|
|
132
|
+
"name": "keyword.operator.arrow.kimchi",
|
|
133
|
+
"match": "=>"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "keyword.operator.flow.kimchi",
|
|
137
|
+
"match": "\\|>"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "keyword.operator.range.kimchi",
|
|
141
|
+
"match": "\\.\\."
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "keyword.operator.spread.kimchi",
|
|
145
|
+
"match": "\\.\\.\\."
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "keyword.operator.comparison.kimchi",
|
|
149
|
+
"match": "(===|!==|==|!=|<=|>=|<|>)"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "keyword.operator.assignment.kimchi",
|
|
153
|
+
"match": "="
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "keyword.operator.arithmetic.kimchi",
|
|
157
|
+
"match": "(\\+|-|\\*|/|%)"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "keyword.operator.logical.kimchi",
|
|
161
|
+
"match": "(&&|\\|\\||!)"
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
"functions": {
|
|
166
|
+
"patterns": [
|
|
167
|
+
{
|
|
168
|
+
"name": "entity.name.function.kimchi",
|
|
169
|
+
"match": "\\b(fn)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(",
|
|
170
|
+
"captures": {
|
|
171
|
+
"1": { "name": "storage.type.function.kimchi" },
|
|
172
|
+
"2": { "name": "entity.name.function.kimchi" }
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "meta.function-call.kimchi",
|
|
177
|
+
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(",
|
|
178
|
+
"captures": {
|
|
179
|
+
"1": { "name": "entity.name.function.kimchi" }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
"pattern-matching": {
|
|
185
|
+
"patterns": [
|
|
186
|
+
{
|
|
187
|
+
"name": "meta.pattern-match.kimchi",
|
|
188
|
+
"begin": "\\|(?!>)",
|
|
189
|
+
"end": "\\|\\s*=>",
|
|
190
|
+
"beginCaptures": {
|
|
191
|
+
"0": { "name": "punctuation.definition.pattern.begin.kimchi" }
|
|
192
|
+
},
|
|
193
|
+
"endCaptures": {
|
|
194
|
+
"0": { "name": "punctuation.definition.pattern.end.kimchi" }
|
|
195
|
+
},
|
|
196
|
+
"patterns": [
|
|
197
|
+
{ "include": "#strings" },
|
|
198
|
+
{ "include": "#numbers" },
|
|
199
|
+
{ "include": "#constants" },
|
|
200
|
+
{ "include": "#operators" },
|
|
201
|
+
{ "include": "#identifiers" }
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
},
|
|
206
|
+
"identifiers": {
|
|
207
|
+
"patterns": [
|
|
208
|
+
{
|
|
209
|
+
"name": "variable.other.kimchi",
|
|
210
|
+
"match": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b"
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Example API client module with args and help functions
|
|
2
|
+
|
|
3
|
+
!arg clientId
|
|
4
|
+
arg timeout = 5000
|
|
5
|
+
|
|
6
|
+
as http dep pantry.axios
|
|
7
|
+
|
|
8
|
+
expose fn _describe() {
|
|
9
|
+
return "API client for connecting to external services"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
expose fn _help() {
|
|
13
|
+
return "
|
|
14
|
+
This module provides HTTP client functionality.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
kimchi api.client --client-id YOUR_ID
|
|
18
|
+
|
|
19
|
+
The client will authenticate and make requests on your behalf.
|
|
20
|
+
"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
expose fn connect() {
|
|
24
|
+
print "Connecting with client ID: ${clientId}"
|
|
25
|
+
print "Timeout: ${timeout}ms"
|
|
26
|
+
return { connected: true, clientId: clientId }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
expose fn get(url) {
|
|
30
|
+
print "GET ${url}"
|
|
31
|
+
return { status: 200, data: "response" }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Run on module load
|
|
35
|
+
print "API Client initialized"
|
|
36
|
+
connect()
|