Skip to content

Commit 559dbc4

Browse files
lib: checks for help flag
1 parent 8eb76ea commit 559dbc4

4 files changed

Lines changed: 43 additions & 64 deletions

File tree

doc/api/util.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,7 @@ changes:
19801980
**Default:** `false`.
19811981
* `help` {string} General help text to display at the beginning of help output.
19821982
* `enableHelpPrinting` {boolean} When `true`, if any options have help text
1983-
configured, the help will be printed to stdout and the process will exit
1983+
configured and a `--help` entry was provided, the help will be printed to stdout and the process will exit
19841984
with code 0. **Default:** `false`.
19851985

19861986
* Returns: {Object} The parsed command line arguments:
@@ -2051,31 +2051,31 @@ const options = {
20512051
short: 'v',
20522052
help: 'Enable verbose output',
20532053
},
2054-
file: {
2055-
type: 'string',
2056-
short: 'f',
2057-
help: 'Input file path',
2054+
help: {
2055+
type: 'boolean',
2056+
short: 'h',
2057+
help: 'Prints command line options',
20582058
},
20592059
output: {
20602060
type: 'string',
20612061
help: 'Output directory',
20622062
},
20632063
};
20642064

2065-
// Get help text in result
2065+
// Get serialized help text in result
20662066
const result = parseArgs({
20672067
options,
20682068
help: 'My CLI Tool v1.0\n\nProcess files with various options.',
20692069
});
20702070

20712071
if (result.printUsage) {
2072-
console.log(result.printUsage.join('\n'));
2072+
console.log(result.printUsage);
20732073
// Prints:
20742074
// My CLI Tool v1.0
20752075
//
20762076
// Process files with various options.
20772077
// -v, --verbose Enable verbose output
2078-
// -f, --file <arg> Input file path
2078+
// -h, --help. Prints command line options
20792079
// --output <arg> Output directory
20802080
}
20812081

@@ -2097,10 +2097,10 @@ const options = {
20972097
short: 'v',
20982098
help: 'Enable verbose output',
20992099
},
2100-
file: {
2101-
type: 'string',
2102-
short: 'f',
2103-
help: 'Input file path',
2100+
help: {
2101+
type: 'boolean',
2102+
short: 'h',
2103+
help: 'Prints command line options',
21042104
},
21052105
output: {
21062106
type: 'string',
@@ -2115,13 +2115,13 @@ const result = parseArgs({
21152115
});
21162116

21172117
if (result.printUsage) {
2118-
console.log(result.printUsage.join('\n'));
2118+
console.log(result.printUsage);
21192119
// Prints:
21202120
// My CLI Tool v1.0
21212121
//
21222122
// Process files with various options.
21232123
// -v, --verbose Enable verbose output
2124-
// -f, --file <arg> Input file path
2124+
// -h, --help. Prints command line options
21252125
// --output <arg> Output directory
21262126
}
21272127

lib/internal/util/parse_args/parse_args.js

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ const {
2828
} = require('internal/validators');
2929

3030
const {
31-
findHelpValueForOption,
3231
findLongOptionForShort,
3332
isLoneLongOption,
3433
isLoneShortOption,
@@ -219,7 +218,6 @@ function argsToTokens(args, options) {
219218
// e.g. '-f'
220219
const shortOption = StringPrototypeCharAt(arg, 1);
221220
const longOption = findLongOptionForShort(shortOption, options);
222-
const helpValue = findHelpValueForOption(longOption, options);
223221
let value;
224222
let inlineValue;
225223
if (optionsGetOwn(options, longOption, 'type') === 'string' &&
@@ -231,7 +229,7 @@ function argsToTokens(args, options) {
231229
ArrayPrototypePush(
232230
tokens,
233231
{ kind: 'option', name: longOption, rawName: arg,
234-
index, value, inlineValue, ...(helpValue !== undefined && { help: helpValue }) });
232+
index, value, inlineValue });
235233
if (value != null) ++index;
236234
continue;
237235
}
@@ -263,19 +261,16 @@ function argsToTokens(args, options) {
263261
const shortOption = StringPrototypeCharAt(arg, 1);
264262
const longOption = findLongOptionForShort(shortOption, options);
265263
const value = StringPrototypeSlice(arg, 2);
266-
const helpValue = findHelpValueForOption(longOption, options);
267264
ArrayPrototypePush(
268265
tokens,
269266
{ kind: 'option', name: longOption, rawName: `-${shortOption}`,
270-
index, value, inlineValue: true,
271-
...(helpValue !== undefined && { help: helpValue }) });
267+
index, value, inlineValue: true });
272268
continue;
273269
}
274270

275271
if (isLoneLongOption(arg)) {
276272
// e.g. '--foo'
277273
const longOption = StringPrototypeSlice(arg, 2);
278-
const helpValue = findHelpValueForOption(longOption, options);
279274
let value;
280275
let inlineValue;
281276
if (optionsGetOwn(options, longOption, 'type') === 'string' &&
@@ -287,7 +282,7 @@ function argsToTokens(args, options) {
287282
ArrayPrototypePush(
288283
tokens,
289284
{ kind: 'option', name: longOption, rawName: arg,
290-
index, value, inlineValue, ...(helpValue !== undefined && { help: helpValue }) });
285+
index, value, inlineValue });
291286
if (value != null) ++index;
292287
continue;
293288
}
@@ -297,11 +292,10 @@ function argsToTokens(args, options) {
297292
const equalIndex = StringPrototypeIndexOf(arg, '=');
298293
const longOption = StringPrototypeSlice(arg, 2, equalIndex);
299294
const value = StringPrototypeSlice(arg, equalIndex + 1);
300-
const helpValue = findHelpValueForOption(longOption, options);
301295
ArrayPrototypePush(
302296
tokens,
303297
{ kind: 'option', name: longOption, rawName: `--${longOption}`,
304-
index, value, inlineValue: true, ...(helpValue !== undefined && { help: helpValue }) });
298+
index, value, inlineValue: true });
305299
continue;
306300
}
307301

@@ -455,24 +449,26 @@ const parseArgs = (config = kEmptyObject) => {
455449
});
456450

457451
// Phase 4: generate print usage for each option
458-
const printUsage = [];
452+
let printUsage = '';
459453
if (help) {
460-
ArrayPrototypePush(printUsage, help);
454+
printUsage += help;
461455
}
462456
ArrayPrototypeForEach(ObjectEntries(options), ({ 0: longOption, 1: optionConfig }) => {
463457
const helpTextForPrint = formatHelpTextForPrint(longOption, optionConfig);
464458

465459
if (helpTextForPrint) {
466-
ArrayPrototypePush(printUsage, helpTextForPrint);
460+
if (printUsage.length > 0) {
461+
printUsage += '\n';
462+
}
463+
printUsage += helpTextForPrint;
467464
}
468465
});
469466

470-
if (enableHelpPrinting) {
467+
const helpRequested = result.values.help;
468+
if (enableHelpPrinting && helpRequested) {
471469
const console = require('internal/console/global');
472470
if (printUsage.length > 0 || help) {
473-
ArrayPrototypeForEach(printUsage, (line) => {
474-
console.log(line);
475-
});
471+
console.log(printUsage);
476472
} else {
477473
console.log('No help text available.');
478474
}

lib/internal/util/parse_args/utils.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,6 @@ function findLongOptionForShort(shortOption, options) {
170170
return longOptionEntry?.[0] ?? shortOption;
171171
}
172172

173-
/**
174-
* Find the help value associated with a long option.
175-
* @param {string} longOption
176-
* @param {object} options
177-
* @returns {string|undefined} - the help value or undefined if not found
178-
*/
179-
function findHelpValueForOption(longOption, options) {
180-
validateObject(options, 'options');
181-
if (ObjectHasOwn(options, longOption)) {
182-
return objectGetOwn(options[longOption], 'help');
183-
}
184-
185-
return undefined;
186-
}
187-
188173
/**
189174
* Check if the given option includes a default value
190175
* and that option has not been set by the input args.
@@ -198,7 +183,6 @@ function useDefaultValueOption(longOption, optionConfig, values) {
198183
}
199184

200185
module.exports = {
201-
findHelpValueForOption,
202186
findLongOptionForShort,
203187
isLoneLongOption,
204188
isLoneShortOption,

test/parallel/test-parse-args.mjs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ test('help value for option must be a string', () => {
10751075
test('when help value for lone short option is added, then add help text', () => {
10761076
const args = ['-f', 'bar'];
10771077
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1078-
const printUsage = ['-f, --foo <arg> help text'];
1078+
const printUsage = '-f, --foo <arg> help text';
10791079
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [], printUsage };
10801080
const result = parseArgs({ args, options, allowPositionals: true });
10811081
assert.deepStrictEqual(result, expected);
@@ -1085,8 +1085,7 @@ test('when help value for short group option is added, then add help text', () =
10851085
const args = ['-fm', 'bar'];
10861086
const options = { foo: { type: 'boolean', short: 'f', help: 'help text' },
10871087
moo: { type: 'string', short: 'm', help: 'help text' } };
1088-
const printUsage = ['-f, --foo help text',
1089-
'-m, --moo <arg> help text'];
1088+
const printUsage = '-f, --foo help text\n-m, --moo <arg> help text';
10901089
const expected = { values: { __proto__: null, foo: true, moo: 'bar' }, positionals: [], printUsage };
10911090
const result = parseArgs({ args, options, allowPositionals: true });
10921091
assert.deepStrictEqual(result, expected);
@@ -1095,7 +1094,7 @@ test('when help value for short group option is added, then add help text', () =
10951094
test('when help value for short option and value is added, then add help text', () => {
10961095
const args = ['-fFILE'];
10971096
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1098-
const printUsage = ['-f, --foo <arg> help text'];
1097+
const printUsage = '-f, --foo <arg> help text';
10991098
const expected = { values: { __proto__: null, foo: 'FILE' }, positionals: [], printUsage };
11001099
const result = parseArgs({ args, options, allowPositionals: true });
11011100
assert.deepStrictEqual(result, expected);
@@ -1104,7 +1103,7 @@ test('when help value for short option and value is added, then add help text',
11041103
test('when help value for lone long option is added, then add help text', () => {
11051104
const args = ['--foo', 'bar'];
11061105
const options = { foo: { type: 'string', help: 'help text' } };
1107-
const printUsage = ['--foo <arg> help text'];
1106+
const printUsage = '--foo <arg> help text';
11081107
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [], printUsage };
11091108
const result = parseArgs({ args, options, allowPositionals: true });
11101109
assert.deepStrictEqual(result, expected);
@@ -1113,7 +1112,7 @@ test('when help value for lone long option is added, then add help text', () =>
11131112
test('when help value for lone long option and value is added, then add help text', () => {
11141113
const args = ['--foo=bar'];
11151114
const options = { foo: { type: 'string', help: 'help text' } };
1116-
const printUsage = ['--foo <arg> help text'];
1115+
const printUsage = '--foo <arg> help text';
11171116
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [], printUsage };
11181117
const result = parseArgs({ args, options, allowPositionals: true });
11191118
assert.deepStrictEqual(result, expected);
@@ -1133,7 +1132,7 @@ test('when help value is added, then add initial help text', () => {
11331132
const args = ['-f', 'bar'];
11341133
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
11351134
const help = 'Description for some awesome stuff:';
1136-
const printUsage = [help, '-f, --foo <arg> help text'];
1135+
const printUsage = help + '\n-f, --foo <arg> help text';
11371136
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [], printUsage };
11381137
const result = parseArgs({ args, options, help });
11391138
assert.deepStrictEqual(result, expected);
@@ -1178,19 +1177,20 @@ test('when enableHelpPrinting config is true, print all help text and exit', ()
11781177

11791178
try {
11801179
const args = [
1181-
'-a', 'val1', '--beta', '-c', 'val3', '--delta', 'val4', '-e',
1182-
'--foxtrot', 'val6', '--golf', '-h', 'val8', '--india', 'val9', '-j',
1180+
'-h', '-a', 'val1', '--beta', '-c', 'val3', '--delta', 'val4', '-e',
1181+
'--foxtrot', 'val6', '--golf', '--hotel', 'val8', '--india', 'val9', '-j',
11831182
];
11841183
const options = {
1184+
help: { type: 'boolean', short: 'h', help: 'Prints command line options' },
11851185
alpha: { type: 'string', short: 'a', help: 'Alpha option help' },
11861186
beta: { type: 'boolean', short: 'b', help: 'Beta option help' },
1187-
charlie: { type: 'string', short: 'c', help: 'Charlie option help' },
1187+
charlie: { type: 'string', short: 'c' },
11881188
delta: { type: 'string', help: 'Delta option help' },
11891189
echo: { type: 'boolean', short: 'e', help: 'Echo option help' },
11901190
foxtrot: { type: 'string', help: 'Foxtrot option help' },
11911191
golf: { type: 'boolean', help: 'Golf option help' },
1192-
hotel: { type: 'string', short: 'h', help: 'Hotel option help' },
1193-
india: { type: 'string', help: 'India option help' },
1192+
hotel: { type: 'string', help: 'Hotel option help' },
1193+
india: { type: 'string' },
11941194
juliet: { type: 'boolean', short: 'j', help: 'Juliet option help' },
11951195
looooooooooooooongHelpText: {
11961196
type: 'string',
@@ -1207,15 +1207,14 @@ test('when enableHelpPrinting config is true, print all help text and exit', ()
12071207

12081208
const expectedOutput =
12091209
'Description for some awesome stuff:\n' +
1210+
'-h, --help Prints command line options\n' +
12101211
'-a, --alpha <arg> Alpha option help\n' +
12111212
'-b, --beta Beta option help\n' +
1212-
'-c, --charlie <arg> Charlie option help\n' +
12131213
'--delta <arg> Delta option help\n' +
12141214
'-e, --echo Echo option help\n' +
12151215
'--foxtrot <arg> Foxtrot option help\n' +
12161216
'--golf Golf option help\n' +
1217-
'-h, --hotel <arg> Hotel option help\n' +
1218-
'--india <arg> India option help\n' +
1217+
'--hotel <arg> Hotel option help\n' +
12191218
'-j, --juliet Juliet option help\n' +
12201219
'-L, --looooooooooooooongHelpText <arg>\n' +
12211220
' Very long option help text for demonstration purposes\n';
@@ -1228,8 +1227,8 @@ test('when enableHelpPrinting config is true, but no help text is available', ()
12281227
const { getOutput, getExitCode, restore } = setupConsoleAndExit();
12291228

12301229
try {
1231-
const args = ['-a', 'val1'];
1232-
const options = { alpha: { type: 'string', short: 'a' } };
1230+
const args = ['-a', 'val1', '--help'];
1231+
const options = { alpha: { type: 'string', short: 'a' }, help: { type: 'boolean' } };
12331232

12341233
parseArgs({ args, options, enableHelpPrinting: true });
12351234
} finally {

0 commit comments

Comments
 (0)