@clerc/plugin-completions 1.0.0-beta.9 → 1.0.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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ArgumentHandler, Command, OptionHandler } from "@bomb.sh/tab";
1
2
  import { Plugin } from "@clerc/core";
2
3
 
3
4
  //#region src/index.d.ts
@@ -13,16 +14,41 @@ declare module "@clerc/core" {
13
14
  * @default true
14
15
  */
15
16
  show?: boolean;
17
+ /**
18
+ * Handler to provide custom completions for the command.
19
+ */
20
+ handler?: (command: Command) => void;
21
+ };
22
+ }
23
+ interface FlagCustomOptions {
24
+ /**
25
+ * Completions options for the flag.
26
+ */
27
+ completions?: {
28
+ /**
29
+ * Whether to show the flag in completions output.
30
+ *
31
+ * @default true
32
+ */
33
+ show?: boolean;
34
+ /**
35
+ * Handler to provide custom completions for the flag.
36
+ */
37
+ handler?: OptionHandler;
38
+ };
39
+ }
40
+ interface ParameterCustomOptions {
41
+ /**
42
+ * Completions options for the parameter.
43
+ */
44
+ completions?: {
45
+ /**
46
+ * Handler to provide custom completions for the parameter.
47
+ */
48
+ handler?: ArgumentHandler;
16
49
  };
17
50
  }
18
51
  }
19
- interface CompletionsPluginOptions {
20
- /**
21
- * Whether to register the `completions install` and `completions uninstall` commands.
22
- * @default true
23
- */
24
- managementCommands?: boolean;
25
- }
26
- declare const completionsPlugin: (options?: CompletionsPluginOptions) => Plugin;
52
+ declare const completionsPlugin: () => Plugin;
27
53
  //#endregion
28
- export { CompletionsPluginOptions, completionsPlugin };
54
+ export { completionsPlugin };
package/dist/index.js CHANGED
@@ -1,133 +1,67 @@
1
- import { DOUBLE_DASH, definePlugin, resolveCommand } from "@clerc/core";
2
- import tabtab, { getShellFromEnv } from "@pnpm/tabtab";
3
- import { formatFlagName, toArray } from "@clerc/utils";
1
+ import { RootCommand } from "@bomb.sh/tab";
2
+ import { Types, definePlugin, extractParameterInfo, normalizeFlagValue, normalizeParameterValue } from "@clerc/core";
4
3
 
5
- //#region src/complete.ts
6
- function splitCommand(cmd) {
7
- const args = [];
8
- let current = "";
9
- let quote = null;
10
- let escape = false;
11
- for (const char of cmd) {
12
- if (escape) {
13
- current += char;
14
- escape = false;
15
- continue;
16
- }
17
- if (char === "\\") {
18
- escape = true;
19
- continue;
20
- }
21
- if (quote) if (char === quote) quote = null;
22
- else current += char;
23
- else if (char === "\"" || char === "'") quote = char;
24
- else if (/\s/.test(char)) {
25
- if (current) {
26
- args.push(current);
27
- current = "";
28
- }
29
- } else current += char;
4
+ //#region src/t.ts
5
+ function registerFlag(tc, flagName, def) {
6
+ const normalized = normalizeFlagValue(def);
7
+ const desc = normalized.description ?? "";
8
+ if (normalized.type === Boolean) tc.option(flagName, desc, normalized.short);
9
+ else {
10
+ const handler = normalized.completions?.handler ?? (async () => {});
11
+ tc.option(flagName, desc, handler, normalized.short);
30
12
  }
31
- if (current) args.push(current);
32
- return args;
33
13
  }
34
- async function getCompletion(cli, env) {
35
- const inputArgv = splitCommand(env.partial.slice(0, env.partial.length - env.lastPartial.length)).slice(1);
36
- if (inputArgv.includes(DOUBLE_DASH)) return [];
37
- const [command, commandName] = resolveCommand(cli._commands, inputArgv);
38
- if (env.lastPartial.startsWith("-")) {
39
- const flags = command ? {
40
- ...cli._globalFlags,
41
- ...command.flags
42
- } : cli._globalFlags;
43
- const candidates$1 = [];
44
- for (const [name, def] of Object.entries(flags)) {
45
- candidates$1.push({
46
- name: formatFlagName(name),
47
- description: def.description
48
- });
49
- if (def.alias) {
50
- const aliases = toArray(def.alias);
51
- for (const alias of aliases) candidates$1.push({
52
- name: formatFlagName(alias),
53
- description: def.description
54
- });
55
- }
14
+ function registerGlobalFlags(globalFlags, tc) {
15
+ for (const [flagName, def] of Object.entries(globalFlags)) registerFlag(tc, flagName, def);
16
+ }
17
+ function buildTabModel(t, globalFlags, commands) {
18
+ registerGlobalFlags(globalFlags, t);
19
+ for (const cmd of commands.values()) {
20
+ if (cmd.completions?.show === false) continue;
21
+ let command = t;
22
+ if (cmd.name !== "") {
23
+ command = t.command(cmd.name, cmd.description ?? "");
24
+ registerGlobalFlags(globalFlags, command);
56
25
  }
57
- return candidates$1;
58
- }
59
- const candidates = [];
60
- let prefix = "";
61
- if (commandName) {
62
- const matchedParts = commandName.split(" ");
63
- const remainingArgs = inputArgv.slice(matchedParts.length);
64
- prefix = `${[command.name, ...remainingArgs].join(" ")} `;
65
- } else prefix = inputArgv.length > 0 ? `${inputArgv.join(" ")} ` : "";
66
- for (const command$1 of cli._commands.values()) {
67
- if (command$1.completions?.show === false) continue;
68
- if (command$1.name.startsWith(prefix)) {
69
- const nextWord = command$1.name.slice(prefix.length).split(" ")[0];
70
- if (nextWord) candidates.push({
71
- name: nextWord,
72
- description: command$1.description
73
- });
26
+ cmd.completions?.handler?.(command);
27
+ for (const def of cmd.parameters ?? []) {
28
+ const normalized = normalizeParameterValue(def);
29
+ const { name, isVariadic } = extractParameterInfo(normalized.key);
30
+ command.argument(name, normalized.completions?.handler, isVariadic);
74
31
  }
32
+ for (const [flagName, def] of Object.entries(cmd.flags ?? {})) registerFlag(command, flagName, def);
75
33
  }
76
- const uniqueCandidates = /* @__PURE__ */ new Map();
77
- for (const c of candidates) uniqueCandidates.set(c.name, c);
78
- return [...uniqueCandidates.values()];
79
34
  }
80
35
 
81
36
  //#endregion
82
37
  //#region src/index.ts
83
- const completionsPlugin = (options = {}) => definePlugin({ setup: (cli) => {
84
- const { managementCommands = true } = options;
85
- if (managementCommands) {
86
- cli.command("completions install", "Install shell completions", {
87
- help: { group: "completions" },
88
- flags: { shell: {
89
- description: "Shell type",
90
- type: String
91
- } },
92
- parameters: ["[shell]"]
93
- }).on("completions install", async (ctx) => {
94
- const shell = ctx.parameters.shell ?? ctx.flags.shell;
95
- if (!shell) throw new Error("Please specify the shell type via the --shell flag or the [shell] parameter.");
96
- if (!tabtab.SUPPORTED_SHELLS.includes(shell)) throw new Error(`Unsupported shell: ${shell}. Supported shells are: ${tabtab.SUPPORTED_SHELLS.join(", ")}.`);
97
- await tabtab.install({
98
- name: cli._name,
99
- completer: cli._name,
100
- shell
101
- });
102
- });
103
- cli.command("completions uninstall", "Uninstall shell completions", { help: { group: "completions" } }).on("completions uninstall", async () => {
104
- await tabtab.uninstall({ name: cli._name });
105
- });
106
- }
107
- cli.command("completions", "Generate completions script", {
108
- help: { group: "completions" },
38
+ const completionsPlugin = () => definePlugin({ setup: (cli) => {
39
+ const t = new RootCommand();
40
+ const supportedShellEnum = Types.Enum("zsh", "bash", "fish", "powershell");
41
+ cli.command("completions", "Generate shell completion scripts", {
109
42
  flags: { shell: {
110
43
  description: "Shell type",
111
- type: String
44
+ type: supportedShellEnum
112
45
  } },
113
- parameters: ["[shell]"]
46
+ parameters: [{
47
+ key: "[shell]",
48
+ description: "Shell type",
49
+ type: supportedShellEnum
50
+ }]
114
51
  }).on("completions", async (ctx) => {
115
52
  const shell = ctx.parameters.shell ?? ctx.flags.shell;
116
- if (!shell) throw new Error("Please specify the shell type via the --shell flag or the [shell] parameter.");
117
- if (!tabtab.SUPPORTED_SHELLS.includes(shell)) throw new Error(`Unsupported shell: ${shell}. Supported shells are: ${tabtab.SUPPORTED_SHELLS.join(", ")}.`);
118
- const script = await tabtab.getCompletionScript({
119
- name: cli._name,
120
- completer: cli._name,
121
- shell
122
- });
123
- console.log(script);
53
+ if (!shell) throw new Error("Shell type is required. Please provide it via --shell flag or [shell] parameter.");
54
+ buildTabModel(t, cli._globalFlags, cli._commands);
55
+ t.setup(cli._scriptName, cli._scriptName, shell);
124
56
  });
125
- cli.command("completion-server", "Handle completions", { help: { show: false } }).on("completion-server", async () => {
126
- const env = tabtab.parseEnv(process.env);
127
- if (!env.complete) return;
128
- const shell = getShellFromEnv(process.env);
129
- const filtered = (await getCompletion(cli, env)).filter((c) => c.name.startsWith(env.lastPartial));
130
- tabtab.log(filtered, shell);
57
+ cli.command("complete", {
58
+ help: { show: false },
59
+ completions: { show: false },
60
+ parameters: ["--", "[input...]"]
61
+ }).on("complete", async (ctx) => {
62
+ buildTabModel(t, cli._globalFlags, cli._commands);
63
+ const { input } = ctx.parameters;
64
+ t.parse(input);
131
65
  });
132
66
  return cli;
133
67
  } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerc/plugin-completions",
3
- "version": "1.0.0-beta.9",
3
+ "version": "1.0.0",
4
4
  "author": "Ray <i@mk1.io> (https://github.com/so1ve)",
5
5
  "type": "module",
6
6
  "description": "Clerc plugin completions",
@@ -27,6 +27,9 @@
27
27
  "exports": {
28
28
  ".": "./dist/index.js"
29
29
  },
30
+ "bin": {
31
+ "my-cli": "./src/a.mjs"
32
+ },
30
33
  "main": "./dist/index.js",
31
34
  "module": "./dist/index.js",
32
35
  "types": "dist/index.d.ts",
@@ -45,17 +48,13 @@
45
48
  "access": "public"
46
49
  },
47
50
  "dependencies": {
48
- "@pnpm/tabtab": "^0.5.4",
49
- "@clerc/utils": "1.0.0-beta.9"
51
+ "@bomb.sh/tab": "^0.0.10"
50
52
  },
51
53
  "devDependencies": {
52
- "@clerc/core": "1.0.0-beta.9"
54
+ "@clerc/core": "1.0.0",
55
+ "@clerc/utils": "1.0.0"
53
56
  },
54
57
  "peerDependencies": {
55
58
  "@clerc/core": "*"
56
- },
57
- "scripts": {
58
- "build": "tsdown",
59
- "watch": "tsdown --watch"
60
59
  }
61
60
  }