@xyd-js/opencli-completion 0.0.0-build-b7bd05c-20260701151111

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) LiveSession Sp.z.o.o
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,34 @@
1
+ # @xyd-js/opencli-completion
2
+
3
+ Generate shell completion scripts from an [OpenCLI](https://opencli.org) document. The "tree"
4
+ the generators walk **is an OpenCLI doc** — so any CLI that can describe itself as OpenCLI gets
5
+ real shell completions for free.
6
+
7
+ ```ts
8
+ import { zsh, fish, completion } from '@xyd-js/opencli-completion';
9
+
10
+ zsh(opencliSpec); // → a `#compdef` zsh script
11
+ fish(opencliSpec); // → a fish completion script
12
+ completion(opencliSpec, sh); // → dispatch by shell ('zsh' | 'fish')
13
+ ```
14
+
15
+ ## Mapping
16
+
17
+ | OpenCLI | Completion |
18
+ |---|---|
19
+ | `info.title` | the command name (`#compdef <name>`, `complete -c <name>`) |
20
+ | `commands[]` (recursive) | completable subcommands |
21
+ | a command's `options[]` | completable flags (`--name` + `aliases` → `-x` / `--xy`) |
22
+ | an option with `arguments[]` | a value-taking flag (`-r` in fish, `:value:` in zsh) |
23
+ | root `options` with `recursive: true` | global flags, offered on every command |
24
+
25
+ Adapted from the static fish/zsh generation approach (no runtime completion daemon); the OpenCLI
26
+ document is the single source of truth.
27
+
28
+ ## Limitations
29
+
30
+ - The zsh generator completes the root and one level of subcommands (fish recurses deeper); deeply
31
+ nested command trees aren't fully expanded yet.
32
+ - Positional `arguments` and `acceptedValues` (enum) aren't turned into value completions yet — only
33
+ subcommands and flags complete. Flags that take a value are marked (`-r` / `:value:`) but their
34
+ values aren't enumerated.
package/dist/index.cjs ADDED
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ completion: () => completion,
24
+ fish: () => fish,
25
+ opencliToTree: () => opencliToTree,
26
+ zsh: () => zsh
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/flags.ts
31
+ function splitFlags(flags) {
32
+ const short = [];
33
+ const long = [];
34
+ const old = [];
35
+ for (const f of flags) {
36
+ if (f.startsWith("--")) long.push(f.slice(2));
37
+ else if (f.startsWith("-") && f.length === 2) short.push(f.slice(1));
38
+ else if (f.startsWith("-")) old.push(f.slice(1));
39
+ }
40
+ return { short, long, old };
41
+ }
42
+
43
+ // src/tree.ts
44
+ function opencliToTree(spec) {
45
+ var _a, _b;
46
+ const name = ((_a = spec.info) == null ? void 0 : _a.title) || "cli";
47
+ const rootOptions = (spec.options || []).filter((o) => !o.hidden);
48
+ const globalOptions = rootOptions.filter((o) => o.recursive);
49
+ const commandNode = (cmd) => ({
50
+ name: cmd.name,
51
+ description: cmd.description,
52
+ options: [
53
+ ...(cmd.options || []).filter((o) => !o.hidden).map(optionToCompletion),
54
+ ...globalOptions.map(optionToCompletion)
55
+ ],
56
+ commands: toNodeMap(cmd.commands, commandNode)
57
+ });
58
+ return {
59
+ name,
60
+ description: (_b = spec.info) == null ? void 0 : _b.description,
61
+ options: rootOptions.map(optionToCompletion),
62
+ commands: toNodeMap(spec.commands, commandNode)
63
+ };
64
+ }
65
+ function toNodeMap(commands, node) {
66
+ return Object.fromEntries((commands || []).filter((c) => !c.hidden).map((c) => [c.name, node(c)]));
67
+ }
68
+ function optionToCompletion(opt) {
69
+ var _a;
70
+ const flags = [`--${opt.name}`, ...(opt.aliases || []).map((a) => a.length === 1 ? `-${a}` : `--${a}`)];
71
+ return { flags, takesValue: (((_a = opt.arguments) == null ? void 0 : _a.length) ?? 0) > 0, description: opt.description };
72
+ }
73
+
74
+ // src/fish.ts
75
+ var escFish = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
76
+ function fish(spec) {
77
+ const tree = opencliToTree(spec);
78
+ const cmd = tree.name;
79
+ const lines = [`# fish completions for ${cmd} (generated - do not edit)`];
80
+ const walk = (node, path) => {
81
+ const cond = path.length === 0 ? "__fish_use_subcommand" : path.map((p) => `__fish_seen_subcommand_from ${p}`).join("; and ");
82
+ const subs = Object.values(node.commands);
83
+ for (const sub of subs) {
84
+ const d = sub.description ? ` -d '${escFish(sub.description)}'` : "";
85
+ lines.push(`complete -c ${cmd} -n "${cond}" -f -a "${sub.name}"${d}`);
86
+ }
87
+ for (const opt of node.options) {
88
+ const { short, long, old } = splitFlags(opt.flags);
89
+ const parts = [...short.map((s) => `-s ${s}`), ...long.map((l) => `-l ${l}`), ...old.map((o) => `-o ${o}`)].join(" ");
90
+ const r = opt.takesValue ? " -r" : "";
91
+ const d = opt.description ? ` -d '${escFish(opt.description)}'` : "";
92
+ lines.push(`complete -c ${cmd} -n "${cond}" ${parts}${r}${d}`);
93
+ }
94
+ for (const sub of subs) walk(sub, [...path, sub.name]);
95
+ };
96
+ walk(tree, []);
97
+ return `${lines.join("\n")}
98
+ `;
99
+ }
100
+
101
+ // src/zsh.ts
102
+ var escZshSpec = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/[:[\]{}]/g, (c) => `\\${c}`);
103
+ var escZshDescribe = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/:/g, "\\:");
104
+ function optToSpec(opt) {
105
+ const { short, long } = splitFlags(opt.flags);
106
+ const desc = opt.description ? `[${escZshSpec(opt.description)}]` : "";
107
+ const value = opt.takesValue ? ":value:" : "";
108
+ const all = [...short.map((s) => `-${s}`), ...long.map((l) => `--${l}`)];
109
+ if (all.length >= 2) {
110
+ return `'(${all.join(" ")})'{${all.join(",")}}'${desc}${value}'`;
111
+ }
112
+ return `'${all[0]}${desc}${value}'`;
113
+ }
114
+ function zsh(spec) {
115
+ const tree = opencliToTree(spec);
116
+ const cmd = tree.name;
117
+ const subs = Object.values(tree.commands);
118
+ const hasSubs = subs.length > 0;
119
+ const out = [`#compdef ${cmd}`, "", `_${cmd}() {`];
120
+ out.push(" local context state state_descr line");
121
+ out.push(" typeset -A opt_args");
122
+ out.push("");
123
+ const rootSpecs = tree.options.map(optToSpec);
124
+ if (hasSubs) {
125
+ rootSpecs.push("'1: :->command'");
126
+ rootSpecs.push("'*::arg:->args'");
127
+ }
128
+ out.push(" _arguments -C \\");
129
+ out.push(`${rootSpecs.map((s) => ` ${s}`).join(" \\\n")} && return 0`);
130
+ if (hasSubs) {
131
+ out.push("");
132
+ out.push(" case $state in");
133
+ out.push(" command)");
134
+ out.push(" local -a commands");
135
+ out.push(" commands=(");
136
+ for (const sub of subs) {
137
+ out.push(` '${sub.name}:${escZshDescribe(sub.description || "")}'`);
138
+ }
139
+ out.push(" )");
140
+ out.push(` _describe -t commands '${cmd} command' commands`);
141
+ out.push(" ;;");
142
+ out.push(" args)");
143
+ out.push(" case $line[1] in");
144
+ for (const sub of subs) {
145
+ out.push(` ${sub.name})`);
146
+ const specs = sub.options.map(optToSpec);
147
+ if (specs.length) {
148
+ out.push(" _arguments \\");
149
+ out.push(specs.map((s) => ` ${s}`).join(" \\\n"));
150
+ } else {
151
+ out.push(" _message 'no more arguments'");
152
+ }
153
+ out.push(" ;;");
154
+ }
155
+ out.push(" esac");
156
+ out.push(" ;;");
157
+ out.push(" esac");
158
+ }
159
+ out.push("}");
160
+ out.push("");
161
+ out.push(`_${cmd} "$@"`);
162
+ return `${out.join("\n")}
163
+ `;
164
+ }
165
+
166
+ // src/index.ts
167
+ function completion(spec, shell) {
168
+ switch (shell) {
169
+ case "fish":
170
+ return fish(spec);
171
+ default:
172
+ return zsh(spec);
173
+ }
174
+ }
175
+ // Annotate the CommonJS export names for ESM import in node:
176
+ 0 && (module.exports = {
177
+ completion,
178
+ fish,
179
+ opencliToTree,
180
+ zsh
181
+ });
182
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts","../src/flags.ts","../src/tree.ts","../src/fish.ts","../src/zsh.ts","../src/index.ts"],"sourcesContent":["export * from './src';\n","/** Split flag spellings into short (`-x`), long (`--xy`) and old-style (`-xy`). */\nexport function splitFlags(flags: string[]): { short: string[]; long: string[]; old: string[] } {\n const short: string[] = [];\n const long: string[] = [];\n const old: string[] = [];\n for (const f of flags) {\n if (f.startsWith('--')) long.push(f.slice(2));\n else if (f.startsWith('-') && f.length === 2) short.push(f.slice(1));\n else if (f.startsWith('-')) old.push(f.slice(1));\n }\n return { short, long, old };\n}\n","import type { Command, OpencliSpecJson, Option } from '@xyd-js/opencli';\n\nimport type { CompletionNode, CompletionOption } from './types';\n\n/**\n * Adapt an OpenCLI document into the command tree the shell generators walk.\n * Root-level `recursive` options (a CLI's global flags) are made available on\n * every command, so they complete in any subcommand context too.\n */\nexport function opencliToTree(spec: OpencliSpecJson): CompletionNode {\n const name = spec.info?.title || 'cli';\n const rootOptions = (spec.options || []).filter((o) => !o.hidden);\n const globalOptions = rootOptions.filter((o) => o.recursive);\n\n const commandNode = (cmd: Command): CompletionNode => ({\n name: cmd.name,\n description: cmd.description,\n options: [\n ...(cmd.options || []).filter((o) => !o.hidden).map(optionToCompletion),\n ...globalOptions.map(optionToCompletion),\n ],\n commands: toNodeMap(cmd.commands, commandNode),\n });\n\n return {\n name,\n description: spec.info?.description,\n options: rootOptions.map(optionToCompletion),\n commands: toNodeMap(spec.commands, commandNode),\n };\n}\n\nfunction toNodeMap(commands: Command[] | undefined, node: (c: Command) => CompletionNode): Record<string, CompletionNode> {\n return Object.fromEntries((commands || []).filter((c) => !c.hidden).map((c) => [c.name, node(c)]));\n}\n\nfunction optionToCompletion(opt: Option): CompletionOption {\n // OpenCLI option `name` is the canonical long form; aliases may be short or long.\n const flags = [`--${opt.name}`, ...(opt.aliases || []).map((a) => (a.length === 1 ? `-${a}` : `--${a}`))];\n return { flags, takesValue: (opt.arguments?.length ?? 0) > 0, description: opt.description };\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { splitFlags } from './flags';\nimport { opencliToTree } from './tree';\nimport type { CompletionNode } from './types';\n\nconst escFish = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Generate a fish completion script from an OpenCLI document. */\nexport function fish(spec: OpencliSpecJson): string {\n const tree = opencliToTree(spec);\n const cmd = tree.name;\n const lines = [`# fish completions for ${cmd} (generated - do not edit)`];\n\n const walk = (node: CompletionNode, path: string[]) => {\n const cond =\n path.length === 0\n ? '__fish_use_subcommand'\n : path.map((p) => `__fish_seen_subcommand_from ${p}`).join('; and ');\n\n const subs = Object.values(node.commands);\n for (const sub of subs) {\n const d = sub.description ? ` -d '${escFish(sub.description)}'` : '';\n lines.push(`complete -c ${cmd} -n \"${cond}\" -f -a \"${sub.name}\"${d}`);\n }\n for (const opt of node.options) {\n const { short, long, old } = splitFlags(opt.flags);\n const parts = [...short.map((s) => `-s ${s}`), ...long.map((l) => `-l ${l}`), ...old.map((o) => `-o ${o}`)].join(' ');\n const r = opt.takesValue ? ' -r' : '';\n const d = opt.description ? ` -d '${escFish(opt.description)}'` : '';\n lines.push(`complete -c ${cmd} -n \"${cond}\" ${parts}${r}${d}`);\n }\n for (const sub of subs) walk(sub, [...path, sub.name]);\n };\n\n walk(tree, []);\n return `${lines.join('\\n')}\\n`;\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { splitFlags } from './flags';\nimport { opencliToTree } from './tree';\nimport type { CompletionOption } from './types';\n\n// Inside an `_arguments` spec's `[...]` description: escape backslash, single\n// quote, and the chars that are syntactically special there (`:` `[` `]` `{` `}`).\nconst escZshSpec = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"'\\\\''\")\n .replace(/[:[\\]{}]/g, (c) => `\\\\${c}`);\n\n// Inside a `_describe` `'value:desc'` row only the `:` separator (plus quote /\n// backslash) is special — brackets/braces are literal.\nconst escZshDescribe = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"'\\\\''\").replace(/:/g, '\\\\:');\n\nfunction optToSpec(opt: CompletionOption): string {\n const { short, long } = splitFlags(opt.flags);\n const desc = opt.description ? `[${escZshSpec(opt.description)}]` : '';\n const value = opt.takesValue ? ':value:' : '';\n const all = [...short.map((s) => `-${s}`), ...long.map((l) => `--${l}`)];\n if (all.length >= 2) {\n return `'(${all.join(' ')})'{${all.join(',')}}'${desc}${value}'`;\n }\n return `'${all[0]}${desc}${value}'`;\n}\n\n/** Generate a zsh completion script (`#compdef`) from an OpenCLI document. */\nexport function zsh(spec: OpencliSpecJson): string {\n const tree = opencliToTree(spec);\n const cmd = tree.name;\n const subs = Object.values(tree.commands);\n const hasSubs = subs.length > 0;\n const out = [`#compdef ${cmd}`, '', `_${cmd}() {`];\n\n out.push(' local context state state_descr line');\n out.push(' typeset -A opt_args');\n out.push('');\n\n const rootSpecs = tree.options.map(optToSpec);\n if (hasSubs) {\n rootSpecs.push(\"'1: :->command'\");\n rootSpecs.push(\"'*::arg:->args'\");\n }\n out.push(' _arguments -C \\\\');\n out.push(`${rootSpecs.map((s) => ` ${s}`).join(' \\\\\\n')} && return 0`);\n\n if (hasSubs) {\n out.push('');\n out.push(' case $state in');\n out.push(' command)');\n out.push(' local -a commands');\n out.push(' commands=(');\n for (const sub of subs) {\n out.push(` '${sub.name}:${escZshDescribe(sub.description || '')}'`);\n }\n out.push(' )');\n out.push(` _describe -t commands '${cmd} command' commands`);\n out.push(' ;;');\n out.push(' args)');\n out.push(' case $line[1] in');\n for (const sub of subs) {\n out.push(` ${sub.name})`);\n const specs = sub.options.map(optToSpec);\n if (specs.length) {\n out.push(' _arguments \\\\');\n out.push(specs.map((s) => ` ${s}`).join(' \\\\\\n'));\n } else {\n out.push(\" _message 'no more arguments'\");\n }\n out.push(' ;;');\n }\n out.push(' esac');\n out.push(' ;;');\n out.push(' esac');\n }\n\n out.push('}');\n out.push('');\n out.push(`_${cmd} \"$@\"`);\n return `${out.join('\\n')}\\n`;\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { fish } from './fish';\nimport type { Shell } from './types';\nimport { zsh } from './zsh';\n\nexport { fish } from './fish';\nexport { zsh } from './zsh';\nexport { opencliToTree } from './tree';\nexport type { Shell, CompletionNode, CompletionOption } from './types';\n\n/** Generate a completion script for the given shell from an OpenCLI document. */\nexport function completion(spec: OpencliSpecJson, shell: Shell): string {\n switch (shell) {\n case 'fish':\n return fish(spec);\n default:\n return zsh(spec);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,37 @@
1
+ import { OpencliSpecJson } from '@xyd-js/opencli';
2
+
3
+ type Shell = 'zsh' | 'fish';
4
+ /** A flag/option, normalized for completion generation. */
5
+ interface CompletionOption {
6
+ /** Flag spellings, e.g. `['-h', '--help']`. */
7
+ flags: string[];
8
+ /** Whether the flag consumes a value (`--port <n>`) vs. a switch. */
9
+ takesValue: boolean;
10
+ description?: string;
11
+ }
12
+ /** A command node (the CLI root or a subcommand) the generators walk. */
13
+ interface CompletionNode {
14
+ name: string;
15
+ description?: string;
16
+ options: CompletionOption[];
17
+ /** Subcommands keyed by name. */
18
+ commands: Record<string, CompletionNode>;
19
+ }
20
+
21
+ /** Generate a fish completion script from an OpenCLI document. */
22
+ declare function fish(spec: OpencliSpecJson): string;
23
+
24
+ /** Generate a zsh completion script (`#compdef`) from an OpenCLI document. */
25
+ declare function zsh(spec: OpencliSpecJson): string;
26
+
27
+ /**
28
+ * Adapt an OpenCLI document into the command tree the shell generators walk.
29
+ * Root-level `recursive` options (a CLI's global flags) are made available on
30
+ * every command, so they complete in any subcommand context too.
31
+ */
32
+ declare function opencliToTree(spec: OpencliSpecJson): CompletionNode;
33
+
34
+ /** Generate a completion script for the given shell from an OpenCLI document. */
35
+ declare function completion(spec: OpencliSpecJson, shell: Shell): string;
36
+
37
+ export { type CompletionNode, type CompletionOption, type Shell, completion, fish, opencliToTree, zsh };
@@ -0,0 +1,37 @@
1
+ import { OpencliSpecJson } from '@xyd-js/opencli';
2
+
3
+ type Shell = 'zsh' | 'fish';
4
+ /** A flag/option, normalized for completion generation. */
5
+ interface CompletionOption {
6
+ /** Flag spellings, e.g. `['-h', '--help']`. */
7
+ flags: string[];
8
+ /** Whether the flag consumes a value (`--port <n>`) vs. a switch. */
9
+ takesValue: boolean;
10
+ description?: string;
11
+ }
12
+ /** A command node (the CLI root or a subcommand) the generators walk. */
13
+ interface CompletionNode {
14
+ name: string;
15
+ description?: string;
16
+ options: CompletionOption[];
17
+ /** Subcommands keyed by name. */
18
+ commands: Record<string, CompletionNode>;
19
+ }
20
+
21
+ /** Generate a fish completion script from an OpenCLI document. */
22
+ declare function fish(spec: OpencliSpecJson): string;
23
+
24
+ /** Generate a zsh completion script (`#compdef`) from an OpenCLI document. */
25
+ declare function zsh(spec: OpencliSpecJson): string;
26
+
27
+ /**
28
+ * Adapt an OpenCLI document into the command tree the shell generators walk.
29
+ * Root-level `recursive` options (a CLI's global flags) are made available on
30
+ * every command, so they complete in any subcommand context too.
31
+ */
32
+ declare function opencliToTree(spec: OpencliSpecJson): CompletionNode;
33
+
34
+ /** Generate a completion script for the given shell from an OpenCLI document. */
35
+ declare function completion(spec: OpencliSpecJson, shell: Shell): string;
36
+
37
+ export { type CompletionNode, type CompletionOption, type Shell, completion, fish, opencliToTree, zsh };
package/dist/index.js ADDED
@@ -0,0 +1,152 @@
1
+ // src/flags.ts
2
+ function splitFlags(flags) {
3
+ const short = [];
4
+ const long = [];
5
+ const old = [];
6
+ for (const f of flags) {
7
+ if (f.startsWith("--")) long.push(f.slice(2));
8
+ else if (f.startsWith("-") && f.length === 2) short.push(f.slice(1));
9
+ else if (f.startsWith("-")) old.push(f.slice(1));
10
+ }
11
+ return { short, long, old };
12
+ }
13
+
14
+ // src/tree.ts
15
+ function opencliToTree(spec) {
16
+ var _a, _b;
17
+ const name = ((_a = spec.info) == null ? void 0 : _a.title) || "cli";
18
+ const rootOptions = (spec.options || []).filter((o) => !o.hidden);
19
+ const globalOptions = rootOptions.filter((o) => o.recursive);
20
+ const commandNode = (cmd) => ({
21
+ name: cmd.name,
22
+ description: cmd.description,
23
+ options: [
24
+ ...(cmd.options || []).filter((o) => !o.hidden).map(optionToCompletion),
25
+ ...globalOptions.map(optionToCompletion)
26
+ ],
27
+ commands: toNodeMap(cmd.commands, commandNode)
28
+ });
29
+ return {
30
+ name,
31
+ description: (_b = spec.info) == null ? void 0 : _b.description,
32
+ options: rootOptions.map(optionToCompletion),
33
+ commands: toNodeMap(spec.commands, commandNode)
34
+ };
35
+ }
36
+ function toNodeMap(commands, node) {
37
+ return Object.fromEntries((commands || []).filter((c) => !c.hidden).map((c) => [c.name, node(c)]));
38
+ }
39
+ function optionToCompletion(opt) {
40
+ var _a;
41
+ const flags = [`--${opt.name}`, ...(opt.aliases || []).map((a) => a.length === 1 ? `-${a}` : `--${a}`)];
42
+ return { flags, takesValue: (((_a = opt.arguments) == null ? void 0 : _a.length) ?? 0) > 0, description: opt.description };
43
+ }
44
+
45
+ // src/fish.ts
46
+ var escFish = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
47
+ function fish(spec) {
48
+ const tree = opencliToTree(spec);
49
+ const cmd = tree.name;
50
+ const lines = [`# fish completions for ${cmd} (generated - do not edit)`];
51
+ const walk = (node, path) => {
52
+ const cond = path.length === 0 ? "__fish_use_subcommand" : path.map((p) => `__fish_seen_subcommand_from ${p}`).join("; and ");
53
+ const subs = Object.values(node.commands);
54
+ for (const sub of subs) {
55
+ const d = sub.description ? ` -d '${escFish(sub.description)}'` : "";
56
+ lines.push(`complete -c ${cmd} -n "${cond}" -f -a "${sub.name}"${d}`);
57
+ }
58
+ for (const opt of node.options) {
59
+ const { short, long, old } = splitFlags(opt.flags);
60
+ const parts = [...short.map((s) => `-s ${s}`), ...long.map((l) => `-l ${l}`), ...old.map((o) => `-o ${o}`)].join(" ");
61
+ const r = opt.takesValue ? " -r" : "";
62
+ const d = opt.description ? ` -d '${escFish(opt.description)}'` : "";
63
+ lines.push(`complete -c ${cmd} -n "${cond}" ${parts}${r}${d}`);
64
+ }
65
+ for (const sub of subs) walk(sub, [...path, sub.name]);
66
+ };
67
+ walk(tree, []);
68
+ return `${lines.join("\n")}
69
+ `;
70
+ }
71
+
72
+ // src/zsh.ts
73
+ var escZshSpec = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/[:[\]{}]/g, (c) => `\\${c}`);
74
+ var escZshDescribe = (s) => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/:/g, "\\:");
75
+ function optToSpec(opt) {
76
+ const { short, long } = splitFlags(opt.flags);
77
+ const desc = opt.description ? `[${escZshSpec(opt.description)}]` : "";
78
+ const value = opt.takesValue ? ":value:" : "";
79
+ const all = [...short.map((s) => `-${s}`), ...long.map((l) => `--${l}`)];
80
+ if (all.length >= 2) {
81
+ return `'(${all.join(" ")})'{${all.join(",")}}'${desc}${value}'`;
82
+ }
83
+ return `'${all[0]}${desc}${value}'`;
84
+ }
85
+ function zsh(spec) {
86
+ const tree = opencliToTree(spec);
87
+ const cmd = tree.name;
88
+ const subs = Object.values(tree.commands);
89
+ const hasSubs = subs.length > 0;
90
+ const out = [`#compdef ${cmd}`, "", `_${cmd}() {`];
91
+ out.push(" local context state state_descr line");
92
+ out.push(" typeset -A opt_args");
93
+ out.push("");
94
+ const rootSpecs = tree.options.map(optToSpec);
95
+ if (hasSubs) {
96
+ rootSpecs.push("'1: :->command'");
97
+ rootSpecs.push("'*::arg:->args'");
98
+ }
99
+ out.push(" _arguments -C \\");
100
+ out.push(`${rootSpecs.map((s) => ` ${s}`).join(" \\\n")} && return 0`);
101
+ if (hasSubs) {
102
+ out.push("");
103
+ out.push(" case $state in");
104
+ out.push(" command)");
105
+ out.push(" local -a commands");
106
+ out.push(" commands=(");
107
+ for (const sub of subs) {
108
+ out.push(` '${sub.name}:${escZshDescribe(sub.description || "")}'`);
109
+ }
110
+ out.push(" )");
111
+ out.push(` _describe -t commands '${cmd} command' commands`);
112
+ out.push(" ;;");
113
+ out.push(" args)");
114
+ out.push(" case $line[1] in");
115
+ for (const sub of subs) {
116
+ out.push(` ${sub.name})`);
117
+ const specs = sub.options.map(optToSpec);
118
+ if (specs.length) {
119
+ out.push(" _arguments \\");
120
+ out.push(specs.map((s) => ` ${s}`).join(" \\\n"));
121
+ } else {
122
+ out.push(" _message 'no more arguments'");
123
+ }
124
+ out.push(" ;;");
125
+ }
126
+ out.push(" esac");
127
+ out.push(" ;;");
128
+ out.push(" esac");
129
+ }
130
+ out.push("}");
131
+ out.push("");
132
+ out.push(`_${cmd} "$@"`);
133
+ return `${out.join("\n")}
134
+ `;
135
+ }
136
+
137
+ // src/index.ts
138
+ function completion(spec, shell) {
139
+ switch (shell) {
140
+ case "fish":
141
+ return fish(spec);
142
+ default:
143
+ return zsh(spec);
144
+ }
145
+ }
146
+ export {
147
+ completion,
148
+ fish,
149
+ opencliToTree,
150
+ zsh
151
+ };
152
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/flags.ts","../src/tree.ts","../src/fish.ts","../src/zsh.ts","../src/index.ts"],"sourcesContent":["/** Split flag spellings into short (`-x`), long (`--xy`) and old-style (`-xy`). */\nexport function splitFlags(flags: string[]): { short: string[]; long: string[]; old: string[] } {\n const short: string[] = [];\n const long: string[] = [];\n const old: string[] = [];\n for (const f of flags) {\n if (f.startsWith('--')) long.push(f.slice(2));\n else if (f.startsWith('-') && f.length === 2) short.push(f.slice(1));\n else if (f.startsWith('-')) old.push(f.slice(1));\n }\n return { short, long, old };\n}\n","import type { Command, OpencliSpecJson, Option } from '@xyd-js/opencli';\n\nimport type { CompletionNode, CompletionOption } from './types';\n\n/**\n * Adapt an OpenCLI document into the command tree the shell generators walk.\n * Root-level `recursive` options (a CLI's global flags) are made available on\n * every command, so they complete in any subcommand context too.\n */\nexport function opencliToTree(spec: OpencliSpecJson): CompletionNode {\n const name = spec.info?.title || 'cli';\n const rootOptions = (spec.options || []).filter((o) => !o.hidden);\n const globalOptions = rootOptions.filter((o) => o.recursive);\n\n const commandNode = (cmd: Command): CompletionNode => ({\n name: cmd.name,\n description: cmd.description,\n options: [\n ...(cmd.options || []).filter((o) => !o.hidden).map(optionToCompletion),\n ...globalOptions.map(optionToCompletion),\n ],\n commands: toNodeMap(cmd.commands, commandNode),\n });\n\n return {\n name,\n description: spec.info?.description,\n options: rootOptions.map(optionToCompletion),\n commands: toNodeMap(spec.commands, commandNode),\n };\n}\n\nfunction toNodeMap(commands: Command[] | undefined, node: (c: Command) => CompletionNode): Record<string, CompletionNode> {\n return Object.fromEntries((commands || []).filter((c) => !c.hidden).map((c) => [c.name, node(c)]));\n}\n\nfunction optionToCompletion(opt: Option): CompletionOption {\n // OpenCLI option `name` is the canonical long form; aliases may be short or long.\n const flags = [`--${opt.name}`, ...(opt.aliases || []).map((a) => (a.length === 1 ? `-${a}` : `--${a}`))];\n return { flags, takesValue: (opt.arguments?.length ?? 0) > 0, description: opt.description };\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { splitFlags } from './flags';\nimport { opencliToTree } from './tree';\nimport type { CompletionNode } from './types';\n\nconst escFish = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n\n/** Generate a fish completion script from an OpenCLI document. */\nexport function fish(spec: OpencliSpecJson): string {\n const tree = opencliToTree(spec);\n const cmd = tree.name;\n const lines = [`# fish completions for ${cmd} (generated - do not edit)`];\n\n const walk = (node: CompletionNode, path: string[]) => {\n const cond =\n path.length === 0\n ? '__fish_use_subcommand'\n : path.map((p) => `__fish_seen_subcommand_from ${p}`).join('; and ');\n\n const subs = Object.values(node.commands);\n for (const sub of subs) {\n const d = sub.description ? ` -d '${escFish(sub.description)}'` : '';\n lines.push(`complete -c ${cmd} -n \"${cond}\" -f -a \"${sub.name}\"${d}`);\n }\n for (const opt of node.options) {\n const { short, long, old } = splitFlags(opt.flags);\n const parts = [...short.map((s) => `-s ${s}`), ...long.map((l) => `-l ${l}`), ...old.map((o) => `-o ${o}`)].join(' ');\n const r = opt.takesValue ? ' -r' : '';\n const d = opt.description ? ` -d '${escFish(opt.description)}'` : '';\n lines.push(`complete -c ${cmd} -n \"${cond}\" ${parts}${r}${d}`);\n }\n for (const sub of subs) walk(sub, [...path, sub.name]);\n };\n\n walk(tree, []);\n return `${lines.join('\\n')}\\n`;\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { splitFlags } from './flags';\nimport { opencliToTree } from './tree';\nimport type { CompletionOption } from './types';\n\n// Inside an `_arguments` spec's `[...]` description: escape backslash, single\n// quote, and the chars that are syntactically special there (`:` `[` `]` `{` `}`).\nconst escZshSpec = (s: string) =>\n s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"'\\\\''\")\n .replace(/[:[\\]{}]/g, (c) => `\\\\${c}`);\n\n// Inside a `_describe` `'value:desc'` row only the `:` separator (plus quote /\n// backslash) is special — brackets/braces are literal.\nconst escZshDescribe = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"'\\\\''\").replace(/:/g, '\\\\:');\n\nfunction optToSpec(opt: CompletionOption): string {\n const { short, long } = splitFlags(opt.flags);\n const desc = opt.description ? `[${escZshSpec(opt.description)}]` : '';\n const value = opt.takesValue ? ':value:' : '';\n const all = [...short.map((s) => `-${s}`), ...long.map((l) => `--${l}`)];\n if (all.length >= 2) {\n return `'(${all.join(' ')})'{${all.join(',')}}'${desc}${value}'`;\n }\n return `'${all[0]}${desc}${value}'`;\n}\n\n/** Generate a zsh completion script (`#compdef`) from an OpenCLI document. */\nexport function zsh(spec: OpencliSpecJson): string {\n const tree = opencliToTree(spec);\n const cmd = tree.name;\n const subs = Object.values(tree.commands);\n const hasSubs = subs.length > 0;\n const out = [`#compdef ${cmd}`, '', `_${cmd}() {`];\n\n out.push(' local context state state_descr line');\n out.push(' typeset -A opt_args');\n out.push('');\n\n const rootSpecs = tree.options.map(optToSpec);\n if (hasSubs) {\n rootSpecs.push(\"'1: :->command'\");\n rootSpecs.push(\"'*::arg:->args'\");\n }\n out.push(' _arguments -C \\\\');\n out.push(`${rootSpecs.map((s) => ` ${s}`).join(' \\\\\\n')} && return 0`);\n\n if (hasSubs) {\n out.push('');\n out.push(' case $state in');\n out.push(' command)');\n out.push(' local -a commands');\n out.push(' commands=(');\n for (const sub of subs) {\n out.push(` '${sub.name}:${escZshDescribe(sub.description || '')}'`);\n }\n out.push(' )');\n out.push(` _describe -t commands '${cmd} command' commands`);\n out.push(' ;;');\n out.push(' args)');\n out.push(' case $line[1] in');\n for (const sub of subs) {\n out.push(` ${sub.name})`);\n const specs = sub.options.map(optToSpec);\n if (specs.length) {\n out.push(' _arguments \\\\');\n out.push(specs.map((s) => ` ${s}`).join(' \\\\\\n'));\n } else {\n out.push(\" _message 'no more arguments'\");\n }\n out.push(' ;;');\n }\n out.push(' esac');\n out.push(' ;;');\n out.push(' esac');\n }\n\n out.push('}');\n out.push('');\n out.push(`_${cmd} \"$@\"`);\n return `${out.join('\\n')}\\n`;\n}\n","import type { OpencliSpecJson } from '@xyd-js/opencli';\n\nimport { fish } from './fish';\nimport type { Shell } from './types';\nimport { zsh } from './zsh';\n\nexport { fish } from './fish';\nexport { zsh } from './zsh';\nexport { opencliToTree } from './tree';\nexport type { Shell, CompletionNode, CompletionOption } from './types';\n\n/** Generate a completion script for the given shell from an OpenCLI document. */\nexport function completion(spec: OpencliSpecJson, shell: Shell): string {\n switch (shell) {\n case 'fish':\n return fish(spec);\n default:\n return zsh(spec);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@xyd-js/opencli-completion",
3
+ "version": "0.0.0-build-b7bd05c-20260701151111",
4
+ "description": "Generate shell completion scripts (zsh, fish) from an OpenCLI document",
5
+ "main": "./dist/index.js",
6
+ "type": "module",
7
+ "files": [
8
+ "dist",
9
+ "package.json"
10
+ ],
11
+ "dependencies": {
12
+ "@xyd-js/opencli": "0.0.0-build-b7bd05c-20260701151111"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^20.9.0",
16
+ "rimraf": "^3.0.2",
17
+ "tsup": "^8.3.0",
18
+ "typescript": "^5.6.2",
19
+ "vitest": "^2.1.1"
20
+ },
21
+ "scripts": {
22
+ "clean": "rimraf dist",
23
+ "prebuild": "pnpm clean",
24
+ "build": "tsup",
25
+ "test": "vitest",
26
+ "ci:test": "vitest run",
27
+ "format": "bunx biome check --write src"
28
+ }
29
+ }