UNPKG

@thi.ng/args

Version:

Declarative, functional & typechecked CLI argument/options parser, value coercions etc.

77 lines (76 loc) 2.94 kB
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 };