@enjoys/context-engine 1.0.5 → 1.0.7
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 +477 -100
- package/data/commands/journalctl.json +203 -66
- package/data/commands/manifest.json +6 -2
- package/data/commands/systemctl.json +800 -23
- package/data/commands/systemd-analyze.json +239 -0
- package/data/commands/zsh.json +166 -0
- package/data/completion/nginx.json +561 -77
- package/data/completion/systemd.json +795 -47
- package/data/completion/zsh.json +829 -70
- package/data/defination/nginx.json +416 -32
- package/data/defination/systemd.json +538 -56
- package/data/defination/zsh.json +323 -86
- package/data/hover/nginx.json +59 -17
- package/data/hover/systemd.json +42 -7
- package/data/hover/zsh.json +44 -9
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @enjoys/context-engine
|
|
2
2
|
|
|
3
|
-
Comprehensive CLI command context engine with **
|
|
3
|
+
Comprehensive CLI command context engine with **190 tools** and **35 languages** — completions, definitions, hovers, subcommands, options, examples, and runtime context detectors for intelligent terminal autocomplete in Monaco Editor.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,12 +8,205 @@ Comprehensive CLI command context engine with **133 tools** — subcommands, opt
|
|
|
8
8
|
npm install @enjoys/context-engine
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## What's Inside
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
```
|
|
14
|
+
data/
|
|
15
|
+
├── commands/ # 190 CLI tool definitions (git, docker, kubectl, nginx, systemctl, ...)
|
|
16
|
+
│ └── *.json # subcommands, options, examples, context detectors
|
|
17
|
+
├── completion/ # 35 languages — Monaco completions (snippets, insertText)
|
|
18
|
+
│ └── *.json # ready-to-use CompletionItem[] for Monaco
|
|
19
|
+
├── defination/ # 35 languages — definitions (signatures, descriptions)
|
|
20
|
+
│ └── *.json # keyword → { signature, description, type }
|
|
21
|
+
├── hover/ # 35 languages — hover documentation
|
|
22
|
+
│ └── *.json # keyword → { contents: [{ value }] }
|
|
23
|
+
└── manifest.json # Language registry with file mappings
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Start — Full Monaco Integration
|
|
29
|
+
|
|
30
|
+
This single example registers **completions**, **hover**, **definitions**, and **command-line autocomplete** for any language:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import * as monaco from 'monaco-editor';
|
|
34
|
+
|
|
35
|
+
// ── 1. Import language data (e.g., nginx) ──
|
|
36
|
+
import nginxCompletions from '@enjoys/context-engine/completion/nginx.json';
|
|
37
|
+
import nginxDefinitions from '@enjoys/context-engine/defination/nginx.json';
|
|
38
|
+
import nginxHovers from '@enjoys/context-engine/hover/nginx.json';
|
|
39
|
+
|
|
40
|
+
// ── 2. Import command data ──
|
|
41
|
+
import { getCommand, searchCommands, getSubcommands } from '@enjoys/context-engine';
|
|
42
|
+
|
|
43
|
+
// =============================================
|
|
44
|
+
// REGISTER COMPLETION PROVIDER
|
|
45
|
+
// =============================================
|
|
46
|
+
monaco.languages.registerCompletionItemProvider('nginx', {
|
|
47
|
+
provideCompletionItems(model, position) {
|
|
48
|
+
const word = model.getWordUntilPosition(position);
|
|
49
|
+
const range = {
|
|
50
|
+
startLineNumber: position.lineNumber,
|
|
51
|
+
endLineNumber: position.lineNumber,
|
|
52
|
+
startColumn: word.startColumn,
|
|
53
|
+
endColumn: word.endColumn,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Map data to Monaco CompletionItems
|
|
57
|
+
const suggestions = nginxCompletions.completions.map((item) => ({
|
|
58
|
+
label: item.label,
|
|
59
|
+
kind: item.kind, // e.g. 15 = Snippet
|
|
60
|
+
detail: item.detail,
|
|
61
|
+
documentation: item.documentation?.value
|
|
62
|
+
? { value: item.documentation.value, isTrusted: true }
|
|
63
|
+
: undefined,
|
|
64
|
+
insertText: item.insertText,
|
|
65
|
+
insertTextRules: item.insertTextRules, // 4 = InsertAsSnippet
|
|
66
|
+
sortText: item.sortText,
|
|
67
|
+
range,
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
return { suggestions };
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// =============================================
|
|
75
|
+
// REGISTER HOVER PROVIDER
|
|
76
|
+
// =============================================
|
|
77
|
+
monaco.languages.registerHoverProvider('nginx', {
|
|
78
|
+
provideHover(model, position) {
|
|
79
|
+
const word = model.getWordAtPosition(position);
|
|
80
|
+
if (!word) return null;
|
|
81
|
+
|
|
82
|
+
const key = word.word.toLowerCase();
|
|
83
|
+
const hover = nginxHovers.hovers[key];
|
|
84
|
+
if (!hover) return null;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
range: new monaco.Range(
|
|
88
|
+
position.lineNumber,
|
|
89
|
+
word.startColumn,
|
|
90
|
+
position.lineNumber,
|
|
91
|
+
word.endColumn
|
|
92
|
+
),
|
|
93
|
+
contents: hover.contents.map((c) => ({
|
|
94
|
+
value: c.value,
|
|
95
|
+
isTrusted: true,
|
|
96
|
+
supportThemeIcons: true,
|
|
97
|
+
})),
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// =============================================
|
|
103
|
+
// REGISTER DEFINITION PROVIDER (Peek Definition)
|
|
104
|
+
// =============================================
|
|
105
|
+
monaco.languages.registerDefinitionProvider('nginx', {
|
|
106
|
+
provideDefinition(model, position) {
|
|
107
|
+
const word = model.getWordAtPosition(position);
|
|
108
|
+
if (!word) return null;
|
|
109
|
+
|
|
110
|
+
const key = word.word.toLowerCase();
|
|
111
|
+
const def = nginxDefinitions.definitions[key];
|
|
112
|
+
if (!def) return null;
|
|
113
|
+
|
|
114
|
+
// Search the document for the first occurrence of this keyword
|
|
115
|
+
const text = model.getValue();
|
|
116
|
+
const lines = text.split('\n');
|
|
117
|
+
for (let i = 0; i < lines.length; i++) {
|
|
118
|
+
const col = lines[i].indexOf(word.word);
|
|
119
|
+
if (col !== -1) {
|
|
120
|
+
return {
|
|
121
|
+
uri: model.uri,
|
|
122
|
+
range: new monaco.Range(i + 1, col + 1, i + 1, col + 1 + word.word.length),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// =============================================
|
|
131
|
+
// SHOW DEFINITION INFO IN A CUSTOM WIDGET
|
|
132
|
+
// =============================================
|
|
133
|
+
// You can use definitions data to build a sidebar, tooltip, or panel:
|
|
134
|
+
function getDefinitionInfo(keyword) {
|
|
135
|
+
const def = nginxDefinitions.definitions[keyword];
|
|
136
|
+
if (!def) return null;
|
|
137
|
+
return {
|
|
138
|
+
signature: def.signature, // e.g. "proxy_pass URL"
|
|
139
|
+
description: def.description, // e.g. "Forwards requests to backend..."
|
|
140
|
+
type: def.type, // e.g. "directive"
|
|
141
|
+
module: def.module, // e.g. "ngx_http_proxy_module"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Example:
|
|
146
|
+
// getDefinitionInfo('proxy_pass')
|
|
147
|
+
// → { signature: "proxy_pass URL", description: "Sets the protocol and address...", type: "directive", module: "ngx_http_proxy_module" }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Register Multiple Languages at Once
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
import manifest from '@enjoys/context-engine/data/manifest.json';
|
|
154
|
+
|
|
155
|
+
// Dynamically register all 35 languages
|
|
156
|
+
for (const lang of manifest.languages) {
|
|
157
|
+
const completionData = await import(`@enjoys/context-engine/${lang.files.completion}`);
|
|
158
|
+
const hoverData = await import(`@enjoys/context-engine/${lang.files.hover}`);
|
|
159
|
+
const defData = await import(`@enjoys/context-engine/${lang.files.defination}`);
|
|
160
|
+
|
|
161
|
+
monaco.languages.registerCompletionItemProvider(lang.id, {
|
|
162
|
+
provideCompletionItems(model, position) {
|
|
163
|
+
const word = model.getWordUntilPosition(position);
|
|
164
|
+
const range = {
|
|
165
|
+
startLineNumber: position.lineNumber,
|
|
166
|
+
endLineNumber: position.lineNumber,
|
|
167
|
+
startColumn: word.startColumn,
|
|
168
|
+
endColumn: word.endColumn,
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
suggestions: completionData.completions.map((item) => ({
|
|
172
|
+
label: item.label,
|
|
173
|
+
kind: item.kind,
|
|
174
|
+
detail: item.detail,
|
|
175
|
+
documentation: item.documentation?.value
|
|
176
|
+
? { value: item.documentation.value, isTrusted: true }
|
|
177
|
+
: undefined,
|
|
178
|
+
insertText: item.insertText,
|
|
179
|
+
insertTextRules: item.insertTextRules,
|
|
180
|
+
sortText: item.sortText,
|
|
181
|
+
range,
|
|
182
|
+
})),
|
|
183
|
+
};
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
monaco.languages.registerHoverProvider(lang.id, {
|
|
188
|
+
provideHover(model, position) {
|
|
189
|
+
const word = model.getWordAtPosition(position);
|
|
190
|
+
if (!word) return null;
|
|
191
|
+
const hover = hoverData.hovers[word.word.toLowerCase()];
|
|
192
|
+
if (!hover) return null;
|
|
193
|
+
return {
|
|
194
|
+
range: new monaco.Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn),
|
|
195
|
+
contents: hover.contents.map((c) => ({ value: c.value, isTrusted: true })),
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Terminal Autocomplete — Command Engine API
|
|
205
|
+
|
|
206
|
+
Use the command engine to build intelligent terminal autocomplete (like Fig or Warp):
|
|
14
207
|
|
|
15
208
|
```js
|
|
16
|
-
|
|
209
|
+
import {
|
|
17
210
|
getCommand,
|
|
18
211
|
getAllCommands,
|
|
19
212
|
listCommandNames,
|
|
@@ -26,186 +219,370 @@ const {
|
|
|
26
219
|
getGlobalOptions,
|
|
27
220
|
getExamples,
|
|
28
221
|
count,
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### ESM
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
import {
|
|
36
|
-
getCommand,
|
|
37
|
-
getAllCommands,
|
|
38
|
-
searchCommands,
|
|
39
|
-
count,
|
|
40
|
-
} from "@enjoys/context-engine";
|
|
222
|
+
} from '@enjoys/context-engine';
|
|
41
223
|
```
|
|
42
224
|
|
|
43
|
-
## API
|
|
44
|
-
|
|
45
225
|
### `getCommand(name)`
|
|
46
226
|
|
|
47
227
|
Get a single command definition by name.
|
|
48
228
|
|
|
49
229
|
```js
|
|
50
|
-
const git = getCommand(
|
|
230
|
+
const git = getCommand('git');
|
|
51
231
|
console.log(git.subcommands.map((s) => s.name));
|
|
52
232
|
// ['init', 'clone', 'add', 'commit', 'push', ...]
|
|
53
233
|
```
|
|
54
234
|
|
|
55
|
-
### `getAllCommands()`
|
|
56
|
-
|
|
57
|
-
Return all 133 command objects as an array.
|
|
58
|
-
|
|
59
|
-
### `listCommandNames()`
|
|
60
|
-
|
|
61
|
-
Return sorted array of all command names.
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
listCommandNames();
|
|
65
|
-
// ['air', 'ansible', 'apachectl', 'apt', 'apt-get', 'awk', 'aws', ...]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
235
|
### `searchCommands(query)`
|
|
69
236
|
|
|
70
237
|
Search commands by name, description, or category (case-insensitive).
|
|
71
238
|
|
|
72
239
|
```js
|
|
73
|
-
searchCommands(
|
|
74
|
-
// [{ name: 'docker', ... }]
|
|
240
|
+
searchCommands('docker');
|
|
241
|
+
// [{ name: 'docker', ... }, { name: 'docker-compose', ... }]
|
|
75
242
|
|
|
76
|
-
searchCommands(
|
|
77
|
-
// [{ name: '
|
|
243
|
+
searchCommands('database');
|
|
244
|
+
// [{ name: 'psql', ... }, { name: 'mysql', ... }, { name: 'mongosh', ... }]
|
|
78
245
|
```
|
|
79
246
|
|
|
80
|
-
### `
|
|
81
|
-
|
|
82
|
-
Filter by category (case-insensitive partial match).
|
|
247
|
+
### `getSubcommands(name)`
|
|
83
248
|
|
|
84
249
|
```js
|
|
85
|
-
|
|
86
|
-
// [
|
|
250
|
+
getSubcommands('systemctl');
|
|
251
|
+
// [{ name: 'start', description: 'Start (activate) one or more units', args: [...], examples: [...] },
|
|
252
|
+
// { name: 'stop', ... }, { name: 'restart', ... }, { name: 'status', ... },
|
|
253
|
+
// { name: 'enable', options: [{ name: '--now' }], ... }, ... ] (35 subcommands)
|
|
87
254
|
```
|
|
88
255
|
|
|
89
|
-
### `
|
|
90
|
-
|
|
91
|
-
Filter by platform: `"linux"` | `"macos"` | `"windows"`.
|
|
256
|
+
### `getGlobalOptions(name)`
|
|
92
257
|
|
|
93
258
|
```js
|
|
94
|
-
|
|
95
|
-
// [
|
|
259
|
+
getGlobalOptions('journalctl');
|
|
260
|
+
// [{ name: '-u', description: 'Show logs for a specific unit' },
|
|
261
|
+
// { name: '-f', description: 'Follow — show new log entries' },
|
|
262
|
+
// { name: '-n', description: 'Number of lines to show' }, ...] (32 options)
|
|
96
263
|
```
|
|
97
264
|
|
|
98
|
-
### `
|
|
99
|
-
|
|
100
|
-
Return all unique category names.
|
|
265
|
+
### `getExamples(name)`
|
|
101
266
|
|
|
102
267
|
```js
|
|
103
|
-
|
|
104
|
-
// ['
|
|
268
|
+
getExamples('nginx');
|
|
269
|
+
// ['nginx -t', 'nginx -s reload', 'sudo nginx -t && sudo nginx -s reload', ...]
|
|
105
270
|
```
|
|
106
271
|
|
|
107
272
|
### `getContextEngine(name)`
|
|
108
273
|
|
|
109
|
-
Get runtime context detectors for a command.
|
|
274
|
+
Get runtime context detectors for a command — shell commands that gather live context.
|
|
110
275
|
|
|
111
276
|
```js
|
|
112
|
-
const ctx = getContextEngine(
|
|
113
|
-
// {
|
|
277
|
+
const ctx = getContextEngine('docker');
|
|
278
|
+
// {
|
|
279
|
+
// detectors: [
|
|
280
|
+
// { name: 'containers', command: 'docker ps ...', parser: 'lines', cacheFor: 10 },
|
|
281
|
+
// { name: 'images', command: 'docker images ...', parser: 'lines', cacheFor: 30 },
|
|
282
|
+
// ...
|
|
283
|
+
// ]
|
|
284
|
+
// }
|
|
114
285
|
```
|
|
115
286
|
|
|
116
|
-
### `
|
|
287
|
+
### `getCommandsByCategory(category)` / `getCommandsByPlatform(platform)`
|
|
117
288
|
|
|
118
289
|
```js
|
|
119
|
-
|
|
120
|
-
// [
|
|
290
|
+
getCommandsByCategory('database');
|
|
291
|
+
// [psql, mysql, mongosh, sqlite3, redis-cli, cockroach, influx, clickhouse-client, ...]
|
|
292
|
+
|
|
293
|
+
getCommandsByPlatform('windows');
|
|
294
|
+
// [choco, winget, ...]
|
|
121
295
|
```
|
|
122
296
|
|
|
123
|
-
### `
|
|
297
|
+
### `getCategories()`
|
|
124
298
|
|
|
125
299
|
```js
|
|
126
|
-
|
|
127
|
-
// [
|
|
300
|
+
getCategories();
|
|
301
|
+
// ['Build Tools', 'Cloud CLIs', 'Container', 'Database', 'DevOps', ...]
|
|
128
302
|
```
|
|
129
303
|
|
|
130
|
-
### `
|
|
304
|
+
### `count()`
|
|
131
305
|
|
|
132
306
|
```js
|
|
133
|
-
|
|
134
|
-
// [{ command: 'docker run -d nginx', description: 'Run nginx in background' }, ...]
|
|
307
|
+
count(); // 190
|
|
135
308
|
```
|
|
136
309
|
|
|
137
|
-
### `
|
|
310
|
+
### `resolveCommandPath(name)` / `dataDir`
|
|
138
311
|
|
|
139
312
|
```js
|
|
140
|
-
|
|
313
|
+
resolveCommandPath('git');
|
|
314
|
+
// '/path/to/node_modules/@enjoys/context-engine/data/commands/git.json'
|
|
141
315
|
```
|
|
142
316
|
|
|
143
|
-
### `
|
|
317
|
+
### `clearCache()`
|
|
318
|
+
|
|
319
|
+
Clear the in-memory cache (useful in tests).
|
|
320
|
+
|
|
321
|
+
---
|
|
144
322
|
|
|
145
|
-
|
|
323
|
+
## Full Terminal Autocomplete Example
|
|
324
|
+
|
|
325
|
+
Build a terminal autocomplete that suggests subcommands, options, and uses context detectors:
|
|
146
326
|
|
|
147
327
|
```js
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
328
|
+
import { getCommand, getContextEngine, searchCommands } from '@enjoys/context-engine';
|
|
329
|
+
import { exec } from 'child_process';
|
|
330
|
+
import { promisify } from 'util';
|
|
151
331
|
|
|
152
|
-
|
|
332
|
+
const execAsync = promisify(exec);
|
|
153
333
|
|
|
154
|
-
|
|
334
|
+
// ── Run a context detector and cache results ──
|
|
335
|
+
const cache = new Map();
|
|
155
336
|
|
|
156
|
-
|
|
337
|
+
async function runDetector(detector) {
|
|
338
|
+
const cached = cache.get(detector.name);
|
|
339
|
+
if (cached && Date.now() - cached.time < (detector.cacheFor || 30) * 1000) {
|
|
340
|
+
return cached.data;
|
|
341
|
+
}
|
|
157
342
|
|
|
158
|
-
|
|
343
|
+
try {
|
|
344
|
+
const { stdout } = await execAsync(detector.command, { timeout: 5000 });
|
|
345
|
+
let data;
|
|
346
|
+
switch (detector.parser) {
|
|
347
|
+
case 'lines': data = stdout.trim().split('\n').filter(Boolean); break;
|
|
348
|
+
case 'json': data = JSON.parse(stdout); break;
|
|
349
|
+
default: data = stdout.trim(); break;
|
|
350
|
+
}
|
|
351
|
+
cache.set(detector.name, { data, time: Date.now() });
|
|
352
|
+
return data;
|
|
353
|
+
} catch {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ── Autocomplete function ──
|
|
359
|
+
async function getCompletions(inputLine) {
|
|
360
|
+
const parts = inputLine.trim().split(/\s+/);
|
|
361
|
+
const cmdName = parts[0];
|
|
362
|
+
const cmd = getCommand(cmdName);
|
|
363
|
+
if (!cmd) {
|
|
364
|
+
// Suggest matching command names
|
|
365
|
+
return searchCommands(cmdName).map((c) => ({
|
|
366
|
+
label: c.name,
|
|
367
|
+
detail: c.description,
|
|
368
|
+
}));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// User typed "systemctl " — suggest subcommands
|
|
372
|
+
if (parts.length === 1 || (parts.length === 2 && !parts[1].startsWith('-'))) {
|
|
373
|
+
const items = cmd.subcommands.map((s) => ({
|
|
374
|
+
label: s.name,
|
|
375
|
+
detail: s.description,
|
|
376
|
+
}));
|
|
377
|
+
|
|
378
|
+
// Also add context detectors (e.g., running services, failed units)
|
|
379
|
+
const ctx = getContextEngine(cmdName);
|
|
380
|
+
if (ctx) {
|
|
381
|
+
for (const detector of ctx.detectors) {
|
|
382
|
+
const data = await runDetector(detector);
|
|
383
|
+
if (Array.isArray(data)) {
|
|
384
|
+
items.push(...data.map((d) => ({
|
|
385
|
+
label: d,
|
|
386
|
+
detail: `[${detector.name}]`,
|
|
387
|
+
})));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return items;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// User typed "systemctl start " — suggest from detectors
|
|
395
|
+
const subName = parts[1];
|
|
396
|
+
const sub = cmd.subcommands.find((s) => s.name === subName);
|
|
397
|
+
if (sub?.options) {
|
|
398
|
+
return sub.options.map((o) => ({
|
|
399
|
+
label: o.name,
|
|
400
|
+
detail: o.description,
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return cmd.globalOptions.map((o) => ({
|
|
405
|
+
label: o.name,
|
|
406
|
+
detail: o.description,
|
|
407
|
+
}));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Usage:
|
|
411
|
+
// await getCompletions('systemctl ') → 35 subcommands + live context
|
|
412
|
+
// await getCompletions('systemctl start') → running/enabled services
|
|
413
|
+
// await getCompletions('docker ') → subcommands + running containers
|
|
414
|
+
// await getCompletions('git ') → subcommands + branches
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
159
418
|
|
|
160
419
|
## Direct JSON Import
|
|
161
420
|
|
|
162
421
|
Access raw JSON files directly:
|
|
163
422
|
|
|
164
423
|
```js
|
|
165
|
-
|
|
424
|
+
// Command data
|
|
425
|
+
const git = require('@enjoys/context-engine/commands/git.json');
|
|
426
|
+
|
|
427
|
+
// Language data
|
|
428
|
+
const nginxCompletion = require('@enjoys/context-engine/completion/nginx.json');
|
|
429
|
+
const nginxDefinition = require('@enjoys/context-engine/defination/nginx.json');
|
|
430
|
+
const nginxHover = require('@enjoys/context-engine/hover/nginx.json');
|
|
431
|
+
|
|
432
|
+
// Manifest (all languages)
|
|
433
|
+
const manifest = require('@enjoys/context-engine/data/manifest.json');
|
|
166
434
|
```
|
|
167
435
|
|
|
168
|
-
|
|
436
|
+
---
|
|
169
437
|
|
|
170
|
-
|
|
171
|
-
|----------|-------|
|
|
172
|
-
| **Cloud CLIs** | aws, az, gcloud, doctl, linode-cli, vercel, netlify, firebase, supabase, railway, render, flyctl, cloudflare, aws-vault |
|
|
173
|
-
| **Container & Orchestration** | docker, kubectl, helm |
|
|
174
|
-
| **Version Control** | git, gh, glab, svn, hg |
|
|
175
|
-
| **Node.js Ecosystem** | node, npm, npx, yarn, pnpm, bun, deno, turbo, nx, vite, next, nest, tsc, eslint, prettier |
|
|
176
|
-
| **Python Ecosystem** | python, pip, pipx, poetry, pipenv, conda, pytest, uvicorn, gunicorn, django-admin, flask |
|
|
177
|
-
| **Rust & Go** | cargo, rust, rustup, wasm-pack, go, gofmt, golangci-lint, air |
|
|
178
|
-
| **Java/JVM** | java, gradle, mvn |
|
|
179
|
-
| **Database** | psql, pg_dump, pg_restore, mysql, mongosh, redis-cli, sqlite3, cockroach, influx, clickhouse-client |
|
|
180
|
-
| **DevOps & Infrastructure** | terraform, terragrunt, pulumi, packer, vault, consul, nomad, ansible |
|
|
181
|
-
| **Web Servers** | nginx, caddy, httpd, apachectl |
|
|
182
|
-
| **Build Tools** | make, cmake, bazel, just |
|
|
183
|
-
| **Linux Core** | ls, cp, mv, rm, cat, grep, find, sed, awk, tar, chmod, chown, ps, sudo, ssh, ssh-keygen, rsync, curl, wget, systemctl, cd, zip, unzip, scp, journalctl, ufw, iptables, nft |
|
|
184
|
-
| **Testing** | jest, vitest, mocha, playwright, cypress, k6, locust |
|
|
185
|
-
| **Network & Security** | nmap, tcpdump, wireshark, openssl, certbot |
|
|
186
|
-
| **Package Managers** | apt, apt-get, yum, dnf, pacman, brew, choco, winget |
|
|
438
|
+
## Data Formats
|
|
187
439
|
|
|
188
|
-
|
|
440
|
+
### Completion Item (`data/completion/*.json`)
|
|
441
|
+
|
|
442
|
+
```json
|
|
443
|
+
{
|
|
444
|
+
"language": "nginx",
|
|
445
|
+
"completions": [
|
|
446
|
+
{
|
|
447
|
+
"label": "server block",
|
|
448
|
+
"kind": 15,
|
|
449
|
+
"detail": "Server block",
|
|
450
|
+
"documentation": { "value": "Defines a virtual server." },
|
|
451
|
+
"insertText": "server {\n listen ${1:80};\n server_name ${2:example.com};\n ...\n}",
|
|
452
|
+
"insertTextRules": 4,
|
|
453
|
+
"sortText": "00_server"
|
|
454
|
+
}
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
`kind` values: `15` = Snippet, `5` = Field, `14` = Keyword, `9` = Function, `12` = Value, `6` = Variable
|
|
460
|
+
`insertTextRules`: `4` = InsertAsSnippet (supports `${1:placeholder}` tab stops)
|
|
189
461
|
|
|
190
|
-
|
|
462
|
+
### Definition Item (`data/defination/*.json`)
|
|
191
463
|
|
|
192
464
|
```json
|
|
193
465
|
{
|
|
466
|
+
"language": "nginx",
|
|
467
|
+
"definitions": {
|
|
468
|
+
"proxy_pass": {
|
|
469
|
+
"signature": "proxy_pass URL",
|
|
470
|
+
"description": "Sets the protocol and address of a proxied server.",
|
|
471
|
+
"type": "directive",
|
|
472
|
+
"module": "ngx_http_proxy_module"
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Hover Item (`data/hover/*.json`)
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"language": "nginx",
|
|
483
|
+
"hovers": {
|
|
484
|
+
"server": {
|
|
485
|
+
"contents": [
|
|
486
|
+
{
|
|
487
|
+
"value": "```nginx\nserver {\n listen 80;\n server_name example.com;\n ...\n}\n```\n**server** block defines a virtual host."
|
|
488
|
+
}
|
|
489
|
+
]
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Command Definition (`data/commands/*.json`)
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"name": "systemctl",
|
|
500
|
+
"description": "Control the systemd system and service manager",
|
|
501
|
+
"category": "system",
|
|
502
|
+
"platforms": ["linux"],
|
|
503
|
+
"shells": ["bash", "zsh", "fish"],
|
|
504
|
+
"subcommands": [
|
|
505
|
+
{
|
|
506
|
+
"name": "start",
|
|
507
|
+
"description": "Start one or more units",
|
|
508
|
+
"args": [{ "name": "<unit>", "type": "string", "required": true }],
|
|
509
|
+
"examples": ["systemctl start nginx"]
|
|
510
|
+
}
|
|
511
|
+
],
|
|
512
|
+
"globalOptions": [
|
|
513
|
+
{ "name": "--no-pager", "description": "Do not pipe output into pager" }
|
|
514
|
+
],
|
|
515
|
+
"examples": ["systemctl start nginx", "systemctl status nginx -l"],
|
|
516
|
+
"relatedCommands": ["journalctl", "systemd-analyze"],
|
|
194
517
|
"contextEngine": {
|
|
195
518
|
"detectors": [
|
|
196
519
|
{
|
|
197
|
-
"name": "
|
|
198
|
-
"
|
|
199
|
-
"command": "git branch --format='%(refname:short)'",
|
|
520
|
+
"name": "failed_units",
|
|
521
|
+
"command": "systemctl --failed --no-legend --plain 2>/dev/null | head -20",
|
|
200
522
|
"parser": "lines",
|
|
201
|
-
"cacheFor":
|
|
202
|
-
"requiresCmd": "
|
|
523
|
+
"cacheFor": 10,
|
|
524
|
+
"requiresCmd": "systemctl"
|
|
203
525
|
}
|
|
204
526
|
]
|
|
205
527
|
}
|
|
206
528
|
}
|
|
207
529
|
```
|
|
208
530
|
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Supported Languages (35)
|
|
534
|
+
|
|
535
|
+
| Category | Languages |
|
|
536
|
+
|----------|-----------|
|
|
537
|
+
| **Systems** | C, C++, Rust, Go |
|
|
538
|
+
| **Web** | JavaScript, TypeScript, HTML, PHP, Ruby, Python, Java, C#, Lua, Perl |
|
|
539
|
+
| **Config** | Nginx, Systemd, Dockerfile, YAML, TOML, JSON, XML, INI, Dotenv, SSH Config, Crontab, HCL, Makefile |
|
|
540
|
+
| **Shell** | Bash, Zsh, PowerShell, Awk |
|
|
541
|
+
| **Data** | SQL, GraphQL, Protobuf |
|
|
542
|
+
| **Docs** | Markdown |
|
|
543
|
+
|
|
544
|
+
## Covered Commands (190)
|
|
545
|
+
|
|
546
|
+
| Category | Tools |
|
|
547
|
+
|----------|-------|
|
|
548
|
+
| **Cloud CLIs** | aws, az, gcloud, doctl, linode-cli, vercel, netlify, firebase, supabase, railway, render, flyctl, cloudflare, aws-vault, auth0, atlas |
|
|
549
|
+
| **Container & Orchestration** | docker, docker-compose, kubectl, helm, minikube, k9s |
|
|
550
|
+
| **Version Control** | git, gh, glab, svn, hg |
|
|
551
|
+
| **Node.js Ecosystem** | node, npm, npx, yarn, pnpm, bun, deno, turbo, nx, vite, next, nest, nuxt, vue, expo, tsc, eslint, prettier |
|
|
552
|
+
| **Python Ecosystem** | python, pip, pipx, poetry, pipenv, conda, pytest, uvicorn, gunicorn, django-admin, flask, alembic, locust |
|
|
553
|
+
| **Rust & Go** | cargo, rustup, wasm-pack, go, gofmt, golangci-lint, air |
|
|
554
|
+
| **Java/JVM** | java, gradle, mvn |
|
|
555
|
+
| **PHP** | php, composer, artisan |
|
|
556
|
+
| **Ruby** | gem, bundle, rails, pod, fastlane |
|
|
557
|
+
| **Database** | psql, pg_dump, pg_restore, mysql, mongosh, redis-cli, sqlite3, cockroach, influx, clickhouse-client, dbmate, liquibase, flyway, drizzle-kit, prisma |
|
|
558
|
+
| **DevOps & Infrastructure** | terraform, terragrunt, pulumi, packer, vault, consul, nomad, ansible |
|
|
559
|
+
| **Web Servers** | nginx, caddy, httpd, apachectl |
|
|
560
|
+
| **System** | systemctl, journalctl, systemd-analyze, zsh, pm2, tmux, htop, btop, nvim |
|
|
561
|
+
| **Build Tools** | make, cmake, bazel, just, bat |
|
|
562
|
+
| **Linux Core** | ls, cp, mv, rm, cat, grep, find, sed, awk, tar, chmod, chown, ps, sudo, ssh, ssh-keygen, rsync, curl, wget, cd, scp, linux |
|
|
563
|
+
| **Network & Security** | nmap, tcpdump, wireshark, openssl, certbot, ufw, iptables, nft |
|
|
564
|
+
| **Package Managers** | apt, apt-get, yum, dnf, pacman, brew, choco, winget, pipx |
|
|
565
|
+
| **Testing** | jest, vitest, mocha, playwright, cypress, k6, locust |
|
|
566
|
+
| **CI/CD** | stripe, adb |
|
|
567
|
+
|
|
568
|
+
## Context Engine
|
|
569
|
+
|
|
570
|
+
Each command can include a `contextEngine` with runtime `detectors` — shell commands that gather live context (running containers, git branches, installed packages, etc.) for intelligent autocomplete:
|
|
571
|
+
|
|
572
|
+
```js
|
|
573
|
+
const { getContextEngine } = require('@enjoys/context-engine');
|
|
574
|
+
|
|
575
|
+
const ctx = getContextEngine('systemctl');
|
|
576
|
+
// {
|
|
577
|
+
// detectors: [
|
|
578
|
+
// { name: 'failed_units', command: 'systemctl --failed ...', parser: 'lines', cacheFor: 10 },
|
|
579
|
+
// { name: 'running_services', command: 'systemctl list-units ...', parser: 'text', cacheFor: 15 },
|
|
580
|
+
// { name: 'active_timers', command: 'systemctl list-timers ...', parser: 'lines', cacheFor: 30 },
|
|
581
|
+
// ...
|
|
582
|
+
// ]
|
|
583
|
+
// }
|
|
584
|
+
```
|
|
585
|
+
|
|
209
586
|
**Parser types:** `text` | `lines` | `json` | `csv` | `keyvalue` | `regex` | `table`
|
|
210
587
|
|
|
211
588
|
## License
|