UNPKG

@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
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 };