@thi.ng/args
Version:
Declarative, functional CLI argument/options parser, app framework, arg value coercions, multi/sub-commands, usage generation, error handling etc.
73 lines (72 loc) • 2.38 kB
JavaScript
import { capitalize, kebab } from "@thi.ng/strings/case";
import { stringify } from "@thi.ng/strings/stringify";
import {
} from "./api.js";
import {
__ansi,
__colorTheme,
__padRightAnsi,
__wrap,
__wrapWithIndent
} from "./utils.js";
const usage = (specs, opts = {}) => {
opts = {
lineWidth: 80,
paramWidth: 32,
showDefaults: true,
prefix: "",
suffix: "",
groups: ["flags", "main"],
...opts
};
const theme = __colorTheme(opts.color);
const format = (ids) => ids.map(
(id) => __argUsage(id, specs[id], opts, theme, opts.paramWidth)
);
const sortedIDs = Object.keys(specs).sort();
const groups = opts.groups ? opts.groups.map(
(gid) => [
gid,
sortedIDs.filter((id) => specs[id].group === gid)
]
).filter((g) => !!g[1].length) : [["options", sortedIDs]];
return [
...__wrap(opts.prefix, opts.lineWidth),
...groups.map(
([gid, ids]) => [
...opts.showGroupNames ? [`${capitalize(gid)}:
`] : [],
...format(ids),
""
].join("\n")
),
...__wrap(opts.suffix, opts.lineWidth)
].join("\n");
};
const __argUsage = (id, spec, opts, theme, indent) => {
const hint = __argHint(spec, theme);
const alias = __argAlias(spec, theme, hint);
const name = __ansi(`--${kebab(id)}`, theme.param);
const params = `${alias}${name}${hint}`;
const isRequired = !!spec.required && spec.default === void 0;
const prefixes = [];
isRequired && prefixes.push("required");
spec.multi && prefixes.push("multiple");
const body = __argPrefix(prefixes, theme, isRequired) + (spec.desc || "") + __argDefault(spec, opts, theme);
return __padRightAnsi(params, opts.paramWidth) + __wrapWithIndent(body, indent, opts.lineWidth);
};
const __argHint = (spec, theme) => spec.hint ? __ansi(" " + spec.hint, theme.hint) : "";
const __argAlias = (spec, theme, hint) => spec.alias ? `${__ansi("-" + spec.alias, theme.param)}${hint}, ` : "";
const __argPrefix = (prefixes, theme, isRequired) => prefixes.length ? __ansi(
`[${prefixes.join(", ")}] `,
isRequired ? theme.required : theme.multi
) : "";
const __argDefault = (spec, opts, theme) => opts.showDefaults && spec.default != null && spec.default !== false ? __ansi(
` (default: ${stringify(true)(
spec.defaultHint != void 0 ? spec.defaultHint : spec.default
)})`,
theme.default
) : "";
export {
usage
};