Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up description parsing #256

Merged
merged 5 commits into from Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions readme.md
Expand Up @@ -142,7 +142,7 @@ flags: {

##### description

Type: `string | boolean`\
Type: `string | false`\
Default: The package.json `"description"` property

Description to show above the help text.
Expand All @@ -151,14 +151,16 @@ Set it to `false` to disable it altogether.

##### help

Type: `string | boolean`
Type: `string | false`

The help text you want shown.

The input is reindented and starting/ending newlines are trimmed which means you can use a [template literal](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings) without having to care about using the correct amount of indent.

The description will be shown above your help text automatically.

Set it to `false` to disable it altogether.

##### version

Type: `string`\
Expand Down
20 changes: 11 additions & 9 deletions source/index.js
Expand Up @@ -3,13 +3,11 @@ import parseArguments from 'yargs-parser';
import camelCaseKeys from 'camelcase-keys';
import {trimNewlines} from 'trim-newlines';
import redent from 'redent';
import normalizePackageData from 'normalize-package-data';
import {buildOptions} from './options.js';
import {buildParserOptions} from './parser.js';
import {validate, checkUnknownFlags, checkMissingRequiredFlags} from './validate.js';

const buildResult = (options, parserOptions) => {
const {pkg: package_} = options;
const buildResult = ({pkg: packageJson, ...options}, parserOptions) => {
const argv = parseArguments(options.argv, parserOptions);
let help = '';

Expand All @@ -23,16 +21,20 @@ const buildResult = (options, parserOptions) => {
help = `\n${help}`;
}

normalizePackageData(package_);
if (options.description !== false) {
let {description} = options;

let description = options.description ?? package_.description;
if (description) {
description = help ? redent(`\n${description}\n`, options.helpIndent) : `\n${description}`;
help = `${description}${help}`;
}
}

description &&= help ? redent(`\n${description}\n`, options.helpIndent) : `\n${description}`;
help = `${description || ''}${help}\n`;
help += '\n';

const showHelp = code => {
console.log(help);
process.exit(typeof code === 'number' ? code : 2);
process.exit(typeof code === 'number' ? code : 2); // Default to code 2 for incorrect usage (#47)
};

const showVersion = () => {
Expand Down Expand Up @@ -76,7 +78,7 @@ const buildResult = (options, parserOptions) => {
input,
flags,
unnormalizedFlags,
pkg: package_,
pkg: packageJson,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on renaming cli.pkg to package or packageJson?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be package as it's a reserved keyword, so it cannot be destructured. But we could indeed make it packageJson.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hadn't considered the destructuring part, fair point. I'm ambivalent on the change, but feel free to add it to #233 if you'd like to change it (or just go for it). The consistency (and not having to rename variables) would be nice though.

help,
showHelp,
showVersion,
Expand Down
14 changes: 10 additions & 4 deletions source/options.js
Expand Up @@ -2,6 +2,7 @@ import process from 'node:process';
import {dirname} from 'node:path';
import {fileURLToPath} from 'node:url';
import {readPackageUpSync} from 'read-package-up';
import normalizePackageData from 'normalize-package-data';
import {decamelizeFlagKey, joinFlagKeys} from './utils.js';

const validateOptions = options => {
Expand Down Expand Up @@ -63,26 +64,31 @@ export const buildOptions = (helpText, options) => {
throw new TypeError('The `importMeta` option is required. Its value must be `import.meta`.');
}

const foundPackage = readPackageUpSync({
const foundPackage = options.pkg ?? readPackageUpSync({
cwd: dirname(fileURLToPath(options.importMeta.url)),
normalize: false,
});
})?.packageJson;

// eslint-disable-next-line unicorn/prevent-abbreviations
const pkg = foundPackage ?? {};
normalizePackageData(pkg);

const parsedOptions = {
pkg: foundPackage ? foundPackage.packageJson : {},
argv: process.argv.slice(2),
flags: {},
inferType: false,
input: 'string',
description: pkg.description ?? false,
help: helpText,
version: foundPackage?.packageJson.version || 'No version found',
version: pkg.version || 'No version found',
autoHelp: true,
autoVersion: true,
booleanDefault: false,
allowUnknownFlags: true,
allowParentFlags: true,
helpIndent: 2,
...options,
pkg,
};

validateOptions(parsedOptions);
Expand Down
17 changes: 15 additions & 2 deletions test/options/help.js
Expand Up @@ -25,12 +25,25 @@ test('support help shortcut', verifyHelp, {
unicorn
cat
`],
expected: indentString('\nCLI app helper\n\nunicorn\ncat\n', 2),
expected: indentString(stripIndent`

CLI app helper

unicorn
cat
`, 2),
});

test('spawn cli and show help screen', verifyCli, {
args: '--help',
expected: indentString('\nCustom description\n\nUsage\n foo <input>\n\n', 2),
expected: indentString(stripIndent`

Custom description

Usage
foo <input>

`, 2),
});

test('spawn cli and disabled autoHelp', verifyCli, {
Expand Down