@seamapi/cli 0.11.0 → 0.13.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.
Files changed (39) hide show
  1. package/README.md +71 -0
  2. package/bin/cli.js +38 -98
  3. package/bin/cli.js.map +1 -1
  4. package/completions/seam.bash +16 -0
  5. package/completions/seam.fish +15 -0
  6. package/completions/seam.zsh +19 -0
  7. package/lib/command-spec.d.ts +53 -0
  8. package/lib/command-spec.js +290 -0
  9. package/lib/command-spec.js.map +1 -0
  10. package/lib/completion/describe.d.ts +10 -0
  11. package/lib/completion/describe.js +16 -0
  12. package/lib/completion/describe.js.map +1 -0
  13. package/lib/completion/index.d.ts +28 -0
  14. package/lib/completion/index.js +92 -0
  15. package/lib/completion/index.js.map +1 -0
  16. package/lib/completion/render-bash.d.ts +2 -0
  17. package/lib/completion/render-bash.js +98 -0
  18. package/lib/completion/render-bash.js.map +1 -0
  19. package/lib/completion/render-fish.d.ts +2 -0
  20. package/lib/completion/render-fish.js +58 -0
  21. package/lib/completion/render-fish.js.map +1 -0
  22. package/lib/completion/render-zsh.d.ts +2 -0
  23. package/lib/completion/render-zsh.js +121 -0
  24. package/lib/completion/render-zsh.js.map +1 -0
  25. package/lib/render-help.d.ts +8 -0
  26. package/lib/render-help.js +150 -0
  27. package/lib/render-help.js.map +1 -0
  28. package/lib/version.d.ts +1 -1
  29. package/lib/version.js +1 -1
  30. package/package.json +2 -1
  31. package/src/bin/cli.ts +54 -104
  32. package/src/lib/command-spec.ts +400 -0
  33. package/src/lib/completion/describe.ts +21 -0
  34. package/src/lib/completion/index.ts +110 -0
  35. package/src/lib/completion/render-bash.ts +125 -0
  36. package/src/lib/completion/render-fish.ts +80 -0
  37. package/src/lib/completion/render-zsh.ts +157 -0
  38. package/src/lib/render-help.ts +197 -0
  39. package/src/lib/version.ts +1 -1
@@ -0,0 +1,290 @@
1
+ export const globalFlags = [
2
+ {
3
+ long: 'help',
4
+ short: 'h',
5
+ description: 'Display this help guide.',
6
+ values: [],
7
+ takesValue: false,
8
+ isRequired: false,
9
+ },
10
+ {
11
+ long: 'interactive',
12
+ short: 'i',
13
+ description: 'Always prompt to review and edit properties, prefilled with the given arguments.',
14
+ values: [],
15
+ takesValue: false,
16
+ isRequired: false,
17
+ },
18
+ {
19
+ long: 'json',
20
+ short: null,
21
+ description: 'Write the response to stdout as JSON. Enabled automatically when stdout is not a terminal, disable with --no-json.',
22
+ values: [],
23
+ takesValue: false,
24
+ isRequired: false,
25
+ },
26
+ {
27
+ long: 'non-interactive',
28
+ short: 'y',
29
+ description: 'Never prompt: exit with an error if the command or any required property is missing.',
30
+ values: [],
31
+ takesValue: false,
32
+ isRequired: false,
33
+ },
34
+ {
35
+ long: 'remote-api-defs',
36
+ short: null,
37
+ description: 'Use the API definitions served by the Seam API.',
38
+ values: [],
39
+ takesValue: false,
40
+ isRequired: false,
41
+ },
42
+ {
43
+ long: 'update',
44
+ short: null,
45
+ description: 'Force an update of the cached Seam API definitions.',
46
+ values: [],
47
+ takesValue: false,
48
+ isRequired: false,
49
+ },
50
+ {
51
+ long: 'version',
52
+ short: null,
53
+ description: 'Print the CLI version.',
54
+ values: [],
55
+ takesValue: false,
56
+ isRequired: false,
57
+ },
58
+ ];
59
+ export const flagTokens = (flag) => {
60
+ const tokens = [];
61
+ if (flag.long != null)
62
+ tokens.push(`--${flag.long}`);
63
+ if (flag.short != null)
64
+ tokens.push(`-${flag.short}`);
65
+ return tokens;
66
+ };
67
+ export const getCommandSpec = (blueprint) => {
68
+ const commands = sortByPath(dedupeByPath([
69
+ ...blueprint.routes
70
+ .flatMap((route) => route.endpoints)
71
+ .map(toCommandDefinition)
72
+ // Command and flag names end up unquoted or single-quoted in shell
73
+ // scripts, so drop any the definitions should never contain rather
74
+ // than emit something a shell could read as syntax.
75
+ .filter((command) => command.path.every(isSafeToken)),
76
+ ...localCommands,
77
+ ]));
78
+ return { commands, groups: toCommandGroups(commands), globalFlags };
79
+ };
80
+ export const findCommand = (spec, path) => spec.commands.find((command) => isSamePath(command.path, path));
81
+ export const findGroup = (spec, path) => spec.groups.find((group) => isSamePath(group.path, path));
82
+ const isSamePath = (a, b) => a.length === b.length && a.every((word, index) => word === b[index]);
83
+ const stringFlag = (long, description) => ({
84
+ long,
85
+ short: null,
86
+ description,
87
+ values: [],
88
+ takesValue: true,
89
+ isRequired: false,
90
+ });
91
+ /**
92
+ * Commands handled by the CLI itself, which have no endpoint in the blueprint.
93
+ *
94
+ * Keep in sync with the command handling in `src/bin/cli.ts` and the extra
95
+ * commands offered by `interactForCommandSelection`.
96
+ */
97
+ const localCommands = [
98
+ {
99
+ path: ['completion', 'bash'],
100
+ kind: 'cli',
101
+ title: 'Print the bash completion script.',
102
+ description: '',
103
+ flags: [],
104
+ },
105
+ {
106
+ path: ['completion', 'fish'],
107
+ kind: 'cli',
108
+ title: 'Print the fish completion script.',
109
+ description: '',
110
+ flags: [],
111
+ },
112
+ {
113
+ path: ['completion', 'zsh'],
114
+ kind: 'cli',
115
+ title: 'Print the zsh completion script.',
116
+ description: '',
117
+ flags: [],
118
+ },
119
+ {
120
+ path: ['config', 'reveal-location'],
121
+ kind: 'cli',
122
+ title: 'Print the path to the CLI configuration file.',
123
+ description: '',
124
+ flags: [],
125
+ },
126
+ {
127
+ path: ['config', 'use-remote-api-defs'],
128
+ kind: 'cli',
129
+ title: 'Choose whether to use the API definitions served by Seam.',
130
+ description: '',
131
+ flags: [],
132
+ },
133
+ {
134
+ path: ['health', 'get-health'],
135
+ kind: 'api',
136
+ title: 'Report the health of the Seam API.',
137
+ description: '',
138
+ flags: [],
139
+ },
140
+ {
141
+ path: ['login'],
142
+ kind: 'cli',
143
+ title: 'Log in to Seam.',
144
+ description: 'Prompts for a personal access token unless one is passed with --token.',
145
+ flags: [
146
+ stringFlag('server', 'Seam API server to log in to.'),
147
+ stringFlag('token', 'Personal access token to log in with.'),
148
+ stringFlag('workspace-id', 'Workspace to select after logging in.'),
149
+ ],
150
+ },
151
+ {
152
+ path: ['logout'],
153
+ kind: 'cli',
154
+ title: 'Log out of Seam.',
155
+ description: '',
156
+ flags: [],
157
+ },
158
+ {
159
+ path: ['select', 'server'],
160
+ kind: 'cli',
161
+ title: 'Select the Seam API server.',
162
+ description: '',
163
+ flags: [stringFlag('server', 'Seam API server to select.')],
164
+ },
165
+ {
166
+ path: ['select', 'workspace'],
167
+ kind: 'cli',
168
+ title: 'Select the current workspace.',
169
+ description: '',
170
+ flags: [],
171
+ },
172
+ {
173
+ path: ['wizard'],
174
+ kind: 'cli',
175
+ title: 'Set up Seam in the current project.',
176
+ description: 'Takes a project from zero to a working Seam integration. Run seam wizard --help for its own options.',
177
+ flags: [],
178
+ },
179
+ ];
180
+ const toCommandDefinition = (endpoint) => {
181
+ const description = toPlainText(endpoint.description);
182
+ return {
183
+ path: toCommandPath(endpoint.path),
184
+ kind: 'api',
185
+ title: endpoint.title === ''
186
+ ? firstSentence(description)
187
+ : toPlainText(endpoint.title),
188
+ description,
189
+ flags: [...endpoint.request.parameters]
190
+ .map(toCommandFlag)
191
+ .filter((flag) => flag.long == null || isSafeToken(flag.long))
192
+ .sort((a, b) => compare(a.long ?? a.short, b.long ?? b.short)),
193
+ };
194
+ };
195
+ const toCommandFlag = (parameter) => ({
196
+ long: toFlagName(parameter.name),
197
+ short: null,
198
+ description: toPlainText(parameter.description),
199
+ values: toFlagValues(parameter),
200
+ takesValue: true,
201
+ isRequired: parameter.isRequired,
202
+ });
203
+ const toFlagValues = (parameter) => {
204
+ if (parameter.format === 'enum') {
205
+ return parameter.values.map(({ name }) => name).filter(isSafeToken);
206
+ }
207
+ if (parameter.format === 'list' && parameter.itemFormat === 'enum') {
208
+ return parameter.itemEnumValues.map(({ name }) => name).filter(isSafeToken);
209
+ }
210
+ // Nothing marks parameters as boolean-only flags, so minimist reads the next
211
+ // argument as the value.
212
+ if (parameter.format === 'boolean')
213
+ return ['true', 'false'];
214
+ return [];
215
+ };
216
+ /**
217
+ * Whether a word is safe to write into a shell script. Command, flag, and
218
+ * enum names come from the API definitions and are embedded unquoted or
219
+ * single-quoted in completion scripts, so never emit one that a shell could
220
+ * read as syntax.
221
+ */
222
+ const isSafeToken = (token) => /^[\w.:@/+-]+$/.test(token);
223
+ const toCommandGroups = (commands) => {
224
+ const groups = new Map();
225
+ for (const command of commands) {
226
+ for (const [depth, name] of command.path.entries()) {
227
+ const key = command.path.slice(0, depth).join(' ');
228
+ const entries = groups.get(key) ?? new Map();
229
+ groups.set(key, entries);
230
+ // An entry is an API command if any command it holds calls the API.
231
+ const kind = command.kind === 'api' ? 'api' : (entries.get(name)?.kind ?? 'cli');
232
+ // A command and a group may share a name, e.g., a hypothetical
233
+ // `seam devices` alongside `seam devices list`. Prefer the command
234
+ // title, since it describes what running the name does.
235
+ if (depth === command.path.length - 1) {
236
+ entries.set(name, { isCommand: true, kind, description: command.title });
237
+ continue;
238
+ }
239
+ const entry = entries.get(name);
240
+ entries.set(name, {
241
+ isCommand: entry?.isCommand ?? false,
242
+ kind,
243
+ description: entry?.description ?? '',
244
+ });
245
+ }
246
+ }
247
+ // Groups have no description of their own in the API definitions, so name
248
+ // the commands they hold instead. Leave the list whole: help wraps it, and
249
+ // completion shortens it to fit a menu column.
250
+ const summarizeGroup = (key) => [...(groups.get(key)?.keys() ?? [])].join(', ');
251
+ return [...groups]
252
+ .map(([key, entries]) => ({
253
+ path: key === '' ? [] : key.split(' '),
254
+ subcommands: [...entries]
255
+ .map(([name, entry]) => ({
256
+ name,
257
+ kind: entry.kind,
258
+ description: entry.isCommand
259
+ ? entry.description
260
+ : summarizeGroup(key === '' ? name : `${key} ${name}`),
261
+ }))
262
+ .sort((a, b) => compare(a.name, b.name)),
263
+ }))
264
+ .sort((a, b) => compare(a.path.join(' '), b.path.join(' ')));
265
+ };
266
+ const dedupeByPath = (commands) => {
267
+ const byPath = new Map();
268
+ for (const command of commands) {
269
+ const key = command.path.join(' ');
270
+ if (byPath.has(key))
271
+ continue;
272
+ byPath.set(key, command);
273
+ }
274
+ return [...byPath.values()];
275
+ };
276
+ const sortByPath = (commands) => [...commands].sort((a, b) => compare(a.path.join(' '), b.path.join(' ')));
277
+ const compare = (a, b) => (a ?? '') < (b ?? '') ? -1 : (a ?? '') > (b ?? '') ? 1 : 0;
278
+ const toCommandPath = (path) => path.replace(/^\//, '').split('/').map(toFlagName);
279
+ const toFlagName = (name) => name.replace(/_/g, '-');
280
+ /** Reduce documentation markdown to a single line of prose. */
281
+ export const toPlainText = (markdown) => markdown
282
+ .replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
283
+ .replace(/[`*]/g, '')
284
+ .replace(/\s+/g, ' ')
285
+ .trim();
286
+ export const firstSentence = (text) => {
287
+ const [sentence] = text.split(/(?<=\.)\s/);
288
+ return sentence ?? text;
289
+ };
290
+ //# sourceMappingURL=command-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-spec.js","sourceRoot":"","sources":["../src/lib/command-spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Reduce a description to one short line that is safe to embed in a
3
+ * single-quoted shell string.
4
+ *
5
+ * Completion menus give a description a single narrow column, and the shells
6
+ * offer no way to escape a quote inside the generated scripts, so drop any
7
+ * character that would end the string early. A colon goes too, since zsh reads
8
+ * it as the separator in a `_describe` entry.
9
+ */
10
+ export declare const describeForShell: (description: string) => string;
@@ -0,0 +1,16 @@
1
+ import { firstSentence } from '../command-spec.js';
2
+ import { ellipsis } from '../util/ellipsis.js';
3
+ const maxDescriptionLength = 72;
4
+ /**
5
+ * Reduce a description to one short line that is safe to embed in a
6
+ * single-quoted shell string.
7
+ *
8
+ * Completion menus give a description a single narrow column, and the shells
9
+ * offer no way to escape a quote inside the generated scripts, so drop any
10
+ * character that would end the string early. A colon goes too, since zsh reads
11
+ * it as the separator in a `_describe` entry.
12
+ */
13
+ export const describeForShell = (description) => ellipsis(firstSentence(description)
14
+ .replace(/['"`$\\:]/g, '')
15
+ .trim(), maxDescriptionLength);
16
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/lib/completion/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,MAAM,oBAAoB,GAAG,EAAE,CAAA;AAE/B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAmB,EAAU,EAAE,CAC9D,QAAQ,CACN,aAAa,CAAC,WAAW,CAAC;KACvB,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;KACzB,IAAI,EAAE,EACT,oBAAoB,CACrB,CAAA"}
@@ -0,0 +1,28 @@
1
+ import type { Blueprint } from '@seamapi/blueprint';
2
+ export declare const completionShells: readonly ["bash", "fish", "zsh"];
3
+ export type CompletionShell = (typeof completionShells)[number];
4
+ export declare const isCompletionShell: (shell: unknown) => shell is CompletionShell;
5
+ /** File name to install the completion script for each shell as. */
6
+ export declare const completionFileNames: Record<CompletionShell, string>;
7
+ export declare const renderCompletion: (shell: CompletionShell, blueprint: Blueprint) => string;
8
+ /**
9
+ * Render the completion loader installed by system packages.
10
+ *
11
+ * The loader runs 'seam completion' the first time the shell completes a seam
12
+ * command, so installed completions always match the CLI's current Seam API
13
+ * definitions instead of the definitions packaged at release time. Each shell
14
+ * loads its completion file on demand, so the CLI runs once per shell session
15
+ * at first completion, never at shell startup.
16
+ *
17
+ * The loader degrades to no completions when the seam command is missing or
18
+ * does not produce a completion script: a script is only evaluated when it
19
+ * starts with the exact first line 'seam completion' generates, so nothing
20
+ * else the CLI may print, e.g., 'Not logged in' from a version without the
21
+ * completion command, is ever evaluated as shell code.
22
+ */
23
+ export declare const renderCompletionStub: (shell: CompletionShell) => string;
24
+ /**
25
+ * First line of each generated completion script, which the loaders require
26
+ * before evaluating one. Must match the output of {@link renderCompletion}.
27
+ */
28
+ export declare const completionScriptSentinels: Record<CompletionShell, string>;
@@ -0,0 +1,92 @@
1
+ import { getCommandSpec } from '../command-spec.js';
2
+ import { renderBashCompletion } from './render-bash.js';
3
+ import { renderFishCompletion } from './render-fish.js';
4
+ import { renderZshCompletion } from './render-zsh.js';
5
+ export const completionShells = ['bash', 'fish', 'zsh'];
6
+ export const isCompletionShell = (shell) => completionShells.includes(shell);
7
+ /** File name to install the completion script for each shell as. */
8
+ export const completionFileNames = {
9
+ bash: 'seam.bash',
10
+ fish: 'seam.fish',
11
+ zsh: 'seam.zsh',
12
+ };
13
+ const renderers = {
14
+ bash: renderBashCompletion,
15
+ fish: renderFishCompletion,
16
+ zsh: renderZshCompletion,
17
+ };
18
+ export const renderCompletion = (shell, blueprint) => renderers[shell](getCommandSpec(blueprint));
19
+ /**
20
+ * Render the completion loader installed by system packages.
21
+ *
22
+ * The loader runs 'seam completion' the first time the shell completes a seam
23
+ * command, so installed completions always match the CLI's current Seam API
24
+ * definitions instead of the definitions packaged at release time. Each shell
25
+ * loads its completion file on demand, so the CLI runs once per shell session
26
+ * at first completion, never at shell startup.
27
+ *
28
+ * The loader degrades to no completions when the seam command is missing or
29
+ * does not produce a completion script: a script is only evaluated when it
30
+ * starts with the exact first line 'seam completion' generates, so nothing
31
+ * else the CLI may print, e.g., 'Not logged in' from a version without the
32
+ * completion command, is ever evaluated as shell code.
33
+ */
34
+ export const renderCompletionStub = (shell) => stubs[shell];
35
+ /**
36
+ * First line of each generated completion script, which the loaders require
37
+ * before evaluating one. Must match the output of {@link renderCompletion}.
38
+ */
39
+ export const completionScriptSentinels = {
40
+ bash: '# bash completion for the seam command.',
41
+ fish: '# fish completion for the seam command.',
42
+ zsh: '#compdef seam',
43
+ };
44
+ const stubHeader = (shell) => `# ${shell} completion loader for the seam command.
45
+ #
46
+ # Generated by @seamapi/cli. Loads completions from the CLI on first use, so
47
+ # they always match the CLI's current Seam API definitions. Requires the seam
48
+ # command on PATH. Print the underlying script with 'seam completion ${shell}'.`;
49
+ const stubs = {
50
+ bash: `${stubHeader('bash')}
51
+ #
52
+ # Install to /usr/share/bash-completion/completions/seam
53
+
54
+ if command -v seam > /dev/null 2>&1; then
55
+ __seam_completion_script="$(seam completion bash 2> /dev/null)"
56
+ # Evaluate only a completion script, never anything else the CLI printed.
57
+ case "$__seam_completion_script" in
58
+ '${completionScriptSentinels.bash}'*) eval "$__seam_completion_script" ;;
59
+ esac
60
+ unset __seam_completion_script
61
+ fi
62
+ `,
63
+ fish: `${stubHeader('fish')}
64
+ #
65
+ # Install to /usr/share/fish/vendor_completions.d/seam.fish
66
+
67
+ if command --query seam
68
+ set -l __seam_completion_script (seam completion fish 2> /dev/null | string collect)
69
+ # Source only a completion script, never anything else the CLI printed.
70
+ if string match --quiet '${completionScriptSentinels.fish}*' -- $__seam_completion_script
71
+ printf '%s\\n' $__seam_completion_script | source
72
+ end
73
+ end
74
+ `,
75
+ zsh: `#compdef seam
76
+ ${stubHeader('zsh')}
77
+ #
78
+ # Install to a directory in fpath as _seam
79
+
80
+ local __seam_completion_script
81
+ __seam_completion_script="$(seam completion zsh 2> /dev/null)"
82
+
83
+ # Evaluate only a completion script, never anything else the CLI printed.
84
+ # The script ends by dispatching on funcstack, so evaluating it while this
85
+ # autoloaded _seam runs both redefines _seam and completes the in-flight
86
+ # request.
87
+ if [[ "$__seam_completion_script" == '${completionScriptSentinels.zsh}'* ]]; then
88
+ eval "$__seam_completion_script"
89
+ fi
90
+ `,
91
+ };
92
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/completion/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAU,CAAA;AAIhE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAA4B,EAAE,CAC5E,gBAAgB,CAAC,QAAQ,CAAC,KAAwB,CAAC,CAAA;AAErD,oEAAoE;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAoC;IAClE,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,UAAU;CAChB,CAAA;AAED,MAAM,SAAS,GAA2D;IACxE,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE,oBAAoB;IAC1B,GAAG,EAAE,mBAAmB;CACzB,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAsB,EACtB,SAAoB,EACZ,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;AAExD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAsB,EAAU,EAAE,CACrE,KAAK,CAAC,KAAK,CAAC,CAAA;AAEd;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAoC;IACxE,IAAI,EAAE,yCAAyC;IAC/C,IAAI,EAAE,yCAAyC;IAC/C,GAAG,EAAE,eAAe;CACrB,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAU,EAAE,CACpD,KAAK,KAAK;;;;uEAI2D,KAAK,IAAI,CAAA;AAEhF,MAAM,KAAK,GAAoC;IAC7C,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC;;;;;;;;OAQtB,yBAAyB,CAAC,IAAI;;;;CAIpC;IACC,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC;;;;;;;+BAOE,yBAAyB,CAAC,IAAI;;;;CAI5D;IACC,GAAG,EAAE;EACL,UAAU,CAAC,KAAK,CAAC;;;;;;;;;;;wCAWqB,yBAAyB,CAAC,GAAG;;;CAGpE;CACA,CAAA"}
@@ -0,0 +1,2 @@
1
+ import { type CommandSpec } from '../command-spec.js';
2
+ export declare const renderBashCompletion: (spec: CommandSpec) => string;
@@ -0,0 +1,98 @@
1
+ import { flagTokens, } from '../command-spec.js';
2
+ export const renderBashCompletion = (spec) => {
3
+ const globalTokens = spec.globalFlags.flatMap(flagTokens).sort();
4
+ const valuelessTokens = spec.globalFlags
5
+ .filter(({ takesValue }) => !takesValue)
6
+ .flatMap(flagTokens)
7
+ .sort();
8
+ return `${[
9
+ header,
10
+ `_seam_global_flags='${globalTokens.join(' ')}'`,
11
+ `_seam_valueless_flags=' ${valuelessTokens.join(' ')} '`,
12
+ renderCase('_seam_subcommands', subcommandBranches(spec)),
13
+ renderCase('_seam_flags', flagBranches(spec)),
14
+ renderCase('_seam_flag_values', flagValueBranches(spec)),
15
+ completionFunction,
16
+ 'complete -F _seam_completion seam',
17
+ ].join('\n\n')}\n`;
18
+ };
19
+ const header = `# bash completion for the seam command.
20
+ #
21
+ # Generated by @seamapi/cli from the Seam API definitions.
22
+ # Do not edit: regenerate with 'seam completion bash'.
23
+ #
24
+ # Load it for the current shell with
25
+ #
26
+ # source <(seam completion bash)
27
+ #
28
+ # or install it for every shell with
29
+ #
30
+ # seam completion bash > /usr/share/bash-completion/completions/seam`;
31
+ const completionFunction = `_seam_completion() {
32
+ local current previous word command subcommands
33
+ local -i index
34
+
35
+ current="\${COMP_WORDS[COMP_CWORD]}"
36
+ previous=''
37
+ if (( COMP_CWORD > 0 )); then
38
+ previous="\${COMP_WORDS[COMP_CWORD - 1]}"
39
+ fi
40
+
41
+ # --flag=value splits into three words under the default word breaks.
42
+ if [[ "$previous" == '=' ]] && (( COMP_CWORD > 1 )); then
43
+ previous="\${COMP_WORDS[COMP_CWORD - 2]}"
44
+ fi
45
+
46
+ # The command path is the run of words before the first flag.
47
+ command=''
48
+ for (( index = 1; index < COMP_CWORD; index++ )); do
49
+ word="\${COMP_WORDS[index]}"
50
+ if [[ "$word" == -* ]]; then
51
+ break
52
+ fi
53
+ command="\${command:+$command }$word"
54
+ done
55
+
56
+ # Completing the value of a flag that takes one.
57
+ if [[ "$previous" == -* && "$_seam_valueless_flags" != *" $previous "* ]]; then
58
+ COMPREPLY=( $(compgen -W "$(_seam_flag_values "$command $previous")" -- "$current") )
59
+ return 0
60
+ fi
61
+
62
+ if [[ "$current" == -* ]]; then
63
+ COMPREPLY=( $(compgen -W "$(_seam_flags "$command") $_seam_global_flags" -- "$current") )
64
+ return 0
65
+ fi
66
+
67
+ subcommands="$(_seam_subcommands "$command")"
68
+ if [[ -z "$subcommands" ]]; then
69
+ COMPREPLY=( $(compgen -W "$(_seam_flags "$command") $_seam_global_flags" -- "$current") )
70
+ return 0
71
+ fi
72
+
73
+ COMPREPLY=( $(compgen -W "$subcommands" -- "$current") )
74
+ return 0
75
+ }`;
76
+ const subcommandBranches = (spec) => spec.groups.map((group) => ({
77
+ pattern: group.path.join(' '),
78
+ words: group.subcommands.map(({ name }) => name),
79
+ }));
80
+ const flagBranches = (spec) => spec.commands
81
+ .filter(({ flags }) => flags.length > 0)
82
+ .map((command) => ({
83
+ pattern: command.path.join(' '),
84
+ words: command.flags.flatMap(flagTokens),
85
+ }));
86
+ const flagValueBranches = (spec) => spec.commands.flatMap((command) => command.flags.filter(hasValues).flatMap((flag) => flagTokens(flag).map((token) => ({
87
+ pattern: `${command.path.join(' ')} ${token}`,
88
+ words: flag.values,
89
+ }))));
90
+ const hasValues = (flag) => flag.values.length > 0;
91
+ const renderCase = (name, branches) => [
92
+ `${name}() {`,
93
+ ` case "$1" in`,
94
+ ...branches.map(({ pattern, words }) => ` '${pattern}') echo '${words.join(' ')}' ;;`),
95
+ ` esac`,
96
+ `}`,
97
+ ].join('\n');
98
+ //# sourceMappingURL=render-bash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-bash.js","sourceRoot":"","sources":["../../src/lib/completion/render-bash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CommandSpec } from '../command-spec.js';
2
+ export declare const renderFishCompletion: (spec: CommandSpec) => string;
@@ -0,0 +1,58 @@
1
+ import { describeForShell } from './describe.js';
2
+ export const renderFishCompletion = (spec) => `${[
3
+ header,
4
+ helpers,
5
+ ['complete -c seam -f', ...subcommandCompletions(spec)].join('\n'),
6
+ flagCompletions(spec).join('\n'),
7
+ globalFlagCompletions(spec).join('\n'),
8
+ ].join('\n\n')}\n`;
9
+ const header = `# fish completion for the seam command.
10
+ #
11
+ # Generated by @seamapi/cli from the Seam API definitions.
12
+ # Do not edit: regenerate with 'seam completion fish'.
13
+ #
14
+ # Install it with
15
+ #
16
+ # seam completion fish > ~/.config/fish/completions/seam.fish`;
17
+ const helpers = `function __seam_command --description 'Print the seam command path on the command line'
18
+ set -l tokens (commandline -opc)
19
+ set -l command
20
+ if test (count $tokens) -gt 1
21
+ # The command path is the run of words before the first flag.
22
+ for token in $tokens[2..-1]
23
+ if string match -q -- '-*' $token
24
+ break
25
+ end
26
+ set -a command $token
27
+ end
28
+ end
29
+ string join ' ' -- $command
30
+ end
31
+
32
+ function __seam_using --description 'Test whether the command line names the given seam command'
33
+ set -l command (__seam_command)
34
+ test "$command" = "$argv[1]"
35
+ end`;
36
+ const subcommandCompletions = (spec) => spec.groups.flatMap((group) => group.subcommands.map(({ name, description }) => complete([
37
+ `-n '__seam_using "${group.path.join(' ')}"'`,
38
+ `-a '${name}'`,
39
+ describe(description),
40
+ ])));
41
+ const flagCompletions = (spec) => spec.commands.flatMap((command) => command.flags.map((flag) => complete([
42
+ `-n '__seam_using "${command.path.join(' ')}"'`,
43
+ ...flagOptions(flag),
44
+ ])));
45
+ const globalFlagCompletions = (spec) => spec.globalFlags.map((flag) => complete(flagOptions(flag)));
46
+ const flagOptions = (flag) => [
47
+ ...(flag.short == null ? [] : [`-s ${flag.short}`]),
48
+ ...(flag.long == null ? [] : [`-l ${flag.long}`]),
49
+ ...(flag.takesValue ? ['-r'] : []),
50
+ ...(flag.values.length === 0 ? [] : [`-a '${flag.values.join(' ')}'`]),
51
+ describe(flag.description),
52
+ ];
53
+ const describe = (description) => {
54
+ const summary = describeForShell(description);
55
+ return summary === '' ? '' : `-d '${summary}'`;
56
+ };
57
+ const complete = (options) => ['complete -c seam', ...options.filter((option) => option !== '')].join(' ');
58
+ //# sourceMappingURL=render-fish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-fish.js","sourceRoot":"","sources":["../../src/lib/completion/render-fish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type CommandSpec } from '../command-spec.js';
2
+ export declare const renderZshCompletion: (spec: CommandSpec) => string;