zod-args-parser 1.0.13 → 1.0.14
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/README.md +12 -1
- package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js +42 -0
- package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js.map +1 -0
- package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js +31 -0
- package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -0
- package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js +41 -0
- package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -0
- package/lib/commonjs/help-message/colors.js +1 -0
- package/lib/commonjs/help-message/colors.js.map +1 -0
- package/lib/commonjs/help-message/print-arguments.js +1 -0
- package/lib/commonjs/help-message/print-arguments.js.map +1 -0
- package/lib/commonjs/help-message/print-help-message.js +1 -0
- package/lib/commonjs/help-message/print-help-message.js.map +1 -0
- package/lib/commonjs/help-message/print-options.js +1 -0
- package/lib/commonjs/help-message/print-options.js.map +1 -0
- package/lib/commonjs/help-message/print-subcommands.js +1 -0
- package/lib/commonjs/help-message/print-subcommands.js.map +1 -0
- package/lib/commonjs/help-message/utils.js +1 -0
- package/lib/commonjs/help-message/utils.js.map +1 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/markdown/generate-markdown.js +1 -0
- package/lib/commonjs/markdown/generate-markdown.js.map +1 -0
- package/lib/commonjs/metadata/get-arguments-metadata.js +1 -0
- package/lib/commonjs/metadata/get-arguments-metadata.js.map +1 -0
- package/lib/commonjs/metadata/get-cli-metadata.js +1 -0
- package/lib/commonjs/metadata/get-cli-metadata.js.map +1 -0
- package/lib/commonjs/metadata/get-options-metadata.js +1 -0
- package/lib/commonjs/metadata/get-options-metadata.js.map +1 -0
- package/lib/commonjs/metadata/get-subcommands-metadata.js +1 -0
- package/lib/commonjs/metadata/get-subcommands-metadata.js.map +1 -0
- package/lib/commonjs/parser/parse.js +1 -0
- package/lib/commonjs/parser/parse.js.map +1 -0
- package/lib/commonjs/parser/safe-parse.js +1 -0
- package/lib/commonjs/parser/safe-parse.js.map +1 -0
- package/lib/commonjs/utils.js +1 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/autocomplete-scripts/bash-autocomplete-script.js +42 -0
- package/lib/module/autocomplete-scripts/bash-autocomplete-script.js.map +1 -0
- package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js +31 -0
- package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -0
- package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js +41 -0
- package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -0
- package/lib/module/help-message/colors.js +1 -0
- package/lib/module/help-message/colors.js.map +1 -0
- package/lib/module/help-message/print-arguments.js +1 -0
- package/lib/module/help-message/print-arguments.js.map +1 -0
- package/lib/module/help-message/print-help-message.js +1 -0
- package/lib/module/help-message/print-help-message.js.map +1 -0
- package/lib/module/help-message/print-options.js +1 -0
- package/lib/module/help-message/print-options.js.map +1 -0
- package/lib/module/help-message/print-subcommands.js +1 -0
- package/lib/module/help-message/print-subcommands.js.map +1 -0
- package/lib/module/help-message/utils.js +1 -0
- package/lib/module/help-message/utils.js.map +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/markdown/generate-markdown.js +1 -0
- package/lib/module/markdown/generate-markdown.js.map +1 -0
- package/lib/module/metadata/get-arguments-metadata.js +1 -0
- package/lib/module/metadata/get-arguments-metadata.js.map +1 -0
- package/lib/module/metadata/get-cli-metadata.js +1 -0
- package/lib/module/metadata/get-cli-metadata.js.map +1 -0
- package/lib/module/metadata/get-options-metadata.js +1 -0
- package/lib/module/metadata/get-options-metadata.js.map +1 -0
- package/lib/module/metadata/get-subcommands-metadata.js +1 -0
- package/lib/module/metadata/get-subcommands-metadata.js.map +1 -0
- package/lib/module/parser/parse.js +1 -0
- package/lib/module/parser/parse.js.map +1 -0
- package/lib/module/parser/safe-parse.js +1 -0
- package/lib/module/parser/safe-parse.js.map +1 -0
- package/lib/module/utils.js +1 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/autocomplete-scripts/bash-autocomplete-script.d.ts +11 -0
- package/lib/typescript/autocomplete-scripts/bash-autocomplete-script.d.ts.map +1 -0
- package/lib/typescript/autocomplete-scripts/powershell-autocomplete-script.d.ts +14 -0
- package/lib/typescript/autocomplete-scripts/powershell-autocomplete-script.d.ts.map +1 -0
- package/lib/typescript/autocomplete-scripts/zsh-autocomplete-script.d.ts +11 -0
- package/lib/typescript/autocomplete-scripts/zsh-autocomplete-script.d.ts.map +1 -0
- package/lib/typescript/help-message/colors.d.ts +17 -0
- package/lib/typescript/help-message/colors.d.ts.map +1 -0
- package/lib/typescript/help-message/print-arguments.d.ts +4 -0
- package/lib/typescript/help-message/print-arguments.d.ts.map +1 -0
- package/lib/typescript/help-message/print-help-message.d.ts +4 -0
- package/lib/typescript/help-message/print-help-message.d.ts.map +1 -0
- package/lib/typescript/help-message/print-options.d.ts +4 -0
- package/lib/typescript/help-message/print-options.d.ts.map +1 -0
- package/lib/typescript/help-message/print-subcommands.d.ts +4 -0
- package/lib/typescript/help-message/print-subcommands.d.ts.map +1 -0
- package/lib/typescript/help-message/utils.d.ts +13 -0
- package/lib/typescript/help-message/utils.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +11 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/markdown/generate-markdown.d.ts +3 -0
- package/lib/typescript/markdown/generate-markdown.d.ts.map +1 -0
- package/lib/typescript/metadata/get-arguments-metadata.d.ts +3 -0
- package/lib/typescript/metadata/get-arguments-metadata.d.ts.map +1 -0
- package/lib/typescript/metadata/get-cli-metadata.d.ts +3 -0
- package/lib/typescript/metadata/get-cli-metadata.d.ts.map +1 -0
- package/lib/typescript/metadata/get-options-metadata.d.ts +3 -0
- package/lib/typescript/metadata/get-options-metadata.d.ts.map +1 -0
- package/lib/typescript/metadata/get-subcommands-metadata.d.ts +3 -0
- package/lib/typescript/metadata/get-subcommands-metadata.d.ts.map +1 -0
- package/lib/typescript/parser/parse.d.ts +3 -0
- package/lib/typescript/parser/parse.d.ts.map +1 -0
- package/lib/typescript/parser/safe-parse.d.ts +3 -0
- package/lib/typescript/parser/safe-parse.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +80 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils.d.ts +0 -12
- package/lib/typescript/utils.d.ts.map +1 -1
- package/package.json +22 -22
- package/src/autocomplete-scripts/bash-autocomplete-script.ts +81 -0
- package/src/autocomplete-scripts/powershell-autocomplete-script.ts +78 -0
- package/src/autocomplete-scripts/zsh-autocomplete-script.ts +69 -0
- package/src/help-message/colors.ts +24 -0
- package/src/help-message/print-arguments.ts +35 -0
- package/src/help-message/print-help-message.ts +126 -0
- package/src/help-message/print-options.ts +40 -0
- package/src/help-message/print-subcommands.ts +28 -0
- package/src/help-message/utils.ts +31 -0
- package/src/index.ts +13 -10
- package/src/markdown/generate-markdown.ts +172 -0
- package/src/metadata/get-arguments-metadata.ts +23 -0
- package/src/metadata/get-cli-metadata.ts +23 -0
- package/src/metadata/get-options-metadata.ts +30 -0
- package/src/metadata/get-subcommands-metadata.ts +29 -0
- package/src/{parser.ts → parser/parse.ts} +4 -54
- package/src/parser/safe-parse.ts +45 -0
- package/src/types.ts +116 -0
- package/src/utils.ts +0 -32
- package/lib/commonjs/autocomplete.js +0 -107
- package/lib/commonjs/autocomplete.js.map +0 -1
- package/lib/commonjs/help.js +0 -1
- package/lib/commonjs/help.js.map +0 -1
- package/lib/commonjs/parser.js +0 -1
- package/lib/commonjs/parser.js.map +0 -1
- package/lib/module/autocomplete.js +0 -107
- package/lib/module/autocomplete.js.map +0 -1
- package/lib/module/help.js +0 -1
- package/lib/module/help.js.map +0 -1
- package/lib/module/parser.js +0 -1
- package/lib/module/parser.js.map +0 -1
- package/lib/typescript/autocomplete.d.ts +0 -32
- package/lib/typescript/autocomplete.d.ts.map +0 -1
- package/lib/typescript/help.d.ts +0 -9
- package/lib/typescript/help.d.ts.map +0 -1
- package/lib/typescript/parser.d.ts +0 -4
- package/lib/typescript/parser.d.ts.map +0 -1
- package/src/autocomplete.ts +0 -217
- package/src/help.ts +0 -341
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { transformOptionToArg } from "../utils.js";
|
|
2
|
+
|
|
3
|
+
import type { Cli, Subcommand } from "../types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* - Generates a PowerShell autocomplete script for your CLI.
|
|
7
|
+
* - The script assumes that your CLI is available as a `.ps1` file in the environment variable. For example:
|
|
8
|
+
* `cliName.ps1`.
|
|
9
|
+
* - This should return a path to your script: `(Get-Command <cliName>.ps1).Source`
|
|
10
|
+
* - The generated script should be added to your `profile.ps1` file:
|
|
11
|
+
*
|
|
12
|
+
* - Run: `notepad $profile`
|
|
13
|
+
* - Add the following line: `. "<generated script path>"`
|
|
14
|
+
* - Save and reopen powershell to take effect
|
|
15
|
+
*/
|
|
16
|
+
export function generatePowerShellAutocompleteScript(...params: [Cli, ...Subcommand[]]): string {
|
|
17
|
+
const [cli, ...subcommands] = params;
|
|
18
|
+
|
|
19
|
+
type MappedCommands = Record<string, { options: string[]; aliases: string[] }>;
|
|
20
|
+
|
|
21
|
+
const mappedCommands = subcommands.reduce((acc: MappedCommands, subcommand) => {
|
|
22
|
+
acc[subcommand.name] = {
|
|
23
|
+
options: subcommand.options?.map(option => transformOptionToArg(option.name)) ?? [],
|
|
24
|
+
aliases: subcommand.aliases ?? [],
|
|
25
|
+
};
|
|
26
|
+
return acc;
|
|
27
|
+
}, {});
|
|
28
|
+
|
|
29
|
+
const subcommandsStr = Object.keys(mappedCommands)
|
|
30
|
+
.map(key => `'${key}'`)
|
|
31
|
+
.join(", ");
|
|
32
|
+
const cliOptionsStr = cli.options?.map(option => `'${transformOptionToArg(option.name)}'`).join(", ") || "";
|
|
33
|
+
|
|
34
|
+
let switchCase = "switch ($subcommand) {\n";
|
|
35
|
+
for (const [key, { options, aliases }] of Object.entries(mappedCommands)) {
|
|
36
|
+
const optionsStr = options.map(option => `'${option}'`).join(", ");
|
|
37
|
+
switchCase += ` '${key}' { @(${optionsStr}) }\n`;
|
|
38
|
+
aliases.forEach(a => (switchCase += ` '${a}' { @(${optionsStr}) }\n`));
|
|
39
|
+
}
|
|
40
|
+
switchCase += ` default { @(${cliOptionsStr}) }\n }`;
|
|
41
|
+
|
|
42
|
+
let functionInfo = "";
|
|
43
|
+
if (cli.description) {
|
|
44
|
+
functionInfo = `<#\n.DESCRIPTION\n${cli.description}\n${cli.example ? `\n.EXAMPLE\n${cli.example}` : ""}\n#>`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return `# Auto-generated by zod-args-parser
|
|
48
|
+
|
|
49
|
+
${functionInfo}
|
|
50
|
+
function ${cli.cliName} {
|
|
51
|
+
param(
|
|
52
|
+
[Parameter(Position = 0, Mandatory = $false)]
|
|
53
|
+
[string]$subcommand,
|
|
54
|
+
[Parameter(Position = 1, ValueFromRemainingArguments = $true)]
|
|
55
|
+
[string[]]$arguments
|
|
56
|
+
)
|
|
57
|
+
$scriptPath = (Get-Command '${cli.cliName}.ps1').Source
|
|
58
|
+
if ($scriptPath) {
|
|
59
|
+
$argumentList = @($subcommand) + ($arguments | Where-Object { $_ -notin '--', '--%' }) | Where-Object { $_ -ne '' }
|
|
60
|
+
& $scriptPath @argumentList
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
Write-Error "Could not find '${cli.cliName}.ps1' script"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Register-ArgumentCompleter -CommandName '${cli.cliName}' -ParameterName 'subcommand' -ScriptBlock {
|
|
67
|
+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
|
|
68
|
+
$subcommands = @(${subcommandsStr}${subcommandsStr && cliOptionsStr ? ", " : ""}${cliOptionsStr})
|
|
69
|
+
$subcommands | Where-Object { $_ -like "$wordToComplete*" }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Register-ArgumentCompleter -CommandName '${cli.cliName}' -ParameterName 'arguments' -ScriptBlock {
|
|
73
|
+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
|
|
74
|
+
$subcommand = $commandAst.CommandElements[1].Value
|
|
75
|
+
$arguments = ${switchCase}
|
|
76
|
+
$arguments | Where-Object { $_ -like "$wordToComplete*" }
|
|
77
|
+
}`;
|
|
78
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { transformOptionToArg } from "../utils.js";
|
|
2
|
+
|
|
3
|
+
import type { Cli, Option, Subcommand } from "../types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* - Generates a ZSH autocomplete script for your CLI.
|
|
7
|
+
* - The generated script should be added to your `~/.zshrc` or `~/.zsh_profile` file:
|
|
8
|
+
*
|
|
9
|
+
* - Run: `nano $HOME/.zshrc` or `nano $HOME/.zsh_profile`
|
|
10
|
+
* - Add the following line: `source <generated script path>`
|
|
11
|
+
* - Save and reopen zsh to take effect
|
|
12
|
+
*/
|
|
13
|
+
export function generateZshAutocompleteScript(...params: [Cli, ...Subcommand[]]): string {
|
|
14
|
+
const [cli, ...subcommands] = params;
|
|
15
|
+
|
|
16
|
+
const genArguments = (options: Option[]) => {
|
|
17
|
+
return options
|
|
18
|
+
?.map(option => `'${transformOptionToArg(option.name)}[${option.description ?? ""}]'`)
|
|
19
|
+
.join(" \\\n ");
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const genSubCommand = (subcommand: Subcommand) => {
|
|
23
|
+
const options = subcommand.options;
|
|
24
|
+
if (!options || options.length === 0) return "";
|
|
25
|
+
return `${subcommand.name})
|
|
26
|
+
_arguments \\
|
|
27
|
+
${genArguments(options)} \\
|
|
28
|
+
'*: :_files' \\
|
|
29
|
+
&& ret=0
|
|
30
|
+
;;`;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return `# Auto-generated by zod-args-parser
|
|
34
|
+
|
|
35
|
+
_${cli.cliName}_autocomplete() {
|
|
36
|
+
local ret=1
|
|
37
|
+
|
|
38
|
+
_arguments -C \\
|
|
39
|
+
'1: :_${cli.cliName}_commands' \\
|
|
40
|
+
'*:: :->subcmds' \\
|
|
41
|
+
&& ret=0
|
|
42
|
+
|
|
43
|
+
case $state in
|
|
44
|
+
subcmds)
|
|
45
|
+
case "$words[1]" in
|
|
46
|
+
${subcommands.map(genSubCommand).filter(Boolean).join("\n ")}
|
|
47
|
+
*)
|
|
48
|
+
_arguments \\
|
|
49
|
+
'*: :_files' \\
|
|
50
|
+
&& ret=0
|
|
51
|
+
;;
|
|
52
|
+
esac
|
|
53
|
+
;;
|
|
54
|
+
esac
|
|
55
|
+
|
|
56
|
+
return $ret
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_${cli.cliName}_commands() {
|
|
60
|
+
local -a commands=(
|
|
61
|
+
${subcommands.map(subcommand => `"${subcommand.name}:${subcommand.description ?? ""}"`).join("\n ")}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_describe -t subcommands 'subcommand' commands
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
compdef _${cli.cliName}_autocomplete ${cli.cliName}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import type { PrintHelpOpt } from "../types.js";
|
|
3
|
+
|
|
4
|
+
export type PrintHelpColors = NonNullable<Required<PrintHelpOpt["customColors"]>>;
|
|
5
|
+
|
|
6
|
+
export const printColors: PrintHelpColors = {
|
|
7
|
+
title: chalk.bold.blue,
|
|
8
|
+
description: chalk.white,
|
|
9
|
+
default: chalk.dim.italic,
|
|
10
|
+
optional: chalk.dim.italic,
|
|
11
|
+
exampleTitle: chalk.yellow,
|
|
12
|
+
example: chalk.dim,
|
|
13
|
+
command: chalk.yellow,
|
|
14
|
+
option: chalk.cyan,
|
|
15
|
+
argument: chalk.green,
|
|
16
|
+
placeholder: chalk.hex("#FF9800"),
|
|
17
|
+
punctuation: chalk.white.dim,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const noColors = new Proxy(printColors, {
|
|
21
|
+
get: () => {
|
|
22
|
+
return (...str: string[]) => str.join(" ");
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { indent, print, println } from "./utils.js";
|
|
2
|
+
|
|
3
|
+
import type { ArgumentMetadata } from "../types.js";
|
|
4
|
+
import type { PrintHelpColors } from "./colors.js";
|
|
5
|
+
|
|
6
|
+
export function printPreparedArguments(argsMetadata: ArgumentMetadata[], c: PrintHelpColors, longest: number) {
|
|
7
|
+
if (!argsMetadata.length) return;
|
|
8
|
+
|
|
9
|
+
print(c.title(" ARGUMENTS "));
|
|
10
|
+
|
|
11
|
+
println();
|
|
12
|
+
|
|
13
|
+
for (const metadata of argsMetadata) {
|
|
14
|
+
const defaultStr =
|
|
15
|
+
typeof metadata.defaultValue !== "undefined" ? `(default: ${metadata.defaultValueAsString})` : "";
|
|
16
|
+
|
|
17
|
+
const spacing = longest + 2 - metadata.name.length;
|
|
18
|
+
const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 6) + c.punctuation("└"));
|
|
19
|
+
|
|
20
|
+
println(
|
|
21
|
+
indent(2),
|
|
22
|
+
c.argument(metadata.name),
|
|
23
|
+
indent(spacing),
|
|
24
|
+
c.description(normalizeDesc),
|
|
25
|
+
defaultStr ? c.default(defaultStr) : c.optional(metadata.optional),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (metadata.example) {
|
|
29
|
+
const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(longest + 16));
|
|
30
|
+
println(indent(longest + 5), c.punctuation("└") + c.exampleTitle("Example:"), c.example(normalizeExample));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
println();
|
|
35
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { getCliMetadata } from "../metadata/get-cli-metadata.js";
|
|
2
|
+
import { noColors, printColors } from "./colors.js";
|
|
3
|
+
import { printPreparedArguments } from "./print-arguments.js";
|
|
4
|
+
import { printOptions } from "./print-options.js";
|
|
5
|
+
import { printSubcommands } from "./print-subcommands.js";
|
|
6
|
+
import { concat, indent, ln, print, println } from "./utils.js";
|
|
7
|
+
|
|
8
|
+
import type { Cli, PrintHelpOpt, Subcommand } from "../types.js";
|
|
9
|
+
|
|
10
|
+
export function printCliHelp(params: [Cli, ...Subcommand[]], printConfig: PrintHelpOpt = {}) {
|
|
11
|
+
printConfig.colors ??= true;
|
|
12
|
+
|
|
13
|
+
const c = printConfig.colors ? printColors : noColors;
|
|
14
|
+
|
|
15
|
+
const metadata = getCliMetadata(params);
|
|
16
|
+
|
|
17
|
+
if (printConfig.customColors) {
|
|
18
|
+
Object.assign(c, printConfig.customColors);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Print a styled title */
|
|
22
|
+
const printTitle = (title: string) => {
|
|
23
|
+
print(c.title(` ${title.toUpperCase()} `));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Print CLI usage
|
|
27
|
+
const usage =
|
|
28
|
+
metadata.usage ||
|
|
29
|
+
concat(
|
|
30
|
+
c.punctuation("$"),
|
|
31
|
+
metadata.name,
|
|
32
|
+
metadata.subcommands.length ? c.command("[command]") : "",
|
|
33
|
+
metadata.options.length ? c.option("[options]") : "",
|
|
34
|
+
metadata.arguments.length || metadata.allowPositional ? c.argument("<arguments>") : "",
|
|
35
|
+
);
|
|
36
|
+
printTitle("Usage");
|
|
37
|
+
println();
|
|
38
|
+
println(indent(2), usage, ln(1));
|
|
39
|
+
|
|
40
|
+
// Print CLI description
|
|
41
|
+
if (metadata.description) {
|
|
42
|
+
printTitle("Description");
|
|
43
|
+
println();
|
|
44
|
+
println(indent(2), c.description(metadata.description), ln(1));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let longest = 0;
|
|
48
|
+
|
|
49
|
+
// Prepare CLI options
|
|
50
|
+
const optionsMetadata = metadata.options;
|
|
51
|
+
|
|
52
|
+
const longestOptionTitle = optionsMetadata.reduce((acc, metadata) => {
|
|
53
|
+
const names = metadata.aliasesAsArgs.concat([metadata.nameAsArg]).join(", ");
|
|
54
|
+
const optLength = names.length + metadata.placeholder.length;
|
|
55
|
+
return optLength > acc ? optLength : acc;
|
|
56
|
+
}, 0);
|
|
57
|
+
|
|
58
|
+
if (longestOptionTitle > longest) {
|
|
59
|
+
longest = longestOptionTitle;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Prepare CLI commands
|
|
63
|
+
const subcommandsMetadata = metadata.subcommands;
|
|
64
|
+
|
|
65
|
+
const longestSubcommandTitle = subcommandsMetadata.reduce((acc, metadata) => {
|
|
66
|
+
const names = metadata.aliases.concat([metadata.name]).join(", ");
|
|
67
|
+
const placeholder =
|
|
68
|
+
metadata.placeholder || (metadata.options.length ? "[options]" : metadata.allowPositional ? "<args>" : " ");
|
|
69
|
+
const optLength = names.length + placeholder.length;
|
|
70
|
+
return optLength > acc ? optLength : acc;
|
|
71
|
+
}, 0);
|
|
72
|
+
|
|
73
|
+
if (longestSubcommandTitle > longest) {
|
|
74
|
+
longest = longestSubcommandTitle;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Prepare CLI arguments
|
|
78
|
+
const argsMetadata = metadata.arguments;
|
|
79
|
+
|
|
80
|
+
const longestArgTitle = argsMetadata.reduce((acc, arg) => (arg.name.length > acc ? arg.name.length : acc), 0);
|
|
81
|
+
|
|
82
|
+
if (longestArgTitle > longest) {
|
|
83
|
+
longest = longestArgTitle;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Print CLI options
|
|
87
|
+
printOptions(optionsMetadata, c, longest);
|
|
88
|
+
|
|
89
|
+
// Print CLI commands
|
|
90
|
+
printSubcommands(subcommandsMetadata, c, longest);
|
|
91
|
+
|
|
92
|
+
// Print CLI arguments
|
|
93
|
+
printPreparedArguments(argsMetadata, c, longest);
|
|
94
|
+
|
|
95
|
+
// Print CLI example
|
|
96
|
+
if (metadata.example) {
|
|
97
|
+
printTitle("Example");
|
|
98
|
+
println();
|
|
99
|
+
const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(3));
|
|
100
|
+
println(indent(2), c.example(normalizeExample), ln(1));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function printSubcommandHelp(subcommand: Subcommand, printConfig: PrintHelpOpt = {}, cliName = "") {
|
|
105
|
+
printConfig.colors ??= true;
|
|
106
|
+
|
|
107
|
+
const c = printConfig.colors ? printColors : noColors;
|
|
108
|
+
|
|
109
|
+
const usage =
|
|
110
|
+
subcommand.usage ||
|
|
111
|
+
concat(
|
|
112
|
+
c.punctuation("$"),
|
|
113
|
+
cliName,
|
|
114
|
+
c.command(subcommand.name),
|
|
115
|
+
subcommand.options?.length ? c.option("[options]") : "",
|
|
116
|
+
subcommand.arguments?.length || subcommand.allowPositional ? c.argument("<arguments>") : "",
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const asCli: Cli = {
|
|
120
|
+
cliName,
|
|
121
|
+
usage,
|
|
122
|
+
...subcommand,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
printCliHelp([asCli], printConfig);
|
|
126
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { indent, print, println } from "./utils.js";
|
|
2
|
+
|
|
3
|
+
import type { PrintHelpColors } from "./colors.js";
|
|
4
|
+
import type { OptionMetadata } from "../types.js";
|
|
5
|
+
|
|
6
|
+
export function printOptions(optionsMetadata: OptionMetadata[], c: PrintHelpColors, longest: number) {
|
|
7
|
+
if (!optionsMetadata.length) return;
|
|
8
|
+
|
|
9
|
+
print(c.title(" OPTIONS "));
|
|
10
|
+
|
|
11
|
+
println();
|
|
12
|
+
|
|
13
|
+
for (const metadata of optionsMetadata) {
|
|
14
|
+
const names = metadata.aliasesAsArgs.concat([metadata.nameAsArg]);
|
|
15
|
+
const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 7) + c.punctuation("└"));
|
|
16
|
+
const defaultStr =
|
|
17
|
+
typeof metadata.defaultValue !== "undefined" ? `(default: ${metadata.defaultValueAsString})` : "";
|
|
18
|
+
|
|
19
|
+
const optLength = names.join(", ").length + metadata.placeholder.length;
|
|
20
|
+
const spacing = longest + 1 - optLength;
|
|
21
|
+
|
|
22
|
+
const coloredNames = names.map(name => c.option(name)).join(c.punctuation(", "));
|
|
23
|
+
|
|
24
|
+
println(
|
|
25
|
+
indent(2),
|
|
26
|
+
coloredNames,
|
|
27
|
+
c.placeholder(metadata.placeholder),
|
|
28
|
+
indent(spacing),
|
|
29
|
+
c.description(normalizeDesc),
|
|
30
|
+
defaultStr ? c.default(defaultStr) : c.optional(metadata.optional),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (metadata.example) {
|
|
34
|
+
const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(longest + 17));
|
|
35
|
+
println(indent(longest + 6), c.punctuation("└") + c.exampleTitle("Example:"), c.example(normalizeExample));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
println();
|
|
40
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { indent, print, println } from "./utils.js";
|
|
2
|
+
|
|
3
|
+
import type { SubcommandMetadata } from "src/types.js";
|
|
4
|
+
import type { PrintHelpColors } from "./colors.js";
|
|
5
|
+
|
|
6
|
+
export function printSubcommands(subcommandsMetadata: SubcommandMetadata[], c: PrintHelpColors, longest: number) {
|
|
7
|
+
if (!subcommandsMetadata.length) return;
|
|
8
|
+
|
|
9
|
+
print(c.title(" COMMANDS "));
|
|
10
|
+
|
|
11
|
+
println();
|
|
12
|
+
|
|
13
|
+
for (const metadata of subcommandsMetadata) {
|
|
14
|
+
const names = metadata.aliases.concat([metadata.name]);
|
|
15
|
+
const placeholder =
|
|
16
|
+
metadata.placeholder || (metadata.options.length ? "[options]" : metadata.allowPositional ? "<args>" : " ");
|
|
17
|
+
const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 7) + c.punctuation("└"));
|
|
18
|
+
|
|
19
|
+
const optLength = names.join(", ").length + placeholder.length;
|
|
20
|
+
const spacing = longest + 1 - optLength;
|
|
21
|
+
|
|
22
|
+
const coloredNames = names.map(name => c.command(name)).join(c.punctuation(", "));
|
|
23
|
+
|
|
24
|
+
println(indent(2), coloredNames, c.placeholder(placeholder), indent(spacing), c.description(normalizeDesc));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
println();
|
|
28
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Print */
|
|
2
|
+
export function print(...messages: string[]) {
|
|
3
|
+
return process.stdout.write(messages.join(" "));
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Print line */
|
|
7
|
+
export function println(...messages: string[]) {
|
|
8
|
+
messages = messages.filter(Boolean);
|
|
9
|
+
return console.log(...messages);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** New line */
|
|
13
|
+
export function ln(count: number) {
|
|
14
|
+
return "\n".repeat(count);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Space */
|
|
18
|
+
export function indent(count: number) {
|
|
19
|
+
return " ".repeat(count);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Add indent before each new line */
|
|
23
|
+
export function addIndentLn(message: string, indent: string = "") {
|
|
24
|
+
return message.replace(/\n/g, `\n${indent}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Concat strings */
|
|
28
|
+
export function concat(...messages: string[]) {
|
|
29
|
+
messages = messages.filter(Boolean);
|
|
30
|
+
return messages.join(" ");
|
|
31
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { help } from "./help.js";
|
|
2
|
-
|
|
3
1
|
import type {
|
|
4
2
|
ActionFn,
|
|
5
3
|
Argument,
|
|
@@ -74,15 +72,20 @@ export function createArguments<const T extends [Argument, ...Argument[]]>(args:
|
|
|
74
72
|
return args;
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
export { printCliHelp, printSubcommandHelp } from "./help-message/print-help-message.js";
|
|
76
|
+
|
|
77
|
+
export { parse } from "./parser/parse.js";
|
|
78
|
+
export { safeParse } from "./parser/safe-parse.js";
|
|
79
|
+
|
|
80
|
+
export { generateBashAutocompleteScript } from "./autocomplete-scripts/bash-autocomplete-script.js";
|
|
81
|
+
export { generatePowerShellAutocompleteScript } from "./autocomplete-scripts/powershell-autocomplete-script.js";
|
|
82
|
+
export { generateZshAutocompleteScript } from "./autocomplete-scripts/zsh-autocomplete-script.js";
|
|
79
83
|
|
|
80
|
-
export {
|
|
84
|
+
export { getArgumentsMetadata } from "./metadata/get-arguments-metadata.js";
|
|
85
|
+
export { getCliMetadata } from "./metadata/get-cli-metadata.js";
|
|
86
|
+
export { getOptionsMetadata } from "./metadata/get-options-metadata.js";
|
|
87
|
+
export { getSubcommandsMetadata } from "./metadata/get-subcommands-metadata.js";
|
|
81
88
|
|
|
82
|
-
export {
|
|
83
|
-
generateBashAutocompleteScript,
|
|
84
|
-
generateZshAutocompleteScript,
|
|
85
|
-
generatePowerShellAutocompleteScript,
|
|
86
|
-
} from "./autocomplete.js";
|
|
89
|
+
export { generateMarkdown } from "./markdown/generate-markdown.js";
|
|
87
90
|
|
|
88
91
|
export type * from "./types.js";
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { getCliMetadata } from "../metadata/get-cli-metadata.js";
|
|
2
|
+
|
|
3
|
+
import type { ArgumentMetadata, Cli, OptionMetadata, Subcommand, SubcommandMetadata } from "../types.js";
|
|
4
|
+
|
|
5
|
+
export function generateMarkdown(...params: [Cli, ...Subcommand[]]): string {
|
|
6
|
+
const metadata = getCliMetadata(params);
|
|
7
|
+
|
|
8
|
+
let md = "<!-- Auto-generated by zod-args-parser -->\n\n";
|
|
9
|
+
|
|
10
|
+
// Title
|
|
11
|
+
md += `# ${metadata.name}\n\n`;
|
|
12
|
+
|
|
13
|
+
// Description
|
|
14
|
+
if (metadata.description) {
|
|
15
|
+
md += `${metadata.description}\n`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Examples
|
|
19
|
+
if (metadata.example) {
|
|
20
|
+
md += renderExamples(metadata.example);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Options
|
|
24
|
+
if (metadata.options.length) {
|
|
25
|
+
md += "\n## Options:\n\n";
|
|
26
|
+
md += renderOptions(metadata.options, 3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Arguments
|
|
30
|
+
if (metadata.arguments.length) {
|
|
31
|
+
md += "\n## Arguments:\n\n";
|
|
32
|
+
md += renderArguments(metadata.arguments, 3);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Subcommands
|
|
36
|
+
if (metadata.subcommands.length) {
|
|
37
|
+
md += "\n## Subcommands:\n\n";
|
|
38
|
+
md += renderSubcommands(metadata.subcommands);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return md;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function renderExamples(examples: string, list = false) {
|
|
45
|
+
let outStr = "";
|
|
46
|
+
|
|
47
|
+
const lang = "bash";
|
|
48
|
+
|
|
49
|
+
const listIndent = " ".repeat(list ? 2 : 0);
|
|
50
|
+
|
|
51
|
+
outStr += "\n" + (list ? "- " : "");
|
|
52
|
+
|
|
53
|
+
outStr += "```" + lang + "\n";
|
|
54
|
+
outStr += listIndent + examples.replace(/\n/g, "\n" + listIndent);
|
|
55
|
+
outStr += "\n" + listIndent + "```\n";
|
|
56
|
+
|
|
57
|
+
return outStr;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function renderOptions(optionsMetadata: OptionMetadata[] = [], h: number) {
|
|
61
|
+
let outStr = "";
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < optionsMetadata.length; i++) {
|
|
64
|
+
const metadata = optionsMetadata[i];
|
|
65
|
+
|
|
66
|
+
const aliases = [metadata.nameAsArg].concat(metadata.aliasesAsArgs).join(", ");
|
|
67
|
+
|
|
68
|
+
const placeholder = metadata.placeholder && ` ${metadata.placeholder}`;
|
|
69
|
+
|
|
70
|
+
outStr += `${"#".repeat(h)} \`${aliases + placeholder}\``;
|
|
71
|
+
|
|
72
|
+
if (metadata.optional) {
|
|
73
|
+
outStr += " **[optional]**";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
outStr += "\n\n";
|
|
77
|
+
|
|
78
|
+
if (metadata.description) {
|
|
79
|
+
outStr += `- ${metadata.description}\n`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (typeof metadata.defaultValue !== "undefined") {
|
|
83
|
+
outStr += `- **default:** \`${metadata.defaultValueAsString}\`\n`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (metadata.example) {
|
|
87
|
+
outStr += renderExamples(metadata.example, true);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (i < optionsMetadata.length - 1) {
|
|
91
|
+
outStr += "\n";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return outStr;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function renderArguments(argsMetadata: ArgumentMetadata[] = [], h: number) {
|
|
99
|
+
let outStr = "";
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < argsMetadata.length; i++) {
|
|
102
|
+
const metadata = argsMetadata[i];
|
|
103
|
+
|
|
104
|
+
outStr += `${"#".repeat(h)} \`${metadata.name}\``;
|
|
105
|
+
|
|
106
|
+
if (metadata.optional) {
|
|
107
|
+
outStr += " **[optional]**";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
outStr += "\n\n";
|
|
111
|
+
|
|
112
|
+
if (metadata.description) {
|
|
113
|
+
outStr += `- ${metadata.description}\n`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (typeof metadata.defaultValue !== "undefined") {
|
|
117
|
+
outStr += `- **default:** \`${metadata.defaultValueAsString}\`\n`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (metadata.example) {
|
|
121
|
+
outStr += renderExamples(metadata.example);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (i < argsMetadata.length - 1) {
|
|
125
|
+
outStr += "\n";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return outStr;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function renderSubcommands(subcommandsMetadata: SubcommandMetadata[]) {
|
|
133
|
+
let outStr = "";
|
|
134
|
+
|
|
135
|
+
for (let i = 0; i < subcommandsMetadata.length; i++) {
|
|
136
|
+
const metadata = subcommandsMetadata[i];
|
|
137
|
+
|
|
138
|
+
const aliases = [metadata.name].concat(metadata.aliases).join(", ");
|
|
139
|
+
|
|
140
|
+
const placeholder = metadata.placeholder && ` ${escapeTags(metadata.placeholder)}`;
|
|
141
|
+
|
|
142
|
+
outStr += `### ${aliases + placeholder}\n\n`;
|
|
143
|
+
|
|
144
|
+
if (metadata.description) {
|
|
145
|
+
outStr += `${metadata.description}\n`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (metadata.example) {
|
|
149
|
+
outStr += renderExamples(metadata.example);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (metadata.options.length) {
|
|
153
|
+
outStr += "\n#### Options:\n\n";
|
|
154
|
+
outStr += renderOptions(metadata.options, 4);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (metadata.arguments.length) {
|
|
158
|
+
outStr += "\n#### Arguments:\n\n";
|
|
159
|
+
outStr += renderArguments(metadata.arguments, 4);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (i < subcommandsMetadata.length - 1) {
|
|
163
|
+
outStr += "\n---\n\n";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return outStr;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function escapeTags(str: string) {
|
|
171
|
+
return str.replace(/</g, "<").replace(/>/g, ">");
|
|
172
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getDefaultValueFromSchema } from "../utils.js";
|
|
2
|
+
|
|
3
|
+
import type { Argument, ArgumentMetadata } from "../types.js";
|
|
4
|
+
|
|
5
|
+
export function getArgumentsMetadata(args: Argument[]): ArgumentMetadata[] {
|
|
6
|
+
const outputMetadata: ArgumentMetadata[] = [];
|
|
7
|
+
|
|
8
|
+
for (const arg of args) {
|
|
9
|
+
const defaultValue = getDefaultValueFromSchema(arg.type);
|
|
10
|
+
|
|
11
|
+
outputMetadata.push({
|
|
12
|
+
name: arg.name,
|
|
13
|
+
description: arg.description ?? arg.type.description ?? "",
|
|
14
|
+
defaultValue,
|
|
15
|
+
defaultValueAsString: JSON.stringify(defaultValue),
|
|
16
|
+
optional: arg.type.isOptional(),
|
|
17
|
+
example: arg.example ?? "",
|
|
18
|
+
type: arg.type,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return outputMetadata;
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getOptionsMetadata } from "./get-options-metadata.js";
|
|
2
|
+
import { getArgumentsMetadata } from "./get-arguments-metadata.js";
|
|
3
|
+
import { getSubcommandsMetadata } from "./get-subcommands-metadata.js";
|
|
4
|
+
|
|
5
|
+
import type { Cli, CliMetadata, Subcommand } from "../types.js";
|
|
6
|
+
|
|
7
|
+
export function getCliMetadata(inputData: [Cli, ...Subcommand[]]): CliMetadata {
|
|
8
|
+
const [cli, ...subcommands] = inputData;
|
|
9
|
+
|
|
10
|
+
const outputMetadata: CliMetadata = {
|
|
11
|
+
name: cli.cliName,
|
|
12
|
+
description: cli.description ?? "",
|
|
13
|
+
placeholder: cli.placeholder ?? "",
|
|
14
|
+
usage: cli.usage ?? "",
|
|
15
|
+
example: cli.example ?? "",
|
|
16
|
+
allowPositional: cli.allowPositional ?? false,
|
|
17
|
+
options: cli.options ? getOptionsMetadata(cli.options) : [],
|
|
18
|
+
arguments: cli.arguments ? getArgumentsMetadata(cli.arguments) : [],
|
|
19
|
+
subcommands: subcommands ? getSubcommandsMetadata(subcommands) : [],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return outputMetadata;
|
|
23
|
+
}
|