diff --git a/src/usage.ts b/src/usage.ts index 8500c26..e3c6450 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -1,7 +1,8 @@ import consola from "consola"; import { colors } from "consola/utils"; +import { snakeCase } from "scule"; import { formatLineColumns, resolveValue } from "./_utils"; -import type { ArgsDef, CommandDef } from "./types"; +import type { Arg, ArgsDef, CommandDef } from "./types"; import { resolveArgs } from "./args"; export async function showUsage( @@ -39,30 +40,17 @@ export async function renderUsage( if (arg.type === "positional") { const name = arg.name.toUpperCase(); const isRequired = arg.required !== false && arg.default === undefined; - // (isRequired ? " (required)" : " (optional)" - const defaultHint = arg.default ? `="${arg.default}"` : ""; posLines.push([ - "`" + name + defaultHint + "`", - arg.description || "", - arg.valueHint ? `<${arg.valueHint}>` : "", + "`" + name + renderValueHint(arg) + "`", + renderDescription(arg, isRequired), ]); usageLine.push(isRequired ? `<${name}>` : `[${name}]`); } else { const isRequired = arg.required === true && arg.default === undefined; const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + - (arg.type === "string" && (arg.valueHint || arg.default) - ? `=${ - arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"` - }` - : "") + - (arg.type === "enum" && arg.options - ? `=<${arg.options.join("|")}>` - : ""); - argLines.push([ - "`" + argStr + (isRequired ? " (required)" : "") + "`", - arg.description || "", - ]); + renderValueHint(arg); + argLines.push(["`" + argStr + "`", renderDescription(arg, isRequired)]); /** * print negative boolean arg variant usage when @@ -79,13 +67,15 @@ export async function renderUsage( `--no-${arg.name}`, ].join(", "); argLines.push([ - "`" + negativeArgStr + (isRequired ? " (required)" : "") + "`", - arg.negativeDescription || "", + "`" + negativeArgStr + "`", + [arg.negativeDescription, isRequired ? colors.gray("(Required)") : ""] + .filter(Boolean) + .join(" "), ]); } if (isRequired) { - usageLine.push(argStr); + usageLine.push(`--${arg.name}` + renderValueHint(arg)); } } } @@ -149,3 +139,29 @@ export async function renderUsage( return usageLines.filter((l) => typeof l === "string").join("\n"); } + +function renderValueHint(arg: Arg) { + const valueHint = arg.valueHint ? `=<${arg.valueHint}>` : ""; + const fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`; + + if (!arg.type || arg.type === "positional" || arg.type === "boolean") { + return valueHint; + } + + if (arg.type === "enum" && arg.options?.length) { + return `=<${arg.options.join("|")}>`; + } + + return fallbackValueHint; +} + +function renderDescription(arg: Arg, required: boolean) { + const requiredHint = required ? colors.gray("(Required)") : ""; + const defaultHint = + arg.default === undefined ? "" : colors.gray(`(Default: ${arg.default})`); + const description = [arg.description, requiredHint, defaultHint] + .filter(Boolean) + .join(" "); + + return description; +} diff --git a/test/usage.test.ts b/test/usage.test.ts index 8927602..fb851cf 100644 --- a/test/usage.test.ts +++ b/test/usage.test.ts @@ -58,18 +58,18 @@ describe("usage", () => { expect(usage).toMatchInlineSnapshot(` "A command (Commander) - USAGE \`Commander [OPTIONS] --foo \` + USAGE \`Commander [OPTIONS] --foo= \` ARGUMENTS - \`POS\` A pos + \`POS\` A pos (Required) OPTIONS - \`--foo (required)\` A foo - \`-b, --bar\` A bar - \`--enum=\` An enum - \`--boolean\` A boolean + \`--foo=\` A foo (Required) + \`-b, --bar=\` A bar + \`--enum=\` An enum + \`--boolean\` A boolean " `); }); @@ -100,8 +100,8 @@ describe("usage", () => { OPTIONS - \`--boolean\` A boolean - \`--no-boolean\` A negative boolean + \`--boolean\` A boolean (Default: true) + \`--no-boolean\` A negative boolean " `); }); @@ -159,7 +159,7 @@ describe("usage", () => { OPTIONS - \`--foo="bar"\` A foo + \`--foo=\` A foo (Default: bar) " `); }); @@ -226,7 +226,7 @@ describe("usage", () => { OPTIONS - \`--foo (required)\` A foo + \`--foo\` A foo (Required) COMMANDS @@ -309,7 +309,7 @@ describe("usage", () => { OPTIONS - \`--foo\` A foo + \`--foo=\` A foo COMMANDS