@optique/core 0.8.9 → 0.8.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constructs.cjs +72 -12
- package/dist/constructs.js +74 -14
- package/dist/doc.d.cts +6 -0
- package/dist/doc.d.ts +6 -0
- package/dist/facade.cjs +8 -6
- package/dist/facade.js +8 -6
- package/dist/parser.cjs +2 -1
- package/dist/parser.js +2 -1
- package/dist/primitives.cjs +1 -0
- package/dist/primitives.js +1 -0
- package/dist/suggestion.cjs +1 -0
- package/dist/suggestion.js +1 -1
- package/package.json +1 -1
package/dist/constructs.cjs
CHANGED
|
@@ -4,6 +4,57 @@ const require_suggestion = require('./suggestion.cjs');
|
|
|
4
4
|
|
|
5
5
|
//#region src/constructs.ts
|
|
6
6
|
/**
|
|
7
|
+
* Collects option names and command names that are valid at the current
|
|
8
|
+
* parse position by walking the usage tree. Only "leading" candidates
|
|
9
|
+
* (those reachable before a required positional argument) are collected.
|
|
10
|
+
*/
|
|
11
|
+
function collectLeadingCandidates(terms, optionNames, commandNames) {
|
|
12
|
+
if (!terms || !Array.isArray(terms)) return true;
|
|
13
|
+
for (const term of terms) {
|
|
14
|
+
if (term.type === "option") {
|
|
15
|
+
for (const name of term.names) optionNames.add(name);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (term.type === "command") {
|
|
19
|
+
commandNames.add(term.name);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (term.type === "argument") return false;
|
|
23
|
+
if (term.type === "optional") {
|
|
24
|
+
collectLeadingCandidates(term.terms, optionNames, commandNames);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (term.type === "multiple") {
|
|
28
|
+
collectLeadingCandidates(term.terms, optionNames, commandNames);
|
|
29
|
+
if (term.min === 0) continue;
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (term.type === "exclusive") {
|
|
33
|
+
let allAlternativesSkippable = true;
|
|
34
|
+
for (const exclusiveUsage of term.terms) {
|
|
35
|
+
const alternativeSkippable = collectLeadingCandidates(exclusiveUsage, optionNames, commandNames);
|
|
36
|
+
allAlternativesSkippable = allAlternativesSkippable && alternativeSkippable;
|
|
37
|
+
}
|
|
38
|
+
if (allAlternativesSkippable) continue;
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput, parsers, customFormatter) {
|
|
45
|
+
const options = /* @__PURE__ */ new Set();
|
|
46
|
+
const commands = /* @__PURE__ */ new Set();
|
|
47
|
+
for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
|
|
48
|
+
const candidates = new Set([...options, ...commands]);
|
|
49
|
+
const suggestions = require_suggestion.findSimilar(invalidInput, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
|
|
50
|
+
const suggestionMsg = customFormatter ? customFormatter(suggestions) : require_suggestion.createSuggestionMessage(suggestions);
|
|
51
|
+
return suggestionMsg.length > 0 ? [
|
|
52
|
+
...baseError,
|
|
53
|
+
require_message.text("\n\n"),
|
|
54
|
+
...suggestionMsg
|
|
55
|
+
] : baseError;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
7
58
|
* Checks if the given token is an option name that requires a value
|
|
8
59
|
* (i.e., has a metavar) within the given usage terms.
|
|
9
60
|
* @param usage The usage terms to search through.
|
|
@@ -168,16 +219,6 @@ function getNoMatchError(options, noMatchContext) {
|
|
|
168
219
|
return customNoMatch ? typeof customNoMatch === "function" ? customNoMatch(noMatchContext) : customNoMatch : generateNoMatchError(noMatchContext);
|
|
169
220
|
}
|
|
170
221
|
/**
|
|
171
|
-
* Creates default error for parse() method when buffer is not empty.
|
|
172
|
-
* Shared by or() and longestMatch().
|
|
173
|
-
* @internal
|
|
174
|
-
*/
|
|
175
|
-
function createUnexpectedInputError(token, usage, options) {
|
|
176
|
-
const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
|
|
177
|
-
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
178
|
-
return require_suggestion.createErrorWithSuggestions(defaultMsg, token, usage, "both", options?.errors?.suggestions);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
222
|
* @since 0.5.0
|
|
182
223
|
*/
|
|
183
224
|
function or(...args) {
|
|
@@ -204,7 +245,12 @@ function or(...args) {
|
|
|
204
245
|
parse(context) {
|
|
205
246
|
let error = {
|
|
206
247
|
consumed: 0,
|
|
207
|
-
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) :
|
|
248
|
+
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
|
|
249
|
+
const token = context.buffer[0];
|
|
250
|
+
const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
|
|
251
|
+
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
252
|
+
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
253
|
+
})()
|
|
208
254
|
};
|
|
209
255
|
const orderedParsers = parsers.map((p, i) => [p, i]);
|
|
210
256
|
orderedParsers.sort(([_, a], [__, b]) => context.state?.[0] === a ? -1 : context.state?.[0] === b ? 1 : a - b);
|
|
@@ -238,7 +284,9 @@ function or(...args) {
|
|
|
238
284
|
},
|
|
239
285
|
suggest: createExclusiveSuggest(parsers),
|
|
240
286
|
getDocFragments(state, _defaultValue) {
|
|
287
|
+
let brief;
|
|
241
288
|
let description;
|
|
289
|
+
let footer;
|
|
242
290
|
let fragments;
|
|
243
291
|
if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }, void 0).fragments);
|
|
244
292
|
else {
|
|
@@ -248,7 +296,9 @@ function or(...args) {
|
|
|
248
296
|
state: parserResult.next.state
|
|
249
297
|
} : { kind: "unavailable" };
|
|
250
298
|
const docFragments = parsers[index].getDocFragments(innerState, void 0);
|
|
299
|
+
brief = docFragments.brief;
|
|
251
300
|
description = docFragments.description;
|
|
301
|
+
footer = docFragments.footer;
|
|
252
302
|
fragments = docFragments.fragments;
|
|
253
303
|
}
|
|
254
304
|
const entries = fragments.filter((f) => f.type === "entry");
|
|
@@ -259,7 +309,9 @@ function or(...args) {
|
|
|
259
309
|
else sections.push(fragment);
|
|
260
310
|
}
|
|
261
311
|
return {
|
|
312
|
+
brief,
|
|
262
313
|
description,
|
|
314
|
+
footer,
|
|
263
315
|
fragments: [...sections.map((s) => ({
|
|
264
316
|
...s,
|
|
265
317
|
type: "section"
|
|
@@ -299,7 +351,12 @@ function longestMatch(...args) {
|
|
|
299
351
|
let bestMatch = null;
|
|
300
352
|
let error = {
|
|
301
353
|
consumed: 0,
|
|
302
|
-
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) :
|
|
354
|
+
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
|
|
355
|
+
const token = context.buffer[0];
|
|
356
|
+
const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
|
|
357
|
+
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
358
|
+
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
359
|
+
})()
|
|
303
360
|
};
|
|
304
361
|
for (let i = 0; i < parsers.length; i++) {
|
|
305
362
|
const parser = parsers[i];
|
|
@@ -333,6 +390,7 @@ function longestMatch(...args) {
|
|
|
333
390
|
},
|
|
334
391
|
suggest: createExclusiveSuggest(parsers),
|
|
335
392
|
getDocFragments(state, _defaultValue) {
|
|
393
|
+
let brief;
|
|
336
394
|
let description;
|
|
337
395
|
let footer;
|
|
338
396
|
let fragments;
|
|
@@ -344,12 +402,14 @@ function longestMatch(...args) {
|
|
|
344
402
|
kind: "available",
|
|
345
403
|
state: result.next.state
|
|
346
404
|
});
|
|
405
|
+
brief = docResult.brief;
|
|
347
406
|
description = docResult.description;
|
|
348
407
|
footer = docResult.footer;
|
|
349
408
|
fragments = docResult.fragments;
|
|
350
409
|
} else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
351
410
|
}
|
|
352
411
|
return {
|
|
412
|
+
brief,
|
|
353
413
|
description,
|
|
354
414
|
fragments,
|
|
355
415
|
footer
|
package/dist/constructs.js
CHANGED
|
@@ -1,9 +1,60 @@
|
|
|
1
|
-
import { message, optionName, values } from "./message.js";
|
|
1
|
+
import { message, optionName, text, values } from "./message.js";
|
|
2
2
|
import { extractArgumentMetavars, extractCommandNames, extractOptionNames } from "./usage.js";
|
|
3
|
-
import { createErrorWithSuggestions, deduplicateSuggestions } from "./suggestion.js";
|
|
3
|
+
import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar } from "./suggestion.js";
|
|
4
4
|
|
|
5
5
|
//#region src/constructs.ts
|
|
6
6
|
/**
|
|
7
|
+
* Collects option names and command names that are valid at the current
|
|
8
|
+
* parse position by walking the usage tree. Only "leading" candidates
|
|
9
|
+
* (those reachable before a required positional argument) are collected.
|
|
10
|
+
*/
|
|
11
|
+
function collectLeadingCandidates(terms, optionNames, commandNames) {
|
|
12
|
+
if (!terms || !Array.isArray(terms)) return true;
|
|
13
|
+
for (const term of terms) {
|
|
14
|
+
if (term.type === "option") {
|
|
15
|
+
for (const name of term.names) optionNames.add(name);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (term.type === "command") {
|
|
19
|
+
commandNames.add(term.name);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (term.type === "argument") return false;
|
|
23
|
+
if (term.type === "optional") {
|
|
24
|
+
collectLeadingCandidates(term.terms, optionNames, commandNames);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (term.type === "multiple") {
|
|
28
|
+
collectLeadingCandidates(term.terms, optionNames, commandNames);
|
|
29
|
+
if (term.min === 0) continue;
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (term.type === "exclusive") {
|
|
33
|
+
let allAlternativesSkippable = true;
|
|
34
|
+
for (const exclusiveUsage of term.terms) {
|
|
35
|
+
const alternativeSkippable = collectLeadingCandidates(exclusiveUsage, optionNames, commandNames);
|
|
36
|
+
allAlternativesSkippable = allAlternativesSkippable && alternativeSkippable;
|
|
37
|
+
}
|
|
38
|
+
if (allAlternativesSkippable) continue;
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput, parsers, customFormatter) {
|
|
45
|
+
const options = /* @__PURE__ */ new Set();
|
|
46
|
+
const commands = /* @__PURE__ */ new Set();
|
|
47
|
+
for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
|
|
48
|
+
const candidates = new Set([...options, ...commands]);
|
|
49
|
+
const suggestions = findSimilar(invalidInput, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
|
|
50
|
+
const suggestionMsg = customFormatter ? customFormatter(suggestions) : createSuggestionMessage(suggestions);
|
|
51
|
+
return suggestionMsg.length > 0 ? [
|
|
52
|
+
...baseError,
|
|
53
|
+
text("\n\n"),
|
|
54
|
+
...suggestionMsg
|
|
55
|
+
] : baseError;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
7
58
|
* Checks if the given token is an option name that requires a value
|
|
8
59
|
* (i.e., has a metavar) within the given usage terms.
|
|
9
60
|
* @param usage The usage terms to search through.
|
|
@@ -168,16 +219,6 @@ function getNoMatchError(options, noMatchContext) {
|
|
|
168
219
|
return customNoMatch ? typeof customNoMatch === "function" ? customNoMatch(noMatchContext) : customNoMatch : generateNoMatchError(noMatchContext);
|
|
169
220
|
}
|
|
170
221
|
/**
|
|
171
|
-
* Creates default error for parse() method when buffer is not empty.
|
|
172
|
-
* Shared by or() and longestMatch().
|
|
173
|
-
* @internal
|
|
174
|
-
*/
|
|
175
|
-
function createUnexpectedInputError(token, usage, options) {
|
|
176
|
-
const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
|
|
177
|
-
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
178
|
-
return createErrorWithSuggestions(defaultMsg, token, usage, "both", options?.errors?.suggestions);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
222
|
* @since 0.5.0
|
|
182
223
|
*/
|
|
183
224
|
function or(...args) {
|
|
@@ -204,7 +245,12 @@ function or(...args) {
|
|
|
204
245
|
parse(context) {
|
|
205
246
|
let error = {
|
|
206
247
|
consumed: 0,
|
|
207
|
-
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) :
|
|
248
|
+
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
|
|
249
|
+
const token = context.buffer[0];
|
|
250
|
+
const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
|
|
251
|
+
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
252
|
+
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
253
|
+
})()
|
|
208
254
|
};
|
|
209
255
|
const orderedParsers = parsers.map((p, i) => [p, i]);
|
|
210
256
|
orderedParsers.sort(([_, a], [__, b]) => context.state?.[0] === a ? -1 : context.state?.[0] === b ? 1 : a - b);
|
|
@@ -238,7 +284,9 @@ function or(...args) {
|
|
|
238
284
|
},
|
|
239
285
|
suggest: createExclusiveSuggest(parsers),
|
|
240
286
|
getDocFragments(state, _defaultValue) {
|
|
287
|
+
let brief;
|
|
241
288
|
let description;
|
|
289
|
+
let footer;
|
|
242
290
|
let fragments;
|
|
243
291
|
if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }, void 0).fragments);
|
|
244
292
|
else {
|
|
@@ -248,7 +296,9 @@ function or(...args) {
|
|
|
248
296
|
state: parserResult.next.state
|
|
249
297
|
} : { kind: "unavailable" };
|
|
250
298
|
const docFragments = parsers[index].getDocFragments(innerState, void 0);
|
|
299
|
+
brief = docFragments.brief;
|
|
251
300
|
description = docFragments.description;
|
|
301
|
+
footer = docFragments.footer;
|
|
252
302
|
fragments = docFragments.fragments;
|
|
253
303
|
}
|
|
254
304
|
const entries = fragments.filter((f) => f.type === "entry");
|
|
@@ -259,7 +309,9 @@ function or(...args) {
|
|
|
259
309
|
else sections.push(fragment);
|
|
260
310
|
}
|
|
261
311
|
return {
|
|
312
|
+
brief,
|
|
262
313
|
description,
|
|
314
|
+
footer,
|
|
263
315
|
fragments: [...sections.map((s) => ({
|
|
264
316
|
...s,
|
|
265
317
|
type: "section"
|
|
@@ -299,7 +351,12 @@ function longestMatch(...args) {
|
|
|
299
351
|
let bestMatch = null;
|
|
300
352
|
let error = {
|
|
301
353
|
consumed: 0,
|
|
302
|
-
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) :
|
|
354
|
+
error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
|
|
355
|
+
const token = context.buffer[0];
|
|
356
|
+
const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
|
|
357
|
+
if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
|
|
358
|
+
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
359
|
+
})()
|
|
303
360
|
};
|
|
304
361
|
for (let i = 0; i < parsers.length; i++) {
|
|
305
362
|
const parser = parsers[i];
|
|
@@ -333,6 +390,7 @@ function longestMatch(...args) {
|
|
|
333
390
|
},
|
|
334
391
|
suggest: createExclusiveSuggest(parsers),
|
|
335
392
|
getDocFragments(state, _defaultValue) {
|
|
393
|
+
let brief;
|
|
336
394
|
let description;
|
|
337
395
|
let footer;
|
|
338
396
|
let fragments;
|
|
@@ -344,12 +402,14 @@ function longestMatch(...args) {
|
|
|
344
402
|
kind: "available",
|
|
345
403
|
state: result.next.state
|
|
346
404
|
});
|
|
405
|
+
brief = docResult.brief;
|
|
347
406
|
description = docResult.description;
|
|
348
407
|
footer = docResult.footer;
|
|
349
408
|
fragments = docResult.fragments;
|
|
350
409
|
} else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
351
410
|
}
|
|
352
411
|
return {
|
|
412
|
+
brief,
|
|
353
413
|
description,
|
|
354
414
|
fragments,
|
|
355
415
|
footer
|
package/dist/doc.d.cts
CHANGED
|
@@ -60,6 +60,12 @@ type DocFragment = {
|
|
|
60
60
|
* a final document page.
|
|
61
61
|
*/
|
|
62
62
|
interface DocFragments {
|
|
63
|
+
/**
|
|
64
|
+
* An optional brief that provides a short summary for the collection
|
|
65
|
+
* of fragments.
|
|
66
|
+
* @since 0.7.12
|
|
67
|
+
*/
|
|
68
|
+
readonly brief?: Message;
|
|
63
69
|
/**
|
|
64
70
|
* An optional description that applies to the entire collection of fragments.
|
|
65
71
|
*/
|
package/dist/doc.d.ts
CHANGED
|
@@ -60,6 +60,12 @@ type DocFragment = {
|
|
|
60
60
|
* a final document page.
|
|
61
61
|
*/
|
|
62
62
|
interface DocFragments {
|
|
63
|
+
/**
|
|
64
|
+
* An optional brief that provides a short summary for the collection
|
|
65
|
+
* of fragments.
|
|
66
|
+
* @since 0.7.12
|
|
67
|
+
*/
|
|
68
|
+
readonly brief?: Message;
|
|
63
69
|
/**
|
|
64
70
|
* An optional description that applies to the entire collection of fragments.
|
|
65
71
|
*/
|
package/dist/facade.cjs
CHANGED
|
@@ -470,9 +470,9 @@ function run(parser, programName, args, options = {}) {
|
|
|
470
470
|
} else {
|
|
471
471
|
const singularMatchExact = completionName === "singular" || completionName === "both" ? arg === "--completion" : false;
|
|
472
472
|
const pluralMatchExact = completionName === "plural" || completionName === "both" ? arg === "--completions" : false;
|
|
473
|
-
if (
|
|
474
|
-
const shell = args[i + 1];
|
|
475
|
-
const completionArgs = args.slice(i + 2);
|
|
473
|
+
if (singularMatchExact || pluralMatchExact) {
|
|
474
|
+
const shell = i + 1 < args.length ? args[i + 1] : "";
|
|
475
|
+
const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
|
|
476
476
|
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName);
|
|
477
477
|
}
|
|
478
478
|
}
|
|
@@ -561,11 +561,13 @@ function run(parser, programName, args, options = {}) {
|
|
|
561
561
|
const doc = require_parser.getDocPage(helpGeneratorParser, classified.commands);
|
|
562
562
|
if (doc != null) {
|
|
563
563
|
const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
|
|
564
|
+
const isSubcommandHelp = classified.commands.length > 0;
|
|
565
|
+
const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
|
|
564
566
|
const augmentedDoc = {
|
|
565
567
|
...doc,
|
|
566
|
-
brief:
|
|
567
|
-
description:
|
|
568
|
-
footer:
|
|
568
|
+
brief: shouldOverride ? brief ?? doc.brief : doc.brief ?? brief,
|
|
569
|
+
description: shouldOverride ? description ?? doc.description : doc.description ?? description,
|
|
570
|
+
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
569
571
|
};
|
|
570
572
|
stdout(require_doc.formatDocPage(programName, augmentedDoc, {
|
|
571
573
|
colors,
|
package/dist/facade.js
CHANGED
|
@@ -470,9 +470,9 @@ function run(parser, programName, args, options = {}) {
|
|
|
470
470
|
} else {
|
|
471
471
|
const singularMatchExact = completionName === "singular" || completionName === "both" ? arg === "--completion" : false;
|
|
472
472
|
const pluralMatchExact = completionName === "plural" || completionName === "both" ? arg === "--completions" : false;
|
|
473
|
-
if (
|
|
474
|
-
const shell = args[i + 1];
|
|
475
|
-
const completionArgs = args.slice(i + 2);
|
|
473
|
+
if (singularMatchExact || pluralMatchExact) {
|
|
474
|
+
const shell = i + 1 < args.length ? args[i + 1] : "";
|
|
475
|
+
const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
|
|
476
476
|
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName);
|
|
477
477
|
}
|
|
478
478
|
}
|
|
@@ -561,11 +561,13 @@ function run(parser, programName, args, options = {}) {
|
|
|
561
561
|
const doc = getDocPage(helpGeneratorParser, classified.commands);
|
|
562
562
|
if (doc != null) {
|
|
563
563
|
const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
|
|
564
|
+
const isSubcommandHelp = classified.commands.length > 0;
|
|
565
|
+
const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
|
|
564
566
|
const augmentedDoc = {
|
|
565
567
|
...doc,
|
|
566
|
-
brief:
|
|
567
|
-
description:
|
|
568
|
-
footer:
|
|
568
|
+
brief: shouldOverride ? brief ?? doc.brief : doc.brief ?? brief,
|
|
569
|
+
description: shouldOverride ? description ?? doc.description : doc.description ?? description,
|
|
570
|
+
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
569
571
|
};
|
|
570
572
|
stdout(formatDocPage(programName, augmentedDoc, {
|
|
571
573
|
colors,
|
package/dist/parser.cjs
CHANGED
|
@@ -159,7 +159,7 @@ function getDocPage(parser, args = []) {
|
|
|
159
159
|
if (!result.success) break;
|
|
160
160
|
context = result.next;
|
|
161
161
|
} while (context.buffer.length > 0);
|
|
162
|
-
const { description, fragments, footer } = parser.getDocFragments({
|
|
162
|
+
const { brief, description, fragments, footer } = parser.getDocFragments({
|
|
163
163
|
kind: "available",
|
|
164
164
|
state: context.state
|
|
165
165
|
}, void 0);
|
|
@@ -185,6 +185,7 @@ function getDocPage(parser, args = []) {
|
|
|
185
185
|
return {
|
|
186
186
|
usage,
|
|
187
187
|
sections,
|
|
188
|
+
...brief != null && { brief },
|
|
188
189
|
...description != null && { description },
|
|
189
190
|
...footer != null && { footer }
|
|
190
191
|
};
|
package/dist/parser.js
CHANGED
|
@@ -159,7 +159,7 @@ function getDocPage(parser, args = []) {
|
|
|
159
159
|
if (!result.success) break;
|
|
160
160
|
context = result.next;
|
|
161
161
|
} while (context.buffer.length > 0);
|
|
162
|
-
const { description, fragments, footer } = parser.getDocFragments({
|
|
162
|
+
const { brief, description, fragments, footer } = parser.getDocFragments({
|
|
163
163
|
kind: "available",
|
|
164
164
|
state: context.state
|
|
165
165
|
}, void 0);
|
|
@@ -185,6 +185,7 @@ function getDocPage(parser, args = []) {
|
|
|
185
185
|
return {
|
|
186
186
|
usage,
|
|
187
187
|
sections,
|
|
188
|
+
...brief != null && { brief },
|
|
188
189
|
...description != null && { description },
|
|
189
190
|
...footer != null && { footer }
|
|
190
191
|
};
|
package/dist/primitives.cjs
CHANGED
|
@@ -725,6 +725,7 @@ function command(name, parser, options = {}) {
|
|
|
725
725
|
const innerFragments = parser.getDocFragments(innerState, defaultValue);
|
|
726
726
|
return {
|
|
727
727
|
...innerFragments,
|
|
728
|
+
brief: innerFragments.brief ?? options.brief,
|
|
728
729
|
description: innerFragments.description ?? options.description,
|
|
729
730
|
footer: innerFragments.footer ?? options.footer
|
|
730
731
|
};
|
package/dist/primitives.js
CHANGED
|
@@ -725,6 +725,7 @@ function command(name, parser, options = {}) {
|
|
|
725
725
|
const innerFragments = parser.getDocFragments(innerState, defaultValue);
|
|
726
726
|
return {
|
|
727
727
|
...innerFragments,
|
|
728
|
+
brief: innerFragments.brief ?? options.brief,
|
|
728
729
|
description: innerFragments.description ?? options.description,
|
|
729
730
|
footer: innerFragments.footer ?? options.footer
|
|
730
731
|
};
|
package/dist/suggestion.cjs
CHANGED
|
@@ -232,5 +232,6 @@ function deduplicateSuggestions(suggestions) {
|
|
|
232
232
|
//#endregion
|
|
233
233
|
exports.DEFAULT_FIND_SIMILAR_OPTIONS = DEFAULT_FIND_SIMILAR_OPTIONS;
|
|
234
234
|
exports.createErrorWithSuggestions = createErrorWithSuggestions;
|
|
235
|
+
exports.createSuggestionMessage = createSuggestionMessage;
|
|
235
236
|
exports.deduplicateSuggestions = deduplicateSuggestions;
|
|
236
237
|
exports.findSimilar = findSimilar;
|
package/dist/suggestion.js
CHANGED
|
@@ -230,4 +230,4 @@ function deduplicateSuggestions(suggestions) {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
//#endregion
|
|
233
|
-
export { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, deduplicateSuggestions, findSimilar };
|
|
233
|
+
export { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar };
|