From 6e52ad23095ee82fb8e36645d83fb8b345b775ac Mon Sep 17 00:00:00 2001 From: Horu <73709188+HigherOrderLogic@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:50:26 +1000 Subject: [PATCH 1/4] feat: command aliases --- src/command.ts | 34 +++++++++++++++++++++++++++++++--- src/types.ts | 1 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/command.ts b/src/command.ts index 4878197..6f975b2 100644 --- a/src/command.ts +++ b/src/command.ts @@ -43,13 +43,27 @@ export async function runCommand( ); const subCommandName = opts.rawArgs[subCommandArgIndex]; if (subCommandName) { - if (!subCommands[subCommandName]) { + let subCommand = await resolveValue(subCommands[subCommandName]); + + if (!subCommand) { + for (const _subCmd of Object.values(subCommands)) { + const subCmd = await resolveValue(_subCmd); + const subCmdMeta = await resolveValue(subCmd.meta); + for (const alias of subCmdMeta?.aliases || []) { + if (alias === subCommandName) { + subCommand = subCmd; + break; + } + } + } + } + + if (!subCommand) { throw new CLIError( `Unknown command \`${subCommandName}\``, "E_UNKNOWN_COMMAND", ); } - const subCommand = await resolveValue(subCommands[subCommandName]); if (subCommand) { await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1), @@ -81,7 +95,21 @@ export async function resolveSubCommand( if (subCommands && Object.keys(subCommands).length > 0) { const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-")); const subCommandName = rawArgs[subCommandArgIndex]; - const subCommand = await resolveValue(subCommands[subCommandName]); + let subCommand = await resolveValue(subCommands[subCommandName]); + + if (!subCommand) { + for (const _subCmd of Object.values(subCommands)) { + const subCmd = await resolveValue(_subCmd); + const subCmdMeta = await resolveValue(subCmd.meta); + for (const alias of subCmdMeta?.aliases || []) { + if (alias === subCommandName) { + subCommand = subCmd; + break; + } + } + } + } + if (subCommand) { return resolveSubCommand( subCommand, diff --git a/src/types.ts b/src/types.ts index e9892f6..217ada0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -106,6 +106,7 @@ export type ParsedArgs = RawArgs & export interface CommandMeta { name?: string; + aliases?: string[]; version?: string; description?: string; hidden?: boolean; From 7d4c468bab4676236f78556ad109a3200941d014 Mon Sep 17 00:00:00 2001 From: Horu <73709188+HigherOrderLogic@users.noreply.github.com> Date: Sat, 5 Oct 2024 13:01:40 +1000 Subject: [PATCH 2/4] feat: render usage with aliases --- src/usage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usage.ts b/src/usage.ts index 8500c26..379d43f 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -99,7 +99,7 @@ export async function renderUsage( if (meta?.hidden) { continue; } - commandsLines.push([`\`${name}\``, meta?.description || ""]); + commandsLines.push([`\`${[name, ...(meta?.aliases || [])].join(", ")}\``, meta?.description || ""]); commandNames.push(name); } usageLine.push(commandNames.join("|")); From 12b61dfff42dd82f4805a5621be1a78db713cdf7 Mon Sep 17 00:00:00 2001 From: Horu <73709188+HigherOrderLogic@users.noreply.github.com> Date: Sat, 5 Oct 2024 13:03:22 +1000 Subject: [PATCH 3/4] chore: playground --- playground/commands/build.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/playground/commands/build.ts b/playground/commands/build.ts index af062e6..e552a34 100644 --- a/playground/commands/build.ts +++ b/playground/commands/build.ts @@ -4,6 +4,7 @@ import { defineCommand } from "../../src"; export default defineCommand({ meta: { name: "build", + aliases: ["b"], description: "Build the project from current directory", }, args: { From d72eb165148b3943c06caaa1b05e2d4645d69797 Mon Sep 17 00:00:00 2001 From: Horu <73709188+HigherOrderLogic@users.noreply.github.com> Date: Sat, 5 Oct 2024 16:27:26 +1000 Subject: [PATCH 4/4] refactor: reduce duplicate code --- src/command.ts | 58 +++++++++++++++++++++++++------------------------- src/usage.ts | 5 ++++- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/command.ts b/src/command.ts index 6f975b2..9664b45 100644 --- a/src/command.ts +++ b/src/command.ts @@ -1,4 +1,9 @@ -import type { CommandContext, CommandDef, ArgsDef } from "./types"; +import type { + CommandContext, + CommandDef, + ArgsDef, + SubCommandsDef, +} from "./types"; import { CLIError, resolveValue } from "./_utils"; import { parseArgs } from "./args"; @@ -14,6 +19,27 @@ export interface RunCommandOptions { showUsage?: boolean; } +async function getSubCommand( + subCommandsList: SubCommandsDef, + subCommandName: string, +): Promise | undefined> { + const subCommand = await resolveValue(subCommandsList[subCommandName]); + + if (subCommand) { + return subCommand; + } + + for (const _subCmd of Object.values(subCommandsList)) { + const subCmd = await resolveValue(_subCmd); + const subCmdMeta = await resolveValue(subCmd.meta); + if ((subCmdMeta?.aliases || []).includes(subCommandName)) { + return subCmd; + } + } + + return undefined; +} + export async function runCommand( cmd: CommandDef, opts: RunCommandOptions, @@ -43,20 +69,7 @@ export async function runCommand( ); const subCommandName = opts.rawArgs[subCommandArgIndex]; if (subCommandName) { - let subCommand = await resolveValue(subCommands[subCommandName]); - - if (!subCommand) { - for (const _subCmd of Object.values(subCommands)) { - const subCmd = await resolveValue(_subCmd); - const subCmdMeta = await resolveValue(subCmd.meta); - for (const alias of subCmdMeta?.aliases || []) { - if (alias === subCommandName) { - subCommand = subCmd; - break; - } - } - } - } + const subCommand = await getSubCommand(subCommands, subCommandName); if (!subCommand) { throw new CLIError( @@ -95,20 +108,7 @@ export async function resolveSubCommand( if (subCommands && Object.keys(subCommands).length > 0) { const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-")); const subCommandName = rawArgs[subCommandArgIndex]; - let subCommand = await resolveValue(subCommands[subCommandName]); - - if (!subCommand) { - for (const _subCmd of Object.values(subCommands)) { - const subCmd = await resolveValue(_subCmd); - const subCmdMeta = await resolveValue(subCmd.meta); - for (const alias of subCmdMeta?.aliases || []) { - if (alias === subCommandName) { - subCommand = subCmd; - break; - } - } - } - } + const subCommand = await getSubCommand(subCommands, subCommandName); if (subCommand) { return resolveSubCommand( diff --git a/src/usage.ts b/src/usage.ts index 379d43f..970fc43 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -99,7 +99,10 @@ export async function renderUsage( if (meta?.hidden) { continue; } - commandsLines.push([`\`${[name, ...(meta?.aliases || [])].join(", ")}\``, meta?.description || ""]); + commandsLines.push([ + `\`${[name, ...(meta?.aliases || [])].join(", ")}\``, + meta?.description || "", + ]); commandNames.push(name); } usageLine.push(commandNames.join("|"));