@thi.ng/args
Version:
Declarative, functional & typechecked CLI argument/options parser, value coercions etc.
77 lines (76 loc) • 2.94 kB
JavaScript
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
import { lengthAnsi } from "@thi.ng/strings/ansi";
import { capitalize, kebab } from "@thi.ng/strings/case";
import { padRight } from "@thi.ng/strings/pad-right";
import { repeat } from "@thi.ng/strings/repeat";
import { stringify } from "@thi.ng/strings/stringify";
import { SPLIT_ANSI, wordWrapLines } from "@thi.ng/strings/word-wrap";
import {
DEFAULT_THEME
} from "./api.js";
const usage = (specs, opts = {}) => {
opts = {
lineWidth: 80,
paramWidth: 32,
showDefaults: true,
prefix: "",
suffix: "",
groups: ["flags", "main"],
...opts
};
const theme = isPlainObject(opts.color) ? { ...DEFAULT_THEME, ...opts.color } : opts.color ? DEFAULT_THEME : {};
const indent = repeat(" ", opts.paramWidth);
const format = (ids) => ids.map((id) => __argUsage(id, specs[id], opts, theme, indent));
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.optional === false && 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 padRight(opts.paramWidth)(params, lengthAnsi(params)) + __wrap(body, opts.lineWidth - opts.paramWidth).map((l, i) => i > 0 ? indent + l : l).join("\n");
};
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
) : "";
const __ansi = (x, col) => col != null ? `\x1B[${col}m${x}\x1B[0m` : x;
const __wrap = (str, width) => str ? wordWrapLines(str, {
width,
splitter: SPLIT_ANSI,
hard: false
}) : [];
export {
usage
};