@optique/core 1.4.0-dev.2683 → 1.4.0-dev.2709
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 +43 -16
- package/dist/constructs.js +43 -16
- package/dist/doc.cjs +11 -3
- package/dist/doc.js +12 -4
- package/dist/internal/empty-input.cjs +368 -0
- package/dist/internal/empty-input.js +355 -0
- package/dist/internal/usage.cjs +235 -0
- package/dist/internal/usage.d.cts +42 -0
- package/dist/internal/usage.d.ts +42 -0
- package/dist/internal/usage.js +233 -0
- package/dist/message.cjs +32 -5
- package/dist/message.js +33 -6
- package/dist/modifiers.cjs +43 -6
- package/dist/modifiers.js +43 -6
- package/dist/primitives.cjs +19 -4
- package/dist/primitives.js +19 -4
- package/dist/terminal-internal.cjs +4 -1
- package/dist/terminal-internal.d.cts +5 -0
- package/dist/terminal-internal.d.ts +5 -0
- package/dist/terminal-internal.js +4 -1
- package/dist/terminal-separators.cjs +13 -0
- package/dist/terminal-separators.js +12 -0
- package/dist/terminal.cjs +4 -1
- package/dist/terminal.js +5 -1
- package/dist/text-layout.cjs +14 -1
- package/dist/text-layout.d.cts +8 -1
- package/dist/text-layout.d.ts +8 -1
- package/dist/text-layout.js +13 -1
- package/dist/usage.cjs +41 -13
- package/dist/usage.d.cts +20 -0
- package/dist/usage.d.ts +20 -0
- package/dist/usage.js +41 -13
- package/package.json +10 -2
package/dist/usage.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getDisplayWidth } from "./displaywidth.js";
|
|
2
2
|
import { cacheTerminalTheme, formatTerminalLeaf, fragmentTokens, serializeTokens } from "./terminal-internal.js";
|
|
3
|
+
import { forgetEmptyInput, resolveUsageForDisplay } from "./internal/usage.js";
|
|
3
4
|
import { validateProgramName } from "./validate.js";
|
|
4
5
|
|
|
5
6
|
//#region src/usage.ts
|
|
@@ -190,16 +191,33 @@ function formatUsage(programName, usage, options = {}) {
|
|
|
190
191
|
theme: cacheTerminalTheme(options.theme)
|
|
191
192
|
};
|
|
192
193
|
validateProgramName(programName);
|
|
193
|
-
usage
|
|
194
|
+
return formatUsageLines(programName, normalizeUsage(filterUsageForDisplay(resolveUsageForDisplay(usage, isUsageHidden))), normalizeUsage(filterUsageForDisplay(forgetEmptyInput(usage))), options);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Formats a display-ready usage, expanding a trailing command group into one
|
|
198
|
+
* line per command when requested.
|
|
199
|
+
* @param programName The program name.
|
|
200
|
+
* @param usage The usage to draw, already resolved, filtered and normalized.
|
|
201
|
+
* @param declared The same usage as declared, without empty-input records,
|
|
202
|
+
* filtered and normalized. It tells a group that was drawn
|
|
203
|
+
* as optional because it accepts empty input apart from a
|
|
204
|
+
* group declared optional.
|
|
205
|
+
* @param options The formatting options.
|
|
206
|
+
* @returns The formatted usage.
|
|
207
|
+
*/
|
|
208
|
+
function formatUsageLines(programName, usage, declared, options) {
|
|
194
209
|
if (options.expandCommands) {
|
|
195
|
-
|
|
210
|
+
let lastTerm = usage.at(-1);
|
|
211
|
+
const declaredLast = declared.at(-1);
|
|
212
|
+
if (lastTerm?.type === "optional" && lastTerm.terms.length === 1 && lastTerm.terms[0].type === "exclusive" && declaredLast?.type === "exclusive") lastTerm = lastTerm.terms[0];
|
|
196
213
|
if (usage.length > 0 && usage.slice(0, -1).every((t) => t.type === "command") && lastTerm.type === "exclusive" && lastTerm.terms.every((t) => t.length > 0 && (t[0].type === "command" || t[0].type === "option" || t[0].type === "argument" || t[0].type === "optional" && t[0].terms.length === 1 && (t[0].terms[0].type === "command" || t[0].terms[0].type === "option" || t[0].terms[0].type === "argument")))) {
|
|
214
|
+
const declaredBranches = declaredLast?.type === "exclusive" && declaredLast.terms.length === lastTerm.terms.length ? declaredLast.terms : void 0;
|
|
197
215
|
const lines = [];
|
|
198
|
-
for (
|
|
216
|
+
for (const [index, command] of lastTerm.terms.entries()) {
|
|
199
217
|
const firstTerm = command[0];
|
|
200
218
|
if (firstTerm?.type === "command" && isUsageHidden(firstTerm.hidden)) continue;
|
|
201
|
-
|
|
202
|
-
lines.push(
|
|
219
|
+
const line = normalizeUsage(filterUsageForDisplay([...usage.slice(0, -1), ...command]));
|
|
220
|
+
lines.push(formatUsageLines(programName, line, declaredBranches == null ? line : normalizeUsage(filterUsageForDisplay([...declared.slice(0, -1), ...declaredBranches[index]])), options));
|
|
203
221
|
}
|
|
204
222
|
if (lines.length > 0) return lines.join("\n");
|
|
205
223
|
}
|
|
@@ -277,7 +295,8 @@ function normalizeUsageTerm(term) {
|
|
|
277
295
|
} else if (term.type === "multiple") return {
|
|
278
296
|
type: "multiple",
|
|
279
297
|
terms: normalizeUsage(term.terms),
|
|
280
|
-
min: term.min
|
|
298
|
+
min: term.min,
|
|
299
|
+
...acceptsEmptyOf(term)
|
|
281
300
|
};
|
|
282
301
|
else if (term.type === "sequence") return {
|
|
283
302
|
type: "sequence",
|
|
@@ -287,14 +306,15 @@ function normalizeUsageTerm(term) {
|
|
|
287
306
|
const terms = [];
|
|
288
307
|
for (const usage of term.terms) {
|
|
289
308
|
const normalized = normalizeUsage(usage);
|
|
290
|
-
if (normalized.length >= 1 && normalized[0].type === "exclusive") {
|
|
309
|
+
if (normalized.length >= 1 && normalized[0].type === "exclusive" && normalized[0].acceptsEmpty == null) {
|
|
291
310
|
const rest = normalized.slice(1);
|
|
292
311
|
for (const subUsage of normalized[0].terms) terms.push([...subUsage, ...rest]);
|
|
293
312
|
} else if (normalized.length > 0 || !containsMalformedLeaf(usage)) terms.push(normalized);
|
|
294
313
|
}
|
|
295
314
|
return {
|
|
296
315
|
type: "exclusive",
|
|
297
|
-
terms
|
|
316
|
+
terms,
|
|
317
|
+
...acceptsEmptyOf(term)
|
|
298
318
|
};
|
|
299
319
|
} else {
|
|
300
320
|
if (term.type === "option") return {
|
|
@@ -311,10 +331,14 @@ function normalizeUsageTerm(term) {
|
|
|
311
331
|
return { ...term };
|
|
312
332
|
}
|
|
313
333
|
}
|
|
334
|
+
function acceptsEmptyOf(term) {
|
|
335
|
+
return term.acceptsEmpty == null ? {} : { acceptsEmpty: term.acceptsEmpty };
|
|
336
|
+
}
|
|
314
337
|
function isNonDegenerateTerm(term) {
|
|
315
338
|
if (term.type === "option") return term.names.length > 0;
|
|
316
339
|
if (term.type === "command") return term.name !== "";
|
|
317
340
|
if (term.type === "argument") return term.metavar.length > 0;
|
|
341
|
+
if ((term.type === "multiple" || term.type === "exclusive") && term.acceptsEmpty != null) return true;
|
|
318
342
|
if (term.type === "optional" || term.type === "multiple" || term.type === "exclusive" || term.type === "sequence") return term.terms.length > 0;
|
|
319
343
|
return true;
|
|
320
344
|
}
|
|
@@ -370,11 +394,13 @@ function cloneUsageTerm(term) {
|
|
|
370
394
|
case "multiple": return {
|
|
371
395
|
type: "multiple",
|
|
372
396
|
terms: term.terms.map(cloneUsageTerm),
|
|
373
|
-
min: term.min
|
|
397
|
+
min: term.min,
|
|
398
|
+
...acceptsEmptyOf(term)
|
|
374
399
|
};
|
|
375
400
|
case "exclusive": return {
|
|
376
401
|
type: "exclusive",
|
|
377
|
-
terms: term.terms.map((u) => u.map(cloneUsageTerm))
|
|
402
|
+
terms: term.terms.map((u) => u.map(cloneUsageTerm)),
|
|
403
|
+
...acceptsEmptyOf(term)
|
|
378
404
|
};
|
|
379
405
|
case "sequence": return {
|
|
380
406
|
type: "sequence",
|
|
@@ -416,7 +442,8 @@ function filterUsageForDisplay(usage, isHidden = isUsageHidden) {
|
|
|
416
442
|
if (filtered.length > 0) terms.push({
|
|
417
443
|
type: "multiple",
|
|
418
444
|
terms: filtered,
|
|
419
|
-
min: term.min
|
|
445
|
+
min: term.min,
|
|
446
|
+
...acceptsEmptyOf(term)
|
|
420
447
|
});
|
|
421
448
|
continue;
|
|
422
449
|
}
|
|
@@ -428,7 +455,8 @@ function filterUsageForDisplay(usage, isHidden = isUsageHidden) {
|
|
|
428
455
|
}).filter((branch) => branch.length > 0);
|
|
429
456
|
if (filteredBranches.length > 0) terms.push({
|
|
430
457
|
type: "exclusive",
|
|
431
|
-
terms: filteredBranches
|
|
458
|
+
terms: filteredBranches,
|
|
459
|
+
...acceptsEmptyOf(term)
|
|
432
460
|
});
|
|
433
461
|
continue;
|
|
434
462
|
}
|
|
@@ -482,7 +510,7 @@ function formatUsageTerm(term, options = {}) {
|
|
|
482
510
|
theme: cacheTerminalTheme(options.theme)
|
|
483
511
|
};
|
|
484
512
|
const hiddenCheck = options.context === "doc" ? isDocHidden : isUsageHidden;
|
|
485
|
-
const visibleTerms = filterUsageForDisplay([term], hiddenCheck);
|
|
513
|
+
const visibleTerms = filterUsageForDisplay(resolveUsageForDisplay([term], hiddenCheck), hiddenCheck);
|
|
486
514
|
if (visibleTerms.length < 1) return "";
|
|
487
515
|
return wrapUsageTokens(formatUsageTermInternal(visibleTerms[0], options), options);
|
|
488
516
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/core",
|
|
3
|
-
"version": "1.4.0-dev.
|
|
3
|
+
"version": "1.4.0-dev.2709",
|
|
4
4
|
"description": "Type-safe combinatorial command-line interface parser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -227,6 +227,14 @@
|
|
|
227
227
|
},
|
|
228
228
|
"import": "./dist/internal/terminal.js",
|
|
229
229
|
"require": "./dist/internal/terminal.cjs"
|
|
230
|
+
},
|
|
231
|
+
"./internal/usage": {
|
|
232
|
+
"types": {
|
|
233
|
+
"import": "./dist/internal/usage.d.ts",
|
|
234
|
+
"require": "./dist/internal/usage.d.cts"
|
|
235
|
+
},
|
|
236
|
+
"import": "./dist/internal/usage.js",
|
|
237
|
+
"require": "./dist/internal/usage.cjs"
|
|
230
238
|
}
|
|
231
239
|
},
|
|
232
240
|
"imports": {
|
|
@@ -237,7 +245,7 @@
|
|
|
237
245
|
},
|
|
238
246
|
"sideEffects": false,
|
|
239
247
|
"devDependencies": {
|
|
240
|
-
"@optique/env": "1.4.0-dev.
|
|
248
|
+
"@optique/env": "1.4.0-dev.2709+c0360f12",
|
|
241
249
|
"@types/node": "^24.0.0",
|
|
242
250
|
"fast-check": "^4.7.0",
|
|
243
251
|
"tsdown": "^0.13.0",
|