From f5723b68fcb956981c893eb67d5618734382013f Mon Sep 17 00:00:00 2001 From: kricsleo Date: Tue, 8 Apr 2025 23:00:56 +0800 Subject: [PATCH 1/4] refactor: add fallback valueHint for usage tips --- src/usage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usage.ts b/src/usage.ts index 8500c26..009bd57 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -55,7 +55,7 @@ export async function renderUsage( ? `=${ arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"` }` - : "") + + : (arg.type === "string" && arg.type ? `=<${arg.type}>` : "")) + (arg.type === "enum" && arg.options ? `=<${arg.options.join("|")}>` : ""); From 75fe61814afc2df8ab5d773ee242e08df997736a Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:03:23 +0000 Subject: [PATCH 2/4] chore: apply automated updates --- src/usage.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/usage.ts b/src/usage.ts index 009bd57..0c0599f 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -55,7 +55,9 @@ export async function renderUsage( ? `=${ arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"` }` - : (arg.type === "string" && arg.type ? `=<${arg.type}>` : "")) + + : arg.type === "string" && arg.type + ? `=<${arg.type}>` + : "") + (arg.type === "enum" && arg.options ? `=<${arg.options.join("|")}>` : ""); From cddf625f509c606cc7ca5287720b229ec3473cba Mon Sep 17 00:00:00 2001 From: kricsleo Date: Wed, 9 Apr 2025 13:16:08 +0800 Subject: [PATCH 3/4] refactor: improve usage tips --- src/usage.ts | 62 +++++++++++++++++++++++++++++----------------- test/usage.test.ts | 24 +++++++++--------- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/usage.ts b/src/usage.ts index 0c0599f..54befa4 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,32 +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, isRequired) + "`", + 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 === "string" && arg.type - ? `=<${arg.type}>` - : "") + - (arg.type === "enum" && arg.options - ? `=<${arg.options.join("|")}>` - : ""); - argLines.push([ - "`" + argStr + (isRequired ? " (required)" : "") + "`", - arg.description || "", - ]); + renderValueHint(arg, isRequired); + argLines.push(["`" + argStr + "`", renderDescription(arg, isRequired)]); /** * print negative boolean arg variant usage when @@ -81,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, isRequired)); } } } @@ -151,3 +139,31 @@ export async function renderUsage( return usageLines.filter((l) => typeof l === "string").join("\n"); } + +function renderValueHint(arg: Arg, required: boolean) { + const pre = required ? "<" : "["; + const post = required ? ">" : "]"; + const valueHint = arg.valueHint ? `=${pre}${arg.valueHint}${post}` : ""; + const fallbackValueHint = valueHint || `=${pre}${snakeCase(arg.name)}${post}`; + + if (!arg.type || arg.type === "positional" || arg.type === "boolean") { + return valueHint; + } + + if (arg.type === "enum" && arg.options?.length) { + return `=${pre}${arg.options.join("|")}${post}`; + } + + 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..419fe1e 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=[bar]\` A bar + \`--enum=[a|b]\` 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 " `); }); @@ -130,7 +130,7 @@ describe("usage", () => { OPTIONS - \`--foo=\` A foo + \`--foo=[FOO]\` A foo " `); }); @@ -159,7 +159,7 @@ describe("usage", () => { OPTIONS - \`--foo="bar"\` A foo + \`--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=[foo]\` A foo COMMANDS From 7ab24aee8936cbc8e13669c7187fb6aaaae876c9 Mon Sep 17 00:00:00 2001 From: kricsleo Date: Wed, 9 Apr 2025 13:39:07 +0800 Subject: [PATCH 4/4] fix: use `<...>` for arg descriptions --- src/usage.ts | 16 +++++++--------- test/usage.test.ts | 10 +++++----- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/usage.ts b/src/usage.ts index 54befa4..e3c6450 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -41,7 +41,7 @@ export async function renderUsage( const name = arg.name.toUpperCase(); const isRequired = arg.required !== false && arg.default === undefined; posLines.push([ - "`" + name + renderValueHint(arg, isRequired) + "`", + "`" + name + renderValueHint(arg) + "`", renderDescription(arg, isRequired), ]); usageLine.push(isRequired ? `<${name}>` : `[${name}]`); @@ -49,7 +49,7 @@ export async function renderUsage( const isRequired = arg.required === true && arg.default === undefined; const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + - renderValueHint(arg, isRequired); + renderValueHint(arg); argLines.push(["`" + argStr + "`", renderDescription(arg, isRequired)]); /** @@ -75,7 +75,7 @@ export async function renderUsage( } if (isRequired) { - usageLine.push(`--${arg.name}` + renderValueHint(arg, isRequired)); + usageLine.push(`--${arg.name}` + renderValueHint(arg)); } } } @@ -140,18 +140,16 @@ export async function renderUsage( return usageLines.filter((l) => typeof l === "string").join("\n"); } -function renderValueHint(arg: Arg, required: boolean) { - const pre = required ? "<" : "["; - const post = required ? ">" : "]"; - const valueHint = arg.valueHint ? `=${pre}${arg.valueHint}${post}` : ""; - const fallbackValueHint = valueHint || `=${pre}${snakeCase(arg.name)}${post}`; +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 `=${pre}${arg.options.join("|")}${post}`; + return `=<${arg.options.join("|")}>`; } return fallbackValueHint; diff --git a/test/usage.test.ts b/test/usage.test.ts index 419fe1e..fb851cf 100644 --- a/test/usage.test.ts +++ b/test/usage.test.ts @@ -67,8 +67,8 @@ describe("usage", () => { OPTIONS \`--foo=\` A foo (Required) - \`-b, --bar=[bar]\` A bar - \`--enum=[a|b]\` An enum + \`-b, --bar=\` A bar + \`--enum=\` An enum \`--boolean\` A boolean " `); @@ -130,7 +130,7 @@ describe("usage", () => { OPTIONS - \`--foo=[FOO]\` A foo + \`--foo=\` A foo " `); }); @@ -159,7 +159,7 @@ describe("usage", () => { OPTIONS - \`--foo=[foo]\` A foo (Default: bar) + \`--foo=\` A foo (Default: bar) " `); }); @@ -309,7 +309,7 @@ describe("usage", () => { OPTIONS - \`--foo=[foo]\` A foo + \`--foo=\` A foo COMMANDS