@optique/core 1.3.0-dev.2529 → 1.3.0-dev.2532
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/doc.cjs +93 -84
- package/dist/doc.d.cts +12 -1
- package/dist/doc.d.ts +12 -1
- package/dist/doc.js +88 -79
- package/dist/facade.cjs +49 -15
- package/dist/facade.d.cts +12 -1
- package/dist/facade.d.ts +12 -1
- package/dist/facade.js +48 -14
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/internal/terminal.cjs +7 -0
- package/dist/internal/terminal.d.cts +4 -0
- package/dist/internal/terminal.d.ts +4 -0
- package/dist/internal/terminal.js +5 -0
- package/dist/message-registry.cjs +6 -0
- package/dist/message-registry.d.cts +7 -0
- package/dist/message-registry.d.ts +7 -0
- package/dist/message-registry.js +5 -0
- package/dist/message-renderer.cjs +26 -0
- package/dist/message-renderer.d.cts +19 -0
- package/dist/message-renderer.d.ts +19 -0
- package/dist/message-renderer.js +26 -0
- package/dist/message.cjs +49 -85
- package/dist/message.d.cts +31 -1
- package/dist/message.d.ts +31 -1
- package/dist/message.js +49 -86
- package/dist/terminal-internal.cjs +268 -0
- package/dist/terminal-internal.d.cts +36 -0
- package/dist/terminal-internal.d.ts +36 -0
- package/dist/terminal-internal.js +262 -0
- package/dist/terminal.cjs +73 -0
- package/dist/terminal.d.cts +129 -0
- package/dist/terminal.d.ts +129 -0
- package/dist/terminal.js +72 -0
- package/dist/usage.cjs +110 -134
- package/dist/usage.d.cts +8 -0
- package/dist/usage.d.ts +8 -0
- package/dist/usage.js +110 -134
- package/package.json +18 -2
- package/skills/optique/SKILL.md +3 -3
package/dist/usage.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_displaywidth = require('./displaywidth.cjs');
|
|
2
|
+
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
2
3
|
const require_validate = require('./validate.cjs');
|
|
3
4
|
|
|
4
5
|
//#region src/usage.ts
|
|
@@ -182,6 +183,10 @@ function extractArgumentMetavars(usage) {
|
|
|
182
183
|
* whitespace-only, or contains control characters.
|
|
183
184
|
*/
|
|
184
185
|
function formatUsage(programName, usage, options = {}) {
|
|
186
|
+
options = {
|
|
187
|
+
...options,
|
|
188
|
+
theme: require_terminal_internal.cacheTerminalTheme(options.theme)
|
|
189
|
+
};
|
|
185
190
|
require_validate.validateProgramName(programName);
|
|
186
191
|
usage = normalizeUsage(filterUsageForDisplay(usage));
|
|
187
192
|
if (options.expandCommands) {
|
|
@@ -197,29 +202,23 @@ function formatUsage(programName, usage, options = {}) {
|
|
|
197
202
|
if (lines.length > 0) return lines.join("\n");
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (text === " ") continue;
|
|
218
|
-
}
|
|
219
|
-
output += text;
|
|
220
|
-
lineWidth += width;
|
|
221
|
-
}
|
|
222
|
-
return output;
|
|
205
|
+
const programTokens = layoutUsageTokens(require_terminal_internal.fragmentTokens(require_terminal_internal.formatTerminalTerm({
|
|
206
|
+
type: "programName",
|
|
207
|
+
programName
|
|
208
|
+
}, options.theme)), options);
|
|
209
|
+
const terms = [...formatUsageTerms(usage, options)];
|
|
210
|
+
if (terms.length === 0) return require_terminal_internal.serializeTokens(programTokens, options.colors);
|
|
211
|
+
const width = programTokens.reduce((n, token) => token.width === -1 ? 0 : n + token.width, 0);
|
|
212
|
+
const separator = options.maxWidth != null && width + 1 + terms[0].width > options.maxWidth ? {
|
|
213
|
+
text: "\n",
|
|
214
|
+
width: -1,
|
|
215
|
+
scopes: []
|
|
216
|
+
} : {
|
|
217
|
+
text: " ",
|
|
218
|
+
width: 1,
|
|
219
|
+
scopes: []
|
|
220
|
+
};
|
|
221
|
+
return require_terminal_internal.serializeTokens([...programTokens, separator], options.colors) + wrapUsageTokens(terms, options, separator.width === -1 ? 0 : width + 1);
|
|
223
222
|
}
|
|
224
223
|
/**
|
|
225
224
|
* Normalizes a usage description by flattening nested exclusive terms,
|
|
@@ -454,7 +453,8 @@ function* formatUsageTerms(terms, options) {
|
|
|
454
453
|
for (const t of terms) {
|
|
455
454
|
if (i > 0) yield {
|
|
456
455
|
text: " ",
|
|
457
|
-
width: 1
|
|
456
|
+
width: 1,
|
|
457
|
+
scopes: []
|
|
458
458
|
};
|
|
459
459
|
yield* formatUsageTermInternal(t, options);
|
|
460
460
|
i++;
|
|
@@ -468,141 +468,117 @@ function* formatUsageTerms(terms, options) {
|
|
|
468
468
|
* @param options Optional formatting options to customize the output.
|
|
469
469
|
* See {@link UsageTermFormatOptions} for available options.
|
|
470
470
|
* @returns A formatted string representation of the usage term.
|
|
471
|
+
* @throws {RangeError} If a theme supplies an invalid RGB channel or palette
|
|
472
|
+
* index, even when colors are disabled.
|
|
471
473
|
*/
|
|
472
474
|
function formatUsageTerm(term, options = {}) {
|
|
475
|
+
options = {
|
|
476
|
+
...options,
|
|
477
|
+
theme: require_terminal_internal.cacheTerminalTheme(options.theme)
|
|
478
|
+
};
|
|
473
479
|
const hiddenCheck = options.context === "doc" ? isDocHidden : isUsageHidden;
|
|
474
480
|
const visibleTerms = filterUsageForDisplay([term], hiddenCheck);
|
|
475
481
|
if (visibleTerms.length < 1) return "";
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
return wrapUsageTokens(formatUsageTermInternal(visibleTerms[0], options), options);
|
|
483
|
+
}
|
|
484
|
+
function wrapUsageTokens(input, options, initialWidth = 0) {
|
|
485
|
+
return require_terminal_internal.serializeTokens(layoutUsageTokens(input, options, initialWidth), options.colors);
|
|
486
|
+
}
|
|
487
|
+
function layoutUsageTokens(input, options, initialWidth = 0) {
|
|
488
|
+
let lineWidth = initialWidth;
|
|
489
|
+
const output = [];
|
|
490
|
+
for (const token of input) {
|
|
491
|
+
if (options.maxWidth != null && lineWidth > 0 && lineWidth + token.width > options.maxWidth) {
|
|
492
|
+
const last = output.at(-1);
|
|
493
|
+
if (last?.text.endsWith(" ") && (!options.colors || last.scopes.length === 0)) output[output.length - 1] = {
|
|
494
|
+
...last,
|
|
495
|
+
text: last.text.slice(0, -1),
|
|
496
|
+
width: last.width - 1
|
|
497
|
+
};
|
|
498
|
+
output.push({
|
|
499
|
+
text: "\n",
|
|
500
|
+
width: -1,
|
|
501
|
+
scopes: []
|
|
502
|
+
});
|
|
482
503
|
lineWidth = 0;
|
|
483
|
-
if (text === " ") continue;
|
|
504
|
+
if (token.text === " ") continue;
|
|
484
505
|
}
|
|
485
|
-
output
|
|
486
|
-
lineWidth += width;
|
|
506
|
+
output.push(token);
|
|
507
|
+
lineWidth += token.width;
|
|
487
508
|
}
|
|
488
509
|
return output;
|
|
489
510
|
}
|
|
490
511
|
function* formatUsageTermInternal(term, options) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
512
|
+
function leaf(t, usage) {
|
|
513
|
+
return require_terminal_internal.fragmentTokens(require_terminal_internal.formatTerminalTerm(t, options.theme, false, usage));
|
|
514
|
+
}
|
|
515
|
+
function punctuation(punctuation$1, kind) {
|
|
516
|
+
return leaf({
|
|
517
|
+
type: "syntaxPunctuation",
|
|
518
|
+
punctuation: punctuation$1,
|
|
519
|
+
kind
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
const space = {
|
|
523
|
+
text: " ",
|
|
524
|
+
width: 1,
|
|
525
|
+
scopes: []
|
|
495
526
|
};
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
};
|
|
509
|
-
yield {
|
|
510
|
-
text: options?.colors ? `\x1b[3m${optionName}\x1b[0m` : optionName,
|
|
511
|
-
width: require_displaywidth.getDisplayWidth(optionName)
|
|
512
|
-
};
|
|
513
|
-
i++;
|
|
527
|
+
if (term.type === "argument") yield* leaf({
|
|
528
|
+
type: "metavar",
|
|
529
|
+
metavar: term.metavar
|
|
530
|
+
}, "argument");
|
|
531
|
+
else if (term.type === "option") {
|
|
532
|
+
const names = options.onlyShortestOptions ? [term.names.reduce((a, b) => require_displaywidth.getDisplayWidth(a) <= require_displaywidth.getDisplayWidth(b) ? a : b)] : term.names;
|
|
533
|
+
for (let i = 0; i < names.length; i++) {
|
|
534
|
+
if (i > 0) yield* punctuation(options.optionsSeparator ?? "/", "optionSeparator");
|
|
535
|
+
yield* leaf({
|
|
536
|
+
type: "optionName",
|
|
537
|
+
optionName: names[i]
|
|
538
|
+
});
|
|
514
539
|
}
|
|
515
|
-
if (term.metavar != null) {
|
|
516
|
-
yield
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
text: options?.colors ? `\x1b[4m\x1b[2m${term.metavar}\x1b[0m` : term.metavar,
|
|
522
|
-
width: require_displaywidth.getDisplayWidth(term.metavar)
|
|
523
|
-
};
|
|
540
|
+
if (!options.onlyShortestOptions && term.metavar != null) {
|
|
541
|
+
yield space;
|
|
542
|
+
yield* leaf({
|
|
543
|
+
type: "metavar",
|
|
544
|
+
metavar: term.metavar
|
|
545
|
+
}, "optionValue");
|
|
524
546
|
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
};
|
|
547
|
+
} else if (term.type === "command") yield* leaf({
|
|
548
|
+
type: "optionName",
|
|
549
|
+
optionName: term.name
|
|
550
|
+
}, "command");
|
|
530
551
|
else if (term.type === "optional") {
|
|
531
|
-
yield
|
|
532
|
-
text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
|
|
533
|
-
width: 1
|
|
534
|
-
};
|
|
552
|
+
yield* punctuation("[", "optionalOpen");
|
|
535
553
|
yield* formatUsageTerms(term.terms, options);
|
|
536
|
-
yield
|
|
537
|
-
text: options?.colors ? `\x1b[2m]\x1b[0m` : "]",
|
|
538
|
-
width: 1
|
|
539
|
-
};
|
|
554
|
+
yield* punctuation("]", "optionalClose");
|
|
540
555
|
} else if (term.type === "exclusive") {
|
|
541
|
-
yield
|
|
542
|
-
|
|
543
|
-
width: 1
|
|
544
|
-
};
|
|
545
|
-
let i = 0;
|
|
546
|
-
for (const termGroup of term.terms) {
|
|
556
|
+
yield* punctuation("(", "groupOpen");
|
|
557
|
+
for (let i = 0; i < term.terms.length; i++) {
|
|
547
558
|
if (i > 0) {
|
|
548
|
-
yield
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
};
|
|
552
|
-
yield {
|
|
553
|
-
text: "|",
|
|
554
|
-
width: 1
|
|
555
|
-
};
|
|
556
|
-
yield {
|
|
557
|
-
text: " ",
|
|
558
|
-
width: 1
|
|
559
|
-
};
|
|
559
|
+
yield space;
|
|
560
|
+
yield* punctuation("|", "alternative");
|
|
561
|
+
yield space;
|
|
560
562
|
}
|
|
561
|
-
yield* formatUsageTerms(
|
|
562
|
-
i++;
|
|
563
|
+
yield* formatUsageTerms(term.terms[i], options);
|
|
563
564
|
}
|
|
564
|
-
yield
|
|
565
|
-
text: options?.colors ? `\x1b[2m)\x1b[0m` : ")",
|
|
566
|
-
width: 1
|
|
567
|
-
};
|
|
565
|
+
yield* punctuation(")", "groupClose");
|
|
568
566
|
} else if (term.type === "sequence") yield* formatUsageTerms(term.terms, options);
|
|
569
567
|
else if (term.type === "multiple") {
|
|
570
|
-
if (term.min < 1) yield
|
|
571
|
-
text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
|
|
572
|
-
width: 1
|
|
573
|
-
};
|
|
568
|
+
if (term.min < 1) yield* punctuation("[", "optionalOpen");
|
|
574
569
|
for (let i = 0; i < Math.max(1, term.min); i++) {
|
|
575
|
-
if (i > 0) yield
|
|
576
|
-
text: " ",
|
|
577
|
-
width: 1
|
|
578
|
-
};
|
|
570
|
+
if (i > 0) yield space;
|
|
579
571
|
yield* formatUsageTerms(term.terms, options);
|
|
580
572
|
}
|
|
581
|
-
yield
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
text: term.value,
|
|
591
|
-
width: require_displaywidth.getDisplayWidth(term.value)
|
|
592
|
-
};
|
|
593
|
-
else if (term.type === "passthrough") {
|
|
594
|
-
const text = "[...]";
|
|
595
|
-
yield {
|
|
596
|
-
text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
|
|
597
|
-
width: 5
|
|
598
|
-
};
|
|
599
|
-
} else if (term.type === "ellipsis") {
|
|
600
|
-
const text = "...";
|
|
601
|
-
yield {
|
|
602
|
-
text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
|
|
603
|
-
width: 3
|
|
604
|
-
};
|
|
605
|
-
} else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
|
|
573
|
+
yield* punctuation("...", "ellipsis");
|
|
574
|
+
if (term.min < 1) yield* punctuation("]", "optionalClose");
|
|
575
|
+
} else if (term.type === "literal") yield* leaf({
|
|
576
|
+
type: "value",
|
|
577
|
+
value: term.value
|
|
578
|
+
}, "literal");
|
|
579
|
+
else if (term.type === "passthrough") yield* punctuation("[...]", "passthrough");
|
|
580
|
+
else if (term.type === "ellipsis") yield* punctuation("...", "ellipsis");
|
|
581
|
+
else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
|
|
606
582
|
}
|
|
607
583
|
|
|
608
584
|
//#endregion
|
package/dist/usage.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NonEmptyString } from "./nonempty.cjs";
|
|
2
|
+
import { TerminalTheme } from "./terminal.cjs";
|
|
2
3
|
|
|
3
4
|
//#region src/usage.d.ts
|
|
4
5
|
|
|
@@ -340,6 +341,11 @@ declare function extractArgumentMetavars(usage: Usage): Set<string>;
|
|
|
340
341
|
* Options for formatting usage descriptions.
|
|
341
342
|
*/
|
|
342
343
|
interface UsageFormatOptions {
|
|
344
|
+
/**
|
|
345
|
+
* Semantic terminal theme.
|
|
346
|
+
* @since 1.3.0
|
|
347
|
+
*/
|
|
348
|
+
readonly theme?: TerminalTheme;
|
|
343
349
|
/**
|
|
344
350
|
* When `true`, expands commands in the usage description
|
|
345
351
|
* to multiple lines, showing each command on a new line.
|
|
@@ -477,6 +483,8 @@ interface UsageTermFormatOptions extends UsageFormatOptions {
|
|
|
477
483
|
* @param options Optional formatting options to customize the output.
|
|
478
484
|
* See {@link UsageTermFormatOptions} for available options.
|
|
479
485
|
* @returns A formatted string representation of the usage term.
|
|
486
|
+
* @throws {RangeError} If a theme supplies an invalid RGB channel or palette
|
|
487
|
+
* index, even when colors are disabled.
|
|
480
488
|
*/
|
|
481
489
|
declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
|
|
482
490
|
//#endregion
|
package/dist/usage.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NonEmptyString } from "./nonempty.js";
|
|
2
|
+
import { TerminalTheme } from "./terminal.js";
|
|
2
3
|
|
|
3
4
|
//#region src/usage.d.ts
|
|
4
5
|
|
|
@@ -340,6 +341,11 @@ declare function extractArgumentMetavars(usage: Usage): Set<string>;
|
|
|
340
341
|
* Options for formatting usage descriptions.
|
|
341
342
|
*/
|
|
342
343
|
interface UsageFormatOptions {
|
|
344
|
+
/**
|
|
345
|
+
* Semantic terminal theme.
|
|
346
|
+
* @since 1.3.0
|
|
347
|
+
*/
|
|
348
|
+
readonly theme?: TerminalTheme;
|
|
343
349
|
/**
|
|
344
350
|
* When `true`, expands commands in the usage description
|
|
345
351
|
* to multiple lines, showing each command on a new line.
|
|
@@ -477,6 +483,8 @@ interface UsageTermFormatOptions extends UsageFormatOptions {
|
|
|
477
483
|
* @param options Optional formatting options to customize the output.
|
|
478
484
|
* See {@link UsageTermFormatOptions} for available options.
|
|
479
485
|
* @returns A formatted string representation of the usage term.
|
|
486
|
+
* @throws {RangeError} If a theme supplies an invalid RGB channel or palette
|
|
487
|
+
* index, even when colors are disabled.
|
|
480
488
|
*/
|
|
481
489
|
declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
|
|
482
490
|
//#endregion
|
package/dist/usage.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDisplayWidth } from "./displaywidth.js";
|
|
2
|
+
import { cacheTerminalTheme, formatTerminalTerm, fragmentTokens, serializeTokens } from "./terminal-internal.js";
|
|
2
3
|
import { validateProgramName } from "./validate.js";
|
|
3
4
|
|
|
4
5
|
//#region src/usage.ts
|
|
@@ -182,6 +183,10 @@ function extractArgumentMetavars(usage) {
|
|
|
182
183
|
* whitespace-only, or contains control characters.
|
|
183
184
|
*/
|
|
184
185
|
function formatUsage(programName, usage, options = {}) {
|
|
186
|
+
options = {
|
|
187
|
+
...options,
|
|
188
|
+
theme: cacheTerminalTheme(options.theme)
|
|
189
|
+
};
|
|
185
190
|
validateProgramName(programName);
|
|
186
191
|
usage = normalizeUsage(filterUsageForDisplay(usage));
|
|
187
192
|
if (options.expandCommands) {
|
|
@@ -197,29 +202,23 @@ function formatUsage(programName, usage, options = {}) {
|
|
|
197
202
|
if (lines.length > 0) return lines.join("\n");
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (text === " ") continue;
|
|
218
|
-
}
|
|
219
|
-
output += text;
|
|
220
|
-
lineWidth += width;
|
|
221
|
-
}
|
|
222
|
-
return output;
|
|
205
|
+
const programTokens = layoutUsageTokens(fragmentTokens(formatTerminalTerm({
|
|
206
|
+
type: "programName",
|
|
207
|
+
programName
|
|
208
|
+
}, options.theme)), options);
|
|
209
|
+
const terms = [...formatUsageTerms(usage, options)];
|
|
210
|
+
if (terms.length === 0) return serializeTokens(programTokens, options.colors);
|
|
211
|
+
const width = programTokens.reduce((n, token) => token.width === -1 ? 0 : n + token.width, 0);
|
|
212
|
+
const separator = options.maxWidth != null && width + 1 + terms[0].width > options.maxWidth ? {
|
|
213
|
+
text: "\n",
|
|
214
|
+
width: -1,
|
|
215
|
+
scopes: []
|
|
216
|
+
} : {
|
|
217
|
+
text: " ",
|
|
218
|
+
width: 1,
|
|
219
|
+
scopes: []
|
|
220
|
+
};
|
|
221
|
+
return serializeTokens([...programTokens, separator], options.colors) + wrapUsageTokens(terms, options, separator.width === -1 ? 0 : width + 1);
|
|
223
222
|
}
|
|
224
223
|
/**
|
|
225
224
|
* Normalizes a usage description by flattening nested exclusive terms,
|
|
@@ -454,7 +453,8 @@ function* formatUsageTerms(terms, options) {
|
|
|
454
453
|
for (const t of terms) {
|
|
455
454
|
if (i > 0) yield {
|
|
456
455
|
text: " ",
|
|
457
|
-
width: 1
|
|
456
|
+
width: 1,
|
|
457
|
+
scopes: []
|
|
458
458
|
};
|
|
459
459
|
yield* formatUsageTermInternal(t, options);
|
|
460
460
|
i++;
|
|
@@ -468,141 +468,117 @@ function* formatUsageTerms(terms, options) {
|
|
|
468
468
|
* @param options Optional formatting options to customize the output.
|
|
469
469
|
* See {@link UsageTermFormatOptions} for available options.
|
|
470
470
|
* @returns A formatted string representation of the usage term.
|
|
471
|
+
* @throws {RangeError} If a theme supplies an invalid RGB channel or palette
|
|
472
|
+
* index, even when colors are disabled.
|
|
471
473
|
*/
|
|
472
474
|
function formatUsageTerm(term, options = {}) {
|
|
475
|
+
options = {
|
|
476
|
+
...options,
|
|
477
|
+
theme: cacheTerminalTheme(options.theme)
|
|
478
|
+
};
|
|
473
479
|
const hiddenCheck = options.context === "doc" ? isDocHidden : isUsageHidden;
|
|
474
480
|
const visibleTerms = filterUsageForDisplay([term], hiddenCheck);
|
|
475
481
|
if (visibleTerms.length < 1) return "";
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
return wrapUsageTokens(formatUsageTermInternal(visibleTerms[0], options), options);
|
|
483
|
+
}
|
|
484
|
+
function wrapUsageTokens(input, options, initialWidth = 0) {
|
|
485
|
+
return serializeTokens(layoutUsageTokens(input, options, initialWidth), options.colors);
|
|
486
|
+
}
|
|
487
|
+
function layoutUsageTokens(input, options, initialWidth = 0) {
|
|
488
|
+
let lineWidth = initialWidth;
|
|
489
|
+
const output = [];
|
|
490
|
+
for (const token of input) {
|
|
491
|
+
if (options.maxWidth != null && lineWidth > 0 && lineWidth + token.width > options.maxWidth) {
|
|
492
|
+
const last = output.at(-1);
|
|
493
|
+
if (last?.text.endsWith(" ") && (!options.colors || last.scopes.length === 0)) output[output.length - 1] = {
|
|
494
|
+
...last,
|
|
495
|
+
text: last.text.slice(0, -1),
|
|
496
|
+
width: last.width - 1
|
|
497
|
+
};
|
|
498
|
+
output.push({
|
|
499
|
+
text: "\n",
|
|
500
|
+
width: -1,
|
|
501
|
+
scopes: []
|
|
502
|
+
});
|
|
482
503
|
lineWidth = 0;
|
|
483
|
-
if (text === " ") continue;
|
|
504
|
+
if (token.text === " ") continue;
|
|
484
505
|
}
|
|
485
|
-
output
|
|
486
|
-
lineWidth += width;
|
|
506
|
+
output.push(token);
|
|
507
|
+
lineWidth += token.width;
|
|
487
508
|
}
|
|
488
509
|
return output;
|
|
489
510
|
}
|
|
490
511
|
function* formatUsageTermInternal(term, options) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
512
|
+
function leaf(t, usage) {
|
|
513
|
+
return fragmentTokens(formatTerminalTerm(t, options.theme, false, usage));
|
|
514
|
+
}
|
|
515
|
+
function punctuation(punctuation$1, kind) {
|
|
516
|
+
return leaf({
|
|
517
|
+
type: "syntaxPunctuation",
|
|
518
|
+
punctuation: punctuation$1,
|
|
519
|
+
kind
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
const space = {
|
|
523
|
+
text: " ",
|
|
524
|
+
width: 1,
|
|
525
|
+
scopes: []
|
|
495
526
|
};
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
};
|
|
509
|
-
yield {
|
|
510
|
-
text: options?.colors ? `\x1b[3m${optionName}\x1b[0m` : optionName,
|
|
511
|
-
width: getDisplayWidth(optionName)
|
|
512
|
-
};
|
|
513
|
-
i++;
|
|
527
|
+
if (term.type === "argument") yield* leaf({
|
|
528
|
+
type: "metavar",
|
|
529
|
+
metavar: term.metavar
|
|
530
|
+
}, "argument");
|
|
531
|
+
else if (term.type === "option") {
|
|
532
|
+
const names = options.onlyShortestOptions ? [term.names.reduce((a, b) => getDisplayWidth(a) <= getDisplayWidth(b) ? a : b)] : term.names;
|
|
533
|
+
for (let i = 0; i < names.length; i++) {
|
|
534
|
+
if (i > 0) yield* punctuation(options.optionsSeparator ?? "/", "optionSeparator");
|
|
535
|
+
yield* leaf({
|
|
536
|
+
type: "optionName",
|
|
537
|
+
optionName: names[i]
|
|
538
|
+
});
|
|
514
539
|
}
|
|
515
|
-
if (term.metavar != null) {
|
|
516
|
-
yield
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
text: options?.colors ? `\x1b[4m\x1b[2m${term.metavar}\x1b[0m` : term.metavar,
|
|
522
|
-
width: getDisplayWidth(term.metavar)
|
|
523
|
-
};
|
|
540
|
+
if (!options.onlyShortestOptions && term.metavar != null) {
|
|
541
|
+
yield space;
|
|
542
|
+
yield* leaf({
|
|
543
|
+
type: "metavar",
|
|
544
|
+
metavar: term.metavar
|
|
545
|
+
}, "optionValue");
|
|
524
546
|
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
};
|
|
547
|
+
} else if (term.type === "command") yield* leaf({
|
|
548
|
+
type: "optionName",
|
|
549
|
+
optionName: term.name
|
|
550
|
+
}, "command");
|
|
530
551
|
else if (term.type === "optional") {
|
|
531
|
-
yield
|
|
532
|
-
text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
|
|
533
|
-
width: 1
|
|
534
|
-
};
|
|
552
|
+
yield* punctuation("[", "optionalOpen");
|
|
535
553
|
yield* formatUsageTerms(term.terms, options);
|
|
536
|
-
yield
|
|
537
|
-
text: options?.colors ? `\x1b[2m]\x1b[0m` : "]",
|
|
538
|
-
width: 1
|
|
539
|
-
};
|
|
554
|
+
yield* punctuation("]", "optionalClose");
|
|
540
555
|
} else if (term.type === "exclusive") {
|
|
541
|
-
yield
|
|
542
|
-
|
|
543
|
-
width: 1
|
|
544
|
-
};
|
|
545
|
-
let i = 0;
|
|
546
|
-
for (const termGroup of term.terms) {
|
|
556
|
+
yield* punctuation("(", "groupOpen");
|
|
557
|
+
for (let i = 0; i < term.terms.length; i++) {
|
|
547
558
|
if (i > 0) {
|
|
548
|
-
yield
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
};
|
|
552
|
-
yield {
|
|
553
|
-
text: "|",
|
|
554
|
-
width: 1
|
|
555
|
-
};
|
|
556
|
-
yield {
|
|
557
|
-
text: " ",
|
|
558
|
-
width: 1
|
|
559
|
-
};
|
|
559
|
+
yield space;
|
|
560
|
+
yield* punctuation("|", "alternative");
|
|
561
|
+
yield space;
|
|
560
562
|
}
|
|
561
|
-
yield* formatUsageTerms(
|
|
562
|
-
i++;
|
|
563
|
+
yield* formatUsageTerms(term.terms[i], options);
|
|
563
564
|
}
|
|
564
|
-
yield
|
|
565
|
-
text: options?.colors ? `\x1b[2m)\x1b[0m` : ")",
|
|
566
|
-
width: 1
|
|
567
|
-
};
|
|
565
|
+
yield* punctuation(")", "groupClose");
|
|
568
566
|
} else if (term.type === "sequence") yield* formatUsageTerms(term.terms, options);
|
|
569
567
|
else if (term.type === "multiple") {
|
|
570
|
-
if (term.min < 1) yield
|
|
571
|
-
text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
|
|
572
|
-
width: 1
|
|
573
|
-
};
|
|
568
|
+
if (term.min < 1) yield* punctuation("[", "optionalOpen");
|
|
574
569
|
for (let i = 0; i < Math.max(1, term.min); i++) {
|
|
575
|
-
if (i > 0) yield
|
|
576
|
-
text: " ",
|
|
577
|
-
width: 1
|
|
578
|
-
};
|
|
570
|
+
if (i > 0) yield space;
|
|
579
571
|
yield* formatUsageTerms(term.terms, options);
|
|
580
572
|
}
|
|
581
|
-
yield
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
text: term.value,
|
|
591
|
-
width: getDisplayWidth(term.value)
|
|
592
|
-
};
|
|
593
|
-
else if (term.type === "passthrough") {
|
|
594
|
-
const text = "[...]";
|
|
595
|
-
yield {
|
|
596
|
-
text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
|
|
597
|
-
width: 5
|
|
598
|
-
};
|
|
599
|
-
} else if (term.type === "ellipsis") {
|
|
600
|
-
const text = "...";
|
|
601
|
-
yield {
|
|
602
|
-
text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
|
|
603
|
-
width: 3
|
|
604
|
-
};
|
|
605
|
-
} else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
|
|
573
|
+
yield* punctuation("...", "ellipsis");
|
|
574
|
+
if (term.min < 1) yield* punctuation("]", "optionalClose");
|
|
575
|
+
} else if (term.type === "literal") yield* leaf({
|
|
576
|
+
type: "value",
|
|
577
|
+
value: term.value
|
|
578
|
+
}, "literal");
|
|
579
|
+
else if (term.type === "passthrough") yield* punctuation("[...]", "passthrough");
|
|
580
|
+
else if (term.type === "ellipsis") yield* punctuation("...", "ellipsis");
|
|
581
|
+
else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
|
|
606
582
|
}
|
|
607
583
|
|
|
608
584
|
//#endregion
|