diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2024-05-29 16:54:43 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2024-05-29 19:40:03 -0300 |
commit | e07a89b56b65f96295f421141f5b02e360d2e7d0 (patch) | |
tree | da751f7eb08282a488eb47cae7fd34cf65fca6b8 /src/util | |
parent | 323cb695015b21ba55513f9e615ecf2a95d7ca80 (diff) |
upd8, util, cli: factor out help internals; no default build mode
Sorry these changes are packed together in one commit! We have no excuse. :+1:
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/cli.js | 73 | ||||
-rw-r--r-- | src/util/sugar.js | 21 |
2 files changed, 94 insertions, 0 deletions
diff --git a/src/util/cli.js b/src/util/cli.js index ce513f08..72979d3f 100644 --- a/src/util/cli.js +++ b/src/util/cli.js @@ -201,6 +201,79 @@ export async function parseOptions(options, optionDescriptorMap) { return result; } +// Takes precisely the same sort of structure as `parseOptions` above, +// and displays associated help messages. Radical! +// +// 'indentWrap' should be the function from '#sugar', with its wrap option +// already bound. +// +// 'sort' should take care of sorting a list of {name, descriptor} entries. +export function showHelpForOptions({ + heading, + options, + indentWrap, + sort = entries => entries, +}) { + if (heading) { + console.log(colors.bright(heading)); + } + + const sortedOptions = + sort( + Object.entries(options) + .map(([name, descriptor]) => ({name, descriptor}))); + + if (!sortedOptions.length) { + console.log(`(No options available)`) + } + + let justInsertedPaddingLine = false; + + for (const {name, descriptor} of sortedOptions) { + if (descriptor.alias) { + continue; + } + + const aliases = + Object.entries(options) + .filter(([_name, {alias}]) => alias === name) + .map(([name]) => name); + + let wrappedHelp, wrappedHelpLines = 0; + if (descriptor.help) { + wrappedHelp = indentWrap(descriptor.help, {spaces: 4}); + wrappedHelpLines = wrappedHelp.split('\n').length; + } + + if (wrappedHelpLines > 0 && !justInsertedPaddingLine) { + console.log(''); + } + + console.log(colors.bright(` --` + name) + + (aliases.length + ? ` (or: ${aliases.map(alias => colors.bright(`--` + alias)).join(', ')})` + : '') + + (descriptor.help + ? '' + : colors.dim(' (no help provided)'))); + + if (wrappedHelp) { + console.log(wrappedHelp); + } + + if (wrappedHelpLines > 1) { + console.log(''); + justInsertedPaddingLine = true; + } else { + justInsertedPaddingLine = false; + } + } + + if (!justInsertedPaddingLine) { + console.log(``); + } +} + export const handleDashless = Symbol(); export const handleUnknown = Symbol(); diff --git a/src/util/sugar.js b/src/util/sugar.js index e060f458..d0b7ffab 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -315,6 +315,27 @@ export function cutStart(text, length = 40) { } } +// Wrapper function around wrap(), ha, ha - this requires the Node module +// 'node-wrap'. +export function indentWrap(str, { + wrap, + spaces = 0, + width = 60, + bullet = false, +}) { + const wrapped = + wrap(str, { + width: width - spaces, + indent: ' '.repeat(spaces), + }); + + if (bullet) { + return wrapped.trimStart(); + } else { + return wrapped; + } +} + // Annotates {index, length} results from another iterator with contextual // details, including: // |