@optique/core 1.3.0-dev.2565 → 1.3.0-dev.2567
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 +1 -1
- package/dist/constructs.js +1 -1
- package/dist/doc.cjs +21 -23
- package/dist/doc.js +22 -24
- package/dist/facade.cjs +50 -25
- package/dist/facade.js +51 -26
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/parser.cjs +1 -1
- package/dist/internal/parser.js +1 -1
- package/dist/internal/terminal.cjs +3 -1
- package/dist/internal/terminal.d.cts +2 -1
- package/dist/internal/terminal.d.ts +2 -1
- package/dist/internal/terminal.js +2 -1
- package/dist/message-renderer.cjs +13 -3
- package/dist/message-renderer.js +14 -4
- package/dist/message.cjs +1 -1
- package/dist/message.js +1 -1
- package/dist/primitives.cjs +1 -1
- package/dist/primitives.js +1 -1
- package/dist/suggestion.cjs +1 -1
- package/dist/suggestion.js +1 -1
- package/dist/terminal-width.cjs +65 -0
- package/dist/terminal-width.d.cts +19 -0
- package/dist/terminal-width.d.ts +19 -0
- package/dist/terminal-width.js +62 -0
- package/package.json +2 -2
package/dist/constructs.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
|
-
const require_message = require('./message.cjs');
|
|
3
2
|
const require_validate = require('./validate.cjs');
|
|
4
3
|
const require_usage = require('./usage.cjs');
|
|
4
|
+
const require_message = require('./message.cjs');
|
|
5
5
|
const require_doc = require('./doc.cjs');
|
|
6
6
|
const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
|
|
7
7
|
const require_internal_dependency = require('./internal/dependency.cjs');
|
package/dist/constructs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { annotateFreshArray, getAnnotations, inheritAnnotations } from "./internal/annotations.js";
|
|
2
|
-
import { message, optionName, text, values } from "./message.js";
|
|
3
2
|
import { validateLabel } from "./validate.js";
|
|
4
3
|
import { extractArgumentMetavars, extractCommandNames, extractOptionNames, isDocHidden, mergeHidden } from "./usage.js";
|
|
4
|
+
import { message, optionName, text, values } from "./message.js";
|
|
5
5
|
import { deduplicateDocFragments } from "./doc.js";
|
|
6
6
|
import { dispatchByMode, dispatchIterableByMode } from "./internal/mode-dispatch.js";
|
|
7
7
|
import { createDependencySourceState, dependencyId, isDependencySourceState, isPendingDependencySourceState, isWrappedDependencySource, wrappedDependencySourceMarker } from "./internal/dependency.js";
|
package/dist/doc.cjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
const require_message_registry = require('./message-registry.cjs');
|
|
2
1
|
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
2
|
const require_text_layout = require('./text-layout.cjs');
|
|
4
|
-
const require_message = require('./message.cjs');
|
|
5
|
-
const require_message_renderer = require('./message-renderer.cjs');
|
|
6
3
|
const require_validate = require('./validate.cjs');
|
|
7
4
|
const require_usage = require('./usage.cjs');
|
|
5
|
+
const require_terminal_width = require('./terminal-width.cjs');
|
|
6
|
+
const require_message_registry = require('./message-registry.cjs');
|
|
7
|
+
const require_message = require('./message.cjs');
|
|
8
|
+
const require_message_renderer = require('./message-renderer.cjs');
|
|
8
9
|
|
|
9
10
|
//#region src/doc.ts
|
|
10
11
|
/**
|
|
@@ -322,11 +323,7 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
322
323
|
const splitEntryMin = termIndent + 2 + Math.max(2, 2 * minDescWidth - 1);
|
|
323
324
|
const fixedEntryMin = termIndent + 2 + termWidth + minDescWidth;
|
|
324
325
|
const entryMin = needsDescColumn ? Math.min(splitEntryMin, fixedEntryMin) : hasEntries ? termIndent + 1 : 1;
|
|
325
|
-
const
|
|
326
|
-
type: "programName",
|
|
327
|
-
programName
|
|
328
|
-
}, options.theme))].map((token) => token.width)) : 0;
|
|
329
|
-
const usageMin = page.usage != null && showUsage ? Math.max(require_text_layout.measureText(usageLabel).maxLineWidth, usageLabelWidth + Math.max(programNameWidth, Math.min(maxVisibleAtomicWidth(page.usage, options.theme), programNameWidth + usageLabelWidth))) : 1;
|
|
326
|
+
const usageMin = page.usage != null && showUsage ? require_terminal_width.minimumUsageWidth(programName, page.usage, usageLabel, options.theme) : 1;
|
|
330
327
|
let sectionMin = 1;
|
|
331
328
|
for (const kind of [
|
|
332
329
|
"examples",
|
|
@@ -338,16 +335,29 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
338
335
|
sectionMin = Math.max(sectionMin, 3, require_text_layout.measureText(label(title, kind)).maxLineWidth);
|
|
339
336
|
}
|
|
340
337
|
const minWidth = Math.max(entryMin, usageMin, sectionMin);
|
|
341
|
-
if (options.maxWidth < minWidth)
|
|
342
|
-
|
|
338
|
+
if (options.maxWidth < minWidth) {
|
|
339
|
+
if (!require_terminal_width.hasAutomaticWidth(options)) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
|
|
340
|
+
options = {
|
|
341
|
+
...options,
|
|
342
|
+
maxWidth: void 0
|
|
343
|
+
};
|
|
344
|
+
effectiveTermWidth = termWidth;
|
|
345
|
+
}
|
|
346
|
+
if (options.maxWidth != null && needsDescColumn && minDescWidth > 1) {
|
|
343
347
|
const avail = options.maxWidth - termIndent - 2;
|
|
344
348
|
const descW = avail - effectiveTermWidth;
|
|
345
349
|
if (descW < minDescWidth) {
|
|
346
350
|
const needed = termIndent + effectiveTermWidth + 2 + minDescWidth;
|
|
347
|
-
throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
|
|
351
|
+
if (!require_terminal_width.hasAutomaticWidth(options)) throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
|
|
352
|
+
options = {
|
|
353
|
+
...options,
|
|
354
|
+
maxWidth: void 0
|
|
355
|
+
};
|
|
356
|
+
effectiveTermWidth = termWidth;
|
|
348
357
|
}
|
|
349
358
|
}
|
|
350
359
|
}
|
|
360
|
+
require_terminal_width.reportAutomaticWidth(options, options.maxWidth);
|
|
351
361
|
let output = "";
|
|
352
362
|
if (hasContent(page.brief)) {
|
|
353
363
|
output += formatMessage(page.brief, {
|
|
@@ -508,18 +518,6 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
508
518
|
function indentLines(text$1, indent) {
|
|
509
519
|
return text$1.split("\n").join("\n" + " ".repeat(indent));
|
|
510
520
|
}
|
|
511
|
-
/**
|
|
512
|
-
* Returns the width of the widest non-breakable segment among visible
|
|
513
|
-
* (non-usage-hidden) terms in a usage tree. Hidden terms are excluded
|
|
514
|
-
* because they are filtered out before rendering, so they do not
|
|
515
|
-
* contribute to the rendered width.
|
|
516
|
-
*/
|
|
517
|
-
function maxVisibleAtomicWidth(usage, theme) {
|
|
518
|
-
return usage.reduce((widest, term) => Math.max(widest, require_text_layout.measureText(require_usage.formatUsageTerm(term, {
|
|
519
|
-
theme,
|
|
520
|
-
maxWidth: 1
|
|
521
|
-
})).maxLineWidth), 0);
|
|
522
|
-
}
|
|
523
521
|
function ansiAwareRightPad(text$1, length, char = " ") {
|
|
524
522
|
const visibleWidth = require_text_layout.measureText(text$1).lastLineWidth;
|
|
525
523
|
if (visibleWidth >= length) return text$1;
|
package/dist/doc.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { cacheTerminalTheme, formatTerminalTerm, fragmentTokens, renderTerminalTerm, styleCode } from "./terminal-internal.js";
|
|
1
|
+
import { cacheTerminalTheme, renderTerminalTerm, styleCode } from "./terminal-internal.js";
|
|
3
2
|
import { measureAnnotation, measureText, placeText, spaceAfterLabel } from "./text-layout.js";
|
|
4
|
-
import { cloneMessage, text } from "./message.js";
|
|
5
|
-
import { resolveMessageFormatter } from "./message-renderer.js";
|
|
6
3
|
import { validateLabel, validateProgramName } from "./validate.js";
|
|
7
4
|
import { cloneUsageTerm, formatUsage, formatUsageTerm, isDocHidden } from "./usage.js";
|
|
5
|
+
import { hasAutomaticWidth, minimumUsageWidth, reportAutomaticWidth } from "./terminal-width.js";
|
|
6
|
+
import { messageRenderers } from "./message-registry.js";
|
|
7
|
+
import { cloneMessage, text } from "./message.js";
|
|
8
|
+
import { resolveMessageFormatter } from "./message-renderer.js";
|
|
8
9
|
|
|
9
10
|
//#region src/doc.ts
|
|
10
11
|
/**
|
|
@@ -322,11 +323,7 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
322
323
|
const splitEntryMin = termIndent + 2 + Math.max(2, 2 * minDescWidth - 1);
|
|
323
324
|
const fixedEntryMin = termIndent + 2 + termWidth + minDescWidth;
|
|
324
325
|
const entryMin = needsDescColumn ? Math.min(splitEntryMin, fixedEntryMin) : hasEntries ? termIndent + 1 : 1;
|
|
325
|
-
const
|
|
326
|
-
type: "programName",
|
|
327
|
-
programName
|
|
328
|
-
}, options.theme))].map((token) => token.width)) : 0;
|
|
329
|
-
const usageMin = page.usage != null && showUsage ? Math.max(measureText(usageLabel).maxLineWidth, usageLabelWidth + Math.max(programNameWidth, Math.min(maxVisibleAtomicWidth(page.usage, options.theme), programNameWidth + usageLabelWidth))) : 1;
|
|
326
|
+
const usageMin = page.usage != null && showUsage ? minimumUsageWidth(programName, page.usage, usageLabel, options.theme) : 1;
|
|
330
327
|
let sectionMin = 1;
|
|
331
328
|
for (const kind of [
|
|
332
329
|
"examples",
|
|
@@ -338,16 +335,29 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
338
335
|
sectionMin = Math.max(sectionMin, 3, measureText(label(title, kind)).maxLineWidth);
|
|
339
336
|
}
|
|
340
337
|
const minWidth = Math.max(entryMin, usageMin, sectionMin);
|
|
341
|
-
if (options.maxWidth < minWidth)
|
|
342
|
-
|
|
338
|
+
if (options.maxWidth < minWidth) {
|
|
339
|
+
if (!hasAutomaticWidth(options)) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
|
|
340
|
+
options = {
|
|
341
|
+
...options,
|
|
342
|
+
maxWidth: void 0
|
|
343
|
+
};
|
|
344
|
+
effectiveTermWidth = termWidth;
|
|
345
|
+
}
|
|
346
|
+
if (options.maxWidth != null && needsDescColumn && minDescWidth > 1) {
|
|
343
347
|
const avail = options.maxWidth - termIndent - 2;
|
|
344
348
|
const descW = avail - effectiveTermWidth;
|
|
345
349
|
if (descW < minDescWidth) {
|
|
346
350
|
const needed = termIndent + effectiveTermWidth + 2 + minDescWidth;
|
|
347
|
-
throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
|
|
351
|
+
if (!hasAutomaticWidth(options)) throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
|
|
352
|
+
options = {
|
|
353
|
+
...options,
|
|
354
|
+
maxWidth: void 0
|
|
355
|
+
};
|
|
356
|
+
effectiveTermWidth = termWidth;
|
|
348
357
|
}
|
|
349
358
|
}
|
|
350
359
|
}
|
|
360
|
+
reportAutomaticWidth(options, options.maxWidth);
|
|
351
361
|
let output = "";
|
|
352
362
|
if (hasContent(page.brief)) {
|
|
353
363
|
output += formatMessage(page.brief, {
|
|
@@ -508,18 +518,6 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
508
518
|
function indentLines(text$1, indent) {
|
|
509
519
|
return text$1.split("\n").join("\n" + " ".repeat(indent));
|
|
510
520
|
}
|
|
511
|
-
/**
|
|
512
|
-
* Returns the width of the widest non-breakable segment among visible
|
|
513
|
-
* (non-usage-hidden) terms in a usage tree. Hidden terms are excluded
|
|
514
|
-
* because they are filtered out before rendering, so they do not
|
|
515
|
-
* contribute to the rendered width.
|
|
516
|
-
*/
|
|
517
|
-
function maxVisibleAtomicWidth(usage, theme) {
|
|
518
|
-
return usage.reduce((widest, term) => Math.max(widest, measureText(formatUsageTerm(term, {
|
|
519
|
-
theme,
|
|
520
|
-
maxWidth: 1
|
|
521
|
-
})).maxLineWidth), 0);
|
|
522
|
-
}
|
|
523
521
|
function ansiAwareRightPad(text$1, length, char = " ") {
|
|
524
522
|
const visibleWidth = measureText(text$1).lastLineWidth;
|
|
525
523
|
if (visibleWidth >= length) return text$1;
|
package/dist/facade.cjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
2
|
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
3
|
const require_text_layout = require('./text-layout.cjs');
|
|
4
|
-
const require_message = require('./message.cjs');
|
|
5
|
-
const require_message_renderer = require('./message-renderer.cjs');
|
|
6
4
|
const require_validate = require('./validate.cjs');
|
|
7
5
|
const require_usage = require('./usage.cjs');
|
|
6
|
+
const require_terminal_width = require('./terminal-width.cjs');
|
|
7
|
+
const require_message = require('./message.cjs');
|
|
8
|
+
const require_message_renderer = require('./message-renderer.cjs');
|
|
8
9
|
const require_doc = require('./doc.cjs');
|
|
9
10
|
const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
|
|
10
11
|
const require_dependency_runtime = require('./dependency-runtime.cjs');
|
|
@@ -516,24 +517,34 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
|
|
|
516
517
|
* Handles shell completion requests.
|
|
517
518
|
* @since 0.6.0
|
|
518
519
|
*/
|
|
519
|
-
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = [], messageFormatter, theme) {
|
|
520
|
+
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = [], messageFormatter, theme, automaticWidth = false) {
|
|
521
|
+
const errorOptions = (format) => automaticWidth ? require_terminal_width.withAutomaticWidth(format, (width) => {
|
|
522
|
+
maxWidth = width;
|
|
523
|
+
}) : format;
|
|
520
524
|
const shellName = completionArgs[0] || "";
|
|
521
525
|
const args = completionArgs.slice(1);
|
|
522
526
|
const callOnError = (code, error) => onError(code, error);
|
|
523
527
|
const callOnCompletion = (code) => onCompletion(code);
|
|
524
528
|
if (!shellName) {
|
|
525
529
|
const error = require_message.message`Missing shell name for completion.`;
|
|
526
|
-
stderr(require_message_renderer.renderErrorMessage(error, {
|
|
530
|
+
const writeError = () => stderr(require_message_renderer.renderErrorMessage(error, errorOptions({
|
|
527
531
|
messageFormatter,
|
|
528
532
|
theme,
|
|
529
533
|
colors,
|
|
530
534
|
quotes: !colors,
|
|
531
535
|
maxWidth
|
|
532
|
-
}) + "\n");
|
|
536
|
+
})) + "\n");
|
|
537
|
+
if (!automaticWidth) writeError();
|
|
538
|
+
let wroteError = !automaticWidth;
|
|
539
|
+
const completionDocOptions = (format) => automaticWidth ? require_terminal_width.withAutomaticWidth(format, (width) => {
|
|
540
|
+
maxWidth = width;
|
|
541
|
+
writeError();
|
|
542
|
+
wroteError = true;
|
|
543
|
+
}) : format;
|
|
533
544
|
if (completionParser) {
|
|
534
545
|
const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
|
|
535
546
|
const doc = require_internal_parser.getDocPage(completionParser, [displayName]);
|
|
536
|
-
if (doc) stderr(require_doc.formatDocPage(programName, doc, {
|
|
547
|
+
if (doc) stderr(require_doc.formatDocPage(programName, doc, completionDocOptions({
|
|
537
548
|
messageFormatter,
|
|
538
549
|
theme,
|
|
539
550
|
colors,
|
|
@@ -541,8 +552,9 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
541
552
|
termWidth,
|
|
542
553
|
sectionOrder,
|
|
543
554
|
showUsage
|
|
544
|
-
}));
|
|
555
|
+
})));
|
|
545
556
|
}
|
|
557
|
+
if (!wroteError) writeError();
|
|
546
558
|
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
547
559
|
const result = callOnError(1, error);
|
|
548
560
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -557,13 +569,13 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
557
569
|
available.push(require_message.value(name));
|
|
558
570
|
}
|
|
559
571
|
const error = require_message.message`Unsupported shell ${shellName}. Available shells: ${available}.`;
|
|
560
|
-
stderr(require_message_renderer.renderErrorMessage(error, {
|
|
572
|
+
stderr(require_message_renderer.renderErrorMessage(error, errorOptions({
|
|
561
573
|
messageFormatter,
|
|
562
574
|
theme,
|
|
563
575
|
colors,
|
|
564
576
|
quotes: !colors,
|
|
565
577
|
maxWidth
|
|
566
|
-
}));
|
|
578
|
+
})));
|
|
567
579
|
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
568
580
|
const result = callOnError(1, error);
|
|
569
581
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -871,9 +883,18 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
871
883
|
options = optionsParam ?? {};
|
|
872
884
|
}
|
|
873
885
|
require_validate.validateProgramName(programName);
|
|
874
|
-
const { colors, messageFormatter, theme, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
886
|
+
const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
875
887
|
throw new RunParserError("Failed to parse command line arguments.");
|
|
876
888
|
}, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
|
|
889
|
+
let maxWidth = requestedMaxWidth;
|
|
890
|
+
const automaticWidth = require_terminal_width.hasAutomaticWidth(options);
|
|
891
|
+
const theme = automaticWidth ? require_terminal_internal.cacheTerminalTheme(requestedTheme) : requestedTheme;
|
|
892
|
+
const formatOptions = (format) => automaticWidth ? require_terminal_width.withAutomaticWidth(format, (width) => {
|
|
893
|
+
maxWidth = width;
|
|
894
|
+
}) : format;
|
|
895
|
+
const resolveUsageWidth = (usage) => {
|
|
896
|
+
if (automaticWidth && maxWidth != null && maxWidth < require_terminal_width.minimumUsageWidth(programName, usage, usageLabel(), theme)) maxWidth = void 0;
|
|
897
|
+
};
|
|
877
898
|
let usagePrefix;
|
|
878
899
|
const usageLabel = () => usagePrefix ??= require_text_layout.spaceAfterLabel(require_terminal_internal.renderTerminalTerm({
|
|
879
900
|
type: "label",
|
|
@@ -1016,7 +1037,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1016
1037
|
classified.shell,
|
|
1017
1038
|
...classified.commandPath ?? [],
|
|
1018
1039
|
...classified.args
|
|
1019
|
-
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, termWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions, messageFormatter, theme);
|
|
1040
|
+
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, termWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions, messageFormatter, theme, automaticWidth);
|
|
1020
1041
|
case "help": {
|
|
1021
1042
|
let helpGeneratorParser;
|
|
1022
1043
|
let docGeneratorParser;
|
|
@@ -1035,19 +1056,20 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1035
1056
|
docGeneratorParser = classified.commands.length > 0 ? parser : helpGeneratorParser;
|
|
1036
1057
|
}
|
|
1037
1058
|
const reportInvalidHelpCommand = (validationError) => {
|
|
1059
|
+
resolveUsageWidth(augmentedParser.usage);
|
|
1038
1060
|
stderr(`${usageLabel()}${indentLines(require_usage.formatUsage(programName, augmentedParser.usage, {
|
|
1039
1061
|
theme,
|
|
1040
1062
|
colors,
|
|
1041
1063
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1042
1064
|
expandCommands: true
|
|
1043
1065
|
}), usageLabelWidth())}`);
|
|
1044
|
-
stderr(require_message_renderer.renderErrorMessage(validationError, {
|
|
1066
|
+
stderr(require_message_renderer.renderErrorMessage(validationError, formatOptions({
|
|
1045
1067
|
messageFormatter,
|
|
1046
1068
|
theme,
|
|
1047
1069
|
colors,
|
|
1048
1070
|
quotes: !colors,
|
|
1049
1071
|
maxWidth
|
|
1050
|
-
}));
|
|
1072
|
+
})));
|
|
1051
1073
|
return onError(1, validationError);
|
|
1052
1074
|
};
|
|
1053
1075
|
const displayHelp = (doc) => {
|
|
@@ -1066,7 +1088,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1066
1088
|
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
1067
1089
|
}, commandList, isTopLevel);
|
|
1068
1090
|
const renderedDoc = isTopLevel && usageLine != null ? applyUsageLine(augmentedDoc, usageLine) : augmentedDoc;
|
|
1069
|
-
stdout(require_doc.formatDocPage(programName, renderedDoc, {
|
|
1091
|
+
stdout(require_doc.formatDocPage(programName, renderedDoc, formatOptions({
|
|
1070
1092
|
messageFormatter,
|
|
1071
1093
|
theme,
|
|
1072
1094
|
colors,
|
|
@@ -1076,7 +1098,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1076
1098
|
showChoices,
|
|
1077
1099
|
sectionOrder,
|
|
1078
1100
|
showUsage
|
|
1079
|
-
}));
|
|
1101
|
+
})));
|
|
1080
1102
|
return onHelp(0, renderedDoc);
|
|
1081
1103
|
}
|
|
1082
1104
|
throw new RunParserError("Failed to generate help page.");
|
|
@@ -1142,7 +1164,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1142
1164
|
}, commandList, isTopLevel);
|
|
1143
1165
|
const defaultRootUsage = typeof usageLine === "function" && (options.help || options.version || options.completion) ? require_usage.normalizeUsage(getRootHelpGeneratorParser().usage) : augmentedDoc.usage ?? [];
|
|
1144
1166
|
const renderedDoc = isTopLevel && usageLine != null ? applyUsageLine(augmentedDoc, usageLine, defaultRootUsage) : augmentedDoc;
|
|
1145
|
-
stderr(require_doc.formatDocPage(programName, renderedDoc, {
|
|
1167
|
+
stderr(require_doc.formatDocPage(programName, renderedDoc, formatOptions({
|
|
1146
1168
|
messageFormatter,
|
|
1147
1169
|
theme,
|
|
1148
1170
|
colors,
|
|
@@ -1152,21 +1174,24 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1152
1174
|
showChoices,
|
|
1153
1175
|
sectionOrder,
|
|
1154
1176
|
showUsage
|
|
1155
|
-
}));
|
|
1177
|
+
})));
|
|
1156
1178
|
}
|
|
1157
|
-
if (effectiveAboveError === "usage")
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1179
|
+
if (effectiveAboveError === "usage") {
|
|
1180
|
+
resolveUsageWidth(augmentedParser.usage);
|
|
1181
|
+
stderr(`${usageLabel()}${indentLines(require_usage.formatUsage(programName, augmentedParser.usage, {
|
|
1182
|
+
theme,
|
|
1183
|
+
colors,
|
|
1184
|
+
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1185
|
+
expandCommands: true
|
|
1186
|
+
}), usageLabelWidth())}`);
|
|
1187
|
+
}
|
|
1188
|
+
stderr(require_message_renderer.renderErrorMessage(classified.error, formatOptions({
|
|
1164
1189
|
messageFormatter,
|
|
1165
1190
|
theme,
|
|
1166
1191
|
colors,
|
|
1167
1192
|
quotes: !colors,
|
|
1168
1193
|
maxWidth
|
|
1169
|
-
}));
|
|
1194
|
+
})));
|
|
1170
1195
|
return onError(1, classified.error);
|
|
1171
1196
|
};
|
|
1172
1197
|
if (aboveError === "help") {
|
package/dist/facade.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { injectAnnotations } from "./internal/annotations.js";
|
|
2
|
-
import { renderTerminalTerm } from "./terminal-internal.js";
|
|
2
|
+
import { cacheTerminalTheme, renderTerminalTerm } from "./terminal-internal.js";
|
|
3
3
|
import { measureText, spaceAfterLabel } from "./text-layout.js";
|
|
4
|
-
import { commandLine, lineBreak, message, optionName, text, value } from "./message.js";
|
|
5
|
-
import { renderErrorMessage } from "./message-renderer.js";
|
|
6
4
|
import { validateCommandNames, validateContextIds, validateMetaNameCollisions, validateOptionNames, validateProgramName } from "./validate.js";
|
|
7
5
|
import { cloneUsage, formatUsage, isSuggestionHidden, normalizeUsage } from "./usage.js";
|
|
6
|
+
import { hasAutomaticWidth, minimumUsageWidth, withAutomaticWidth } from "./terminal-width.js";
|
|
7
|
+
import { commandLine, lineBreak, message, optionName, text, value } from "./message.js";
|
|
8
|
+
import { renderErrorMessage } from "./message-renderer.js";
|
|
8
9
|
import { formatDocPage } from "./doc.js";
|
|
9
10
|
import { dispatchByMode } from "./internal/mode-dispatch.js";
|
|
10
11
|
import { collectExplicitSourceValues, collectExplicitSourceValuesAsync, createDependencyRuntimeContext } from "./dependency-runtime.js";
|
|
@@ -516,24 +517,34 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
|
|
|
516
517
|
* Handles shell completion requests.
|
|
517
518
|
* @since 0.6.0
|
|
518
519
|
*/
|
|
519
|
-
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = [], messageFormatter, theme) {
|
|
520
|
+
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = [], messageFormatter, theme, automaticWidth = false) {
|
|
521
|
+
const errorOptions = (format) => automaticWidth ? withAutomaticWidth(format, (width) => {
|
|
522
|
+
maxWidth = width;
|
|
523
|
+
}) : format;
|
|
520
524
|
const shellName = completionArgs[0] || "";
|
|
521
525
|
const args = completionArgs.slice(1);
|
|
522
526
|
const callOnError = (code, error) => onError(code, error);
|
|
523
527
|
const callOnCompletion = (code) => onCompletion(code);
|
|
524
528
|
if (!shellName) {
|
|
525
529
|
const error = message`Missing shell name for completion.`;
|
|
526
|
-
stderr(renderErrorMessage(error, {
|
|
530
|
+
const writeError = () => stderr(renderErrorMessage(error, errorOptions({
|
|
527
531
|
messageFormatter,
|
|
528
532
|
theme,
|
|
529
533
|
colors,
|
|
530
534
|
quotes: !colors,
|
|
531
535
|
maxWidth
|
|
532
|
-
}) + "\n");
|
|
536
|
+
})) + "\n");
|
|
537
|
+
if (!automaticWidth) writeError();
|
|
538
|
+
let wroteError = !automaticWidth;
|
|
539
|
+
const completionDocOptions = (format) => automaticWidth ? withAutomaticWidth(format, (width) => {
|
|
540
|
+
maxWidth = width;
|
|
541
|
+
writeError();
|
|
542
|
+
wroteError = true;
|
|
543
|
+
}) : format;
|
|
533
544
|
if (completionParser) {
|
|
534
545
|
const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
|
|
535
546
|
const doc = getDocPage(completionParser, [displayName]);
|
|
536
|
-
if (doc) stderr(formatDocPage(programName, doc, {
|
|
547
|
+
if (doc) stderr(formatDocPage(programName, doc, completionDocOptions({
|
|
537
548
|
messageFormatter,
|
|
538
549
|
theme,
|
|
539
550
|
colors,
|
|
@@ -541,8 +552,9 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
541
552
|
termWidth,
|
|
542
553
|
sectionOrder,
|
|
543
554
|
showUsage
|
|
544
|
-
}));
|
|
555
|
+
})));
|
|
545
556
|
}
|
|
557
|
+
if (!wroteError) writeError();
|
|
546
558
|
return dispatchByMode(parser.mode, () => {
|
|
547
559
|
const result = callOnError(1, error);
|
|
548
560
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -557,13 +569,13 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
557
569
|
available.push(value(name));
|
|
558
570
|
}
|
|
559
571
|
const error = message`Unsupported shell ${shellName}. Available shells: ${available}.`;
|
|
560
|
-
stderr(renderErrorMessage(error, {
|
|
572
|
+
stderr(renderErrorMessage(error, errorOptions({
|
|
561
573
|
messageFormatter,
|
|
562
574
|
theme,
|
|
563
575
|
colors,
|
|
564
576
|
quotes: !colors,
|
|
565
577
|
maxWidth
|
|
566
|
-
}));
|
|
578
|
+
})));
|
|
567
579
|
return dispatchByMode(parser.mode, () => {
|
|
568
580
|
const result = callOnError(1, error);
|
|
569
581
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -871,9 +883,18 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
871
883
|
options = optionsParam ?? {};
|
|
872
884
|
}
|
|
873
885
|
validateProgramName(programName);
|
|
874
|
-
const { colors, messageFormatter, theme, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
886
|
+
const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
875
887
|
throw new RunParserError("Failed to parse command line arguments.");
|
|
876
888
|
}, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
|
|
889
|
+
let maxWidth = requestedMaxWidth;
|
|
890
|
+
const automaticWidth = hasAutomaticWidth(options);
|
|
891
|
+
const theme = automaticWidth ? cacheTerminalTheme(requestedTheme) : requestedTheme;
|
|
892
|
+
const formatOptions = (format) => automaticWidth ? withAutomaticWidth(format, (width) => {
|
|
893
|
+
maxWidth = width;
|
|
894
|
+
}) : format;
|
|
895
|
+
const resolveUsageWidth = (usage) => {
|
|
896
|
+
if (automaticWidth && maxWidth != null && maxWidth < minimumUsageWidth(programName, usage, usageLabel(), theme)) maxWidth = void 0;
|
|
897
|
+
};
|
|
877
898
|
let usagePrefix;
|
|
878
899
|
const usageLabel = () => usagePrefix ??= spaceAfterLabel(renderTerminalTerm({
|
|
879
900
|
type: "label",
|
|
@@ -1016,7 +1037,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1016
1037
|
classified.shell,
|
|
1017
1038
|
...classified.commandPath ?? [],
|
|
1018
1039
|
...classified.args
|
|
1019
|
-
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, termWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions, messageFormatter, theme);
|
|
1040
|
+
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, termWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions, messageFormatter, theme, automaticWidth);
|
|
1020
1041
|
case "help": {
|
|
1021
1042
|
let helpGeneratorParser;
|
|
1022
1043
|
let docGeneratorParser;
|
|
@@ -1035,19 +1056,20 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1035
1056
|
docGeneratorParser = classified.commands.length > 0 ? parser : helpGeneratorParser;
|
|
1036
1057
|
}
|
|
1037
1058
|
const reportInvalidHelpCommand = (validationError) => {
|
|
1059
|
+
resolveUsageWidth(augmentedParser.usage);
|
|
1038
1060
|
stderr(`${usageLabel()}${indentLines(formatUsage(programName, augmentedParser.usage, {
|
|
1039
1061
|
theme,
|
|
1040
1062
|
colors,
|
|
1041
1063
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1042
1064
|
expandCommands: true
|
|
1043
1065
|
}), usageLabelWidth())}`);
|
|
1044
|
-
stderr(renderErrorMessage(validationError, {
|
|
1066
|
+
stderr(renderErrorMessage(validationError, formatOptions({
|
|
1045
1067
|
messageFormatter,
|
|
1046
1068
|
theme,
|
|
1047
1069
|
colors,
|
|
1048
1070
|
quotes: !colors,
|
|
1049
1071
|
maxWidth
|
|
1050
|
-
}));
|
|
1072
|
+
})));
|
|
1051
1073
|
return onError(1, validationError);
|
|
1052
1074
|
};
|
|
1053
1075
|
const displayHelp = (doc) => {
|
|
@@ -1066,7 +1088,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1066
1088
|
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
1067
1089
|
}, commandList, isTopLevel);
|
|
1068
1090
|
const renderedDoc = isTopLevel && usageLine != null ? applyUsageLine(augmentedDoc, usageLine) : augmentedDoc;
|
|
1069
|
-
stdout(formatDocPage(programName, renderedDoc, {
|
|
1091
|
+
stdout(formatDocPage(programName, renderedDoc, formatOptions({
|
|
1070
1092
|
messageFormatter,
|
|
1071
1093
|
theme,
|
|
1072
1094
|
colors,
|
|
@@ -1076,7 +1098,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1076
1098
|
showChoices,
|
|
1077
1099
|
sectionOrder,
|
|
1078
1100
|
showUsage
|
|
1079
|
-
}));
|
|
1101
|
+
})));
|
|
1080
1102
|
return onHelp(0, renderedDoc);
|
|
1081
1103
|
}
|
|
1082
1104
|
throw new RunParserError("Failed to generate help page.");
|
|
@@ -1142,7 +1164,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1142
1164
|
}, commandList, isTopLevel);
|
|
1143
1165
|
const defaultRootUsage = typeof usageLine === "function" && (options.help || options.version || options.completion) ? normalizeUsage(getRootHelpGeneratorParser().usage) : augmentedDoc.usage ?? [];
|
|
1144
1166
|
const renderedDoc = isTopLevel && usageLine != null ? applyUsageLine(augmentedDoc, usageLine, defaultRootUsage) : augmentedDoc;
|
|
1145
|
-
stderr(formatDocPage(programName, renderedDoc, {
|
|
1167
|
+
stderr(formatDocPage(programName, renderedDoc, formatOptions({
|
|
1146
1168
|
messageFormatter,
|
|
1147
1169
|
theme,
|
|
1148
1170
|
colors,
|
|
@@ -1152,21 +1174,24 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1152
1174
|
showChoices,
|
|
1153
1175
|
sectionOrder,
|
|
1154
1176
|
showUsage
|
|
1155
|
-
}));
|
|
1177
|
+
})));
|
|
1156
1178
|
}
|
|
1157
|
-
if (effectiveAboveError === "usage")
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1179
|
+
if (effectiveAboveError === "usage") {
|
|
1180
|
+
resolveUsageWidth(augmentedParser.usage);
|
|
1181
|
+
stderr(`${usageLabel()}${indentLines(formatUsage(programName, augmentedParser.usage, {
|
|
1182
|
+
theme,
|
|
1183
|
+
colors,
|
|
1184
|
+
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1185
|
+
expandCommands: true
|
|
1186
|
+
}), usageLabelWidth())}`);
|
|
1187
|
+
}
|
|
1188
|
+
stderr(renderErrorMessage(classified.error, formatOptions({
|
|
1164
1189
|
messageFormatter,
|
|
1165
1190
|
theme,
|
|
1166
1191
|
colors,
|
|
1167
1192
|
quotes: !colors,
|
|
1168
1193
|
maxWidth
|
|
1169
|
-
}));
|
|
1194
|
+
})));
|
|
1170
1195
|
return onError(1, classified.error);
|
|
1171
1196
|
};
|
|
1172
1197
|
if (aboveError === "help") {
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
2
|
const require_terminal = require('./terminal.cjs');
|
|
3
|
-
const require_message = require('./message.cjs');
|
|
4
3
|
const require_usage = require('./usage.cjs');
|
|
4
|
+
const require_message = require('./message.cjs');
|
|
5
5
|
const require_doc = require('./doc.cjs');
|
|
6
6
|
const require_internal_dependency = require('./internal/dependency.cjs');
|
|
7
7
|
const require_internal_parser = require('./internal/parser.cjs');
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAnnotations } from "./internal/annotations.js";
|
|
2
2
|
import { defaultTerminalTheme } from "./terminal.js";
|
|
3
|
-
import { commandLine, createMessageFormatter, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.js";
|
|
4
3
|
import { cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.js";
|
|
4
|
+
import { commandLine, createMessageFormatter, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.js";
|
|
5
5
|
import { cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.js";
|
|
6
6
|
import { dependency, deriveFrom, deriveFromAsync, deriveFromSync, getDependencySourceInfo, isDependencySource, isDerivedValueParser } from "./internal/dependency.js";
|
|
7
7
|
import { createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseDetailed, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
|
package/dist/internal/parser.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_internal_annotations = require('./annotations.cjs');
|
|
2
|
-
const require_message = require('../message.cjs');
|
|
3
2
|
const require_usage = require('../usage.cjs');
|
|
3
|
+
const require_message = require('../message.cjs');
|
|
4
4
|
const require_doc = require('../doc.cjs');
|
|
5
5
|
const require_mode_dispatch = require('./mode-dispatch.cjs');
|
|
6
6
|
const require_dependency_runtime = require('../dependency-runtime.cjs');
|
package/dist/internal/parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { hasMeaningfulAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./annotations.js";
|
|
2
|
-
import { cloneMessage, message } from "../message.js";
|
|
3
2
|
import { cloneUsage, normalizeUsage } from "../usage.js";
|
|
3
|
+
import { cloneMessage, message } from "../message.js";
|
|
4
4
|
import { cloneDocEntry, isDocEntryHidden } from "../doc.js";
|
|
5
5
|
import { dispatchByMode, dispatchParserByMode } from "./mode-dispatch.js";
|
|
6
6
|
import { collectExplicitSourceValues, collectExplicitSourceValuesAsync, createDependencyRuntimeContext } from "../dependency-runtime.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const require_displaywidth = require('../displaywidth.cjs');
|
|
2
2
|
const require_terminal_internal = require('../terminal-internal.cjs');
|
|
3
3
|
const require_text_layout = require('../text-layout.cjs');
|
|
4
|
+
const require_terminal_width = require('../terminal-width.cjs');
|
|
4
5
|
const require_message_renderer = require('../message-renderer.cjs');
|
|
5
6
|
|
|
6
7
|
exports.getDisplayWidth = require_displaywidth.getDisplayWidth;
|
|
@@ -9,4 +10,5 @@ exports.placeText = require_text_layout.placeText;
|
|
|
9
10
|
exports.renderErrorMessage = require_message_renderer.renderErrorMessage;
|
|
10
11
|
exports.renderTerminalTerm = require_terminal_internal.renderTerminalTerm;
|
|
11
12
|
exports.resolveMessageFormatter = require_message_renderer.resolveMessageFormatter;
|
|
12
|
-
exports.spaceAfterLabel = require_text_layout.spaceAfterLabel;
|
|
13
|
+
exports.spaceAfterLabel = require_text_layout.spaceAfterLabel;
|
|
14
|
+
exports.withAutomaticWidth = require_terminal_width.withAutomaticWidth;
|
|
@@ -2,4 +2,5 @@ import { getDisplayWidth } from "../displaywidth.cjs";
|
|
|
2
2
|
import { renderErrorMessage, resolveMessageFormatter } from "../message-renderer.cjs";
|
|
3
3
|
import { renderTerminalTerm } from "../terminal-internal.cjs";
|
|
4
4
|
import { measureText, placeText, spaceAfterLabel } from "../text-layout.cjs";
|
|
5
|
-
|
|
5
|
+
import { withAutomaticWidth } from "../terminal-width.cjs";
|
|
6
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel, withAutomaticWidth };
|
|
@@ -2,4 +2,5 @@ import { getDisplayWidth } from "../displaywidth.js";
|
|
|
2
2
|
import { renderErrorMessage, resolveMessageFormatter } from "../message-renderer.js";
|
|
3
3
|
import { renderTerminalTerm } from "../terminal-internal.js";
|
|
4
4
|
import { measureText, placeText, spaceAfterLabel } from "../text-layout.js";
|
|
5
|
-
|
|
5
|
+
import { withAutomaticWidth } from "../terminal-width.js";
|
|
6
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel, withAutomaticWidth };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getDisplayWidth } from "../displaywidth.js";
|
|
2
2
|
import { renderTerminalTerm } from "../terminal-internal.js";
|
|
3
3
|
import { measureText, placeText, spaceAfterLabel } from "../text-layout.js";
|
|
4
|
+
import { withAutomaticWidth } from "../terminal-width.js";
|
|
4
5
|
import { renderErrorMessage, resolveMessageFormatter } from "../message-renderer.js";
|
|
5
6
|
|
|
6
|
-
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel };
|
|
7
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel, withAutomaticWidth };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
const require_message_registry = require('./message-registry.cjs');
|
|
2
1
|
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
2
|
const require_text_layout = require('./text-layout.cjs');
|
|
3
|
+
const require_terminal_width = require('./terminal-width.cjs');
|
|
4
|
+
const require_message_registry = require('./message-registry.cjs');
|
|
4
5
|
const require_message = require('./message.cjs');
|
|
5
6
|
|
|
6
7
|
//#region src/message-renderer.ts
|
|
@@ -39,10 +40,19 @@ function renderErrorMessage(message, options = {}) {
|
|
|
39
40
|
if (!Number.isFinite(occupied) || !Number.isInteger(occupied)) throw new TypeError("Initial width must be a finite integer.");
|
|
40
41
|
if (occupied < 0) throw new RangeError("Initial width must be nonnegative.");
|
|
41
42
|
const colors = options.colors;
|
|
42
|
-
const
|
|
43
|
+
const label = require_text_layout.spaceAfterLabel(require_terminal_internal.renderTerminalTerm({
|
|
43
44
|
type: "errorLabel",
|
|
44
45
|
label: "Error:"
|
|
45
|
-
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0))
|
|
46
|
+
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0));
|
|
47
|
+
if (require_terminal_width.hasAutomaticWidth(options) && options.maxWidth != null) {
|
|
48
|
+
const size = require_text_layout.measureText(label);
|
|
49
|
+
if (options.maxWidth < Math.max(size.maxLineWidth, occupied + size.lastLineWidth + 1)) options = {
|
|
50
|
+
...options,
|
|
51
|
+
maxWidth: void 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
require_terminal_width.reportAutomaticWidth(options, options.maxWidth);
|
|
55
|
+
const prefix = require_text_layout.placeText(label, {
|
|
46
56
|
line: "",
|
|
47
57
|
column: occupied
|
|
48
58
|
}, options.maxWidth);
|
package/dist/message-renderer.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { messageRenderers } from "./message-registry.js";
|
|
2
1
|
import { renderTerminalTerm } from "./terminal-internal.js";
|
|
3
|
-
import { placeText, spaceAfterLabel } from "./text-layout.js";
|
|
2
|
+
import { measureText, placeText, spaceAfterLabel } from "./text-layout.js";
|
|
3
|
+
import { hasAutomaticWidth, reportAutomaticWidth } from "./terminal-width.js";
|
|
4
|
+
import { messageRenderers } from "./message-registry.js";
|
|
4
5
|
import { createMessageFormatter, formatMessage } from "./message.js";
|
|
5
6
|
|
|
6
7
|
//#region src/message-renderer.ts
|
|
@@ -39,10 +40,19 @@ function renderErrorMessage(message, options = {}) {
|
|
|
39
40
|
if (!Number.isFinite(occupied) || !Number.isInteger(occupied)) throw new TypeError("Initial width must be a finite integer.");
|
|
40
41
|
if (occupied < 0) throw new RangeError("Initial width must be nonnegative.");
|
|
41
42
|
const colors = options.colors;
|
|
42
|
-
const
|
|
43
|
+
const label = spaceAfterLabel(renderTerminalTerm({
|
|
43
44
|
type: "errorLabel",
|
|
44
45
|
label: "Error:"
|
|
45
|
-
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0))
|
|
46
|
+
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0));
|
|
47
|
+
if (hasAutomaticWidth(options) && options.maxWidth != null) {
|
|
48
|
+
const size = measureText(label);
|
|
49
|
+
if (options.maxWidth < Math.max(size.maxLineWidth, occupied + size.lastLineWidth + 1)) options = {
|
|
50
|
+
...options,
|
|
51
|
+
maxWidth: void 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
reportAutomaticWidth(options, options.maxWidth);
|
|
55
|
+
const prefix = placeText(label, {
|
|
46
56
|
line: "",
|
|
47
57
|
column: occupied
|
|
48
58
|
}, options.maxWidth);
|
package/dist/message.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_message_registry = require('./message-registry.cjs');
|
|
2
1
|
const require_displaywidth = require('./displaywidth.cjs');
|
|
3
2
|
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
|
+
const require_message_registry = require('./message-registry.cjs');
|
|
4
4
|
|
|
5
5
|
//#region src/message.ts
|
|
6
6
|
/**
|
package/dist/message.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { messageRenderers } from "./message-registry.js";
|
|
2
1
|
import { getDisplayWidth } from "./displaywidth.js";
|
|
3
2
|
import { formatTerminalTerm, fragmentTokens, serializeTokens } from "./terminal-internal.js";
|
|
3
|
+
import { messageRenderers } from "./message-registry.js";
|
|
4
4
|
|
|
5
5
|
//#region src/message.ts
|
|
6
6
|
/**
|
package/dist/primitives.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
|
-
const require_message = require('./message.cjs');
|
|
3
2
|
const require_validate = require('./validate.cjs');
|
|
4
3
|
const require_usage = require('./usage.cjs');
|
|
4
|
+
const require_message = require('./message.cjs');
|
|
5
5
|
const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
|
|
6
6
|
const require_internal_dependency = require('./internal/dependency.cjs');
|
|
7
7
|
const require_dependency_runtime = require('./dependency-runtime.cjs');
|
package/dist/primitives.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { annotateFreshArray, getAnnotations } from "./internal/annotations.js";
|
|
2
|
-
import { message, metavar, optionName, optionNames, text, valueSet } from "./message.js";
|
|
3
2
|
import { validateCommandNames, validateOptionNames } from "./validate.js";
|
|
4
3
|
import { extractOptionNames, isDocHidden, isSuggestionHidden } from "./usage.js";
|
|
4
|
+
import { message, metavar, optionName, optionNames, text, valueSet } from "./message.js";
|
|
5
5
|
import { dispatchByMode, dispatchIterableByMode, wrapForMode } from "./internal/mode-dispatch.js";
|
|
6
6
|
import { getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDerivedValueParser, suggestWithDependency } from "./internal/dependency.js";
|
|
7
7
|
import { effectfulSchedulingNodesKey, exclusiveSourceScopeKey, includeSourceFailureChain, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey } from "./dependency-runtime.js";
|
package/dist/suggestion.cjs
CHANGED
package/dist/suggestion.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { lineBreak, message, optionName, text, value } from "./message.js";
|
|
2
1
|
import { extractCommandNames, extractOptionNames, isSuggestionHidden } from "./usage.js";
|
|
2
|
+
import { lineBreak, message, optionName, text, value } from "./message.js";
|
|
3
3
|
|
|
4
4
|
//#region src/suggestion.ts
|
|
5
5
|
/**
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
2
|
+
const require_text_layout = require('./text-layout.cjs');
|
|
3
|
+
const require_usage = require('./usage.cjs');
|
|
4
|
+
|
|
5
|
+
//#region src/terminal-width.ts
|
|
6
|
+
const automaticWidth = Symbol.for("@optique/core/automaticWidth");
|
|
7
|
+
/**
|
|
8
|
+
* Marks runner options without changing their public type. The enumerable
|
|
9
|
+
* symbol survives the option copies made by Program and context runners.
|
|
10
|
+
* @param options The options whose width was automatically detected.
|
|
11
|
+
* @param onResolved Receives the effective width before message rendering.
|
|
12
|
+
* @returns A marked copy of the options.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
function withAutomaticWidth(options, onResolved = () => {}) {
|
|
16
|
+
return {
|
|
17
|
+
...options,
|
|
18
|
+
[automaticWidth]: onResolved
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Checks whether a width is a runner hint rather than an explicit constraint.
|
|
23
|
+
* @param options The formatting or runner options.
|
|
24
|
+
* @returns Whether automatic width fallback is enabled.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
function hasAutomaticWidth(options) {
|
|
28
|
+
return automaticWidth in options && typeof options[automaticWidth] === "function";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reports the resolved width before any opaque message formatter runs.
|
|
32
|
+
* @param options The marked formatting options.
|
|
33
|
+
* @param width The width selected by layout validation.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
function reportAutomaticWidth(options, width) {
|
|
37
|
+
if (automaticWidth in options && typeof options[automaticWidth] === "function") options[automaticWidth](width);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Measures the minimum usage layout, allowing long atomic terms to overflow.
|
|
41
|
+
* @param programName The program name shown in the usage line.
|
|
42
|
+
* @param usage The visible usage tree.
|
|
43
|
+
* @param label The rendered usage label, including its trailing space.
|
|
44
|
+
* @param theme The semantic terminal theme.
|
|
45
|
+
* @returns The minimum feasible width for the usage block.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
function minimumUsageWidth(programName, usage, label, theme) {
|
|
49
|
+
const labelWidth = require_text_layout.measureText(label).lastLineWidth;
|
|
50
|
+
const programWidth = Math.max(0, ...[...require_terminal_internal.fragmentTokens(require_terminal_internal.formatTerminalTerm({
|
|
51
|
+
type: "programName",
|
|
52
|
+
programName
|
|
53
|
+
}, theme))].map((token) => token.width));
|
|
54
|
+
const atomicWidth = usage.reduce((widest, term) => Math.max(widest, require_text_layout.measureText(require_usage.formatUsageTerm(term, {
|
|
55
|
+
theme,
|
|
56
|
+
maxWidth: 1
|
|
57
|
+
})).maxLineWidth), 0);
|
|
58
|
+
return Math.max(require_text_layout.measureText(label).maxLineWidth, labelWidth + Math.max(programWidth, Math.min(atomicWidth, programWidth + labelWidth)));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
exports.hasAutomaticWidth = hasAutomaticWidth;
|
|
63
|
+
exports.minimumUsageWidth = minimumUsageWidth;
|
|
64
|
+
exports.reportAutomaticWidth = reportAutomaticWidth;
|
|
65
|
+
exports.withAutomaticWidth = withAutomaticWidth;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/terminal-width.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Marks runner options without changing their public type. The enumerable
|
|
5
|
+
* symbol survives the option copies made by Program and context runners.
|
|
6
|
+
* @param options The options whose width was automatically detected.
|
|
7
|
+
* @param onResolved Receives the effective width before message rendering.
|
|
8
|
+
* @returns A marked copy of the options.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
declare function withAutomaticWidth<T extends object>(options: T, onResolved?: (width: number | undefined) => void): T;
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether a width is a runner hint rather than an explicit constraint.
|
|
14
|
+
* @param options The formatting or runner options.
|
|
15
|
+
* @returns Whether automatic width fallback is enabled.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
//#endregion
|
|
19
|
+
export { withAutomaticWidth };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/terminal-width.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Marks runner options without changing their public type. The enumerable
|
|
5
|
+
* symbol survives the option copies made by Program and context runners.
|
|
6
|
+
* @param options The options whose width was automatically detected.
|
|
7
|
+
* @param onResolved Receives the effective width before message rendering.
|
|
8
|
+
* @returns A marked copy of the options.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
declare function withAutomaticWidth<T extends object>(options: T, onResolved?: (width: number | undefined) => void): T;
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether a width is a runner hint rather than an explicit constraint.
|
|
14
|
+
* @param options The formatting or runner options.
|
|
15
|
+
* @returns Whether automatic width fallback is enabled.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
//#endregion
|
|
19
|
+
export { withAutomaticWidth };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { formatTerminalTerm, fragmentTokens } from "./terminal-internal.js";
|
|
2
|
+
import { measureText } from "./text-layout.js";
|
|
3
|
+
import { formatUsageTerm } from "./usage.js";
|
|
4
|
+
|
|
5
|
+
//#region src/terminal-width.ts
|
|
6
|
+
const automaticWidth = Symbol.for("@optique/core/automaticWidth");
|
|
7
|
+
/**
|
|
8
|
+
* Marks runner options without changing their public type. The enumerable
|
|
9
|
+
* symbol survives the option copies made by Program and context runners.
|
|
10
|
+
* @param options The options whose width was automatically detected.
|
|
11
|
+
* @param onResolved Receives the effective width before message rendering.
|
|
12
|
+
* @returns A marked copy of the options.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
function withAutomaticWidth(options, onResolved = () => {}) {
|
|
16
|
+
return {
|
|
17
|
+
...options,
|
|
18
|
+
[automaticWidth]: onResolved
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Checks whether a width is a runner hint rather than an explicit constraint.
|
|
23
|
+
* @param options The formatting or runner options.
|
|
24
|
+
* @returns Whether automatic width fallback is enabled.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
function hasAutomaticWidth(options) {
|
|
28
|
+
return automaticWidth in options && typeof options[automaticWidth] === "function";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reports the resolved width before any opaque message formatter runs.
|
|
32
|
+
* @param options The marked formatting options.
|
|
33
|
+
* @param width The width selected by layout validation.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
function reportAutomaticWidth(options, width) {
|
|
37
|
+
if (automaticWidth in options && typeof options[automaticWidth] === "function") options[automaticWidth](width);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Measures the minimum usage layout, allowing long atomic terms to overflow.
|
|
41
|
+
* @param programName The program name shown in the usage line.
|
|
42
|
+
* @param usage The visible usage tree.
|
|
43
|
+
* @param label The rendered usage label, including its trailing space.
|
|
44
|
+
* @param theme The semantic terminal theme.
|
|
45
|
+
* @returns The minimum feasible width for the usage block.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
function minimumUsageWidth(programName, usage, label, theme) {
|
|
49
|
+
const labelWidth = measureText(label).lastLineWidth;
|
|
50
|
+
const programWidth = Math.max(0, ...[...fragmentTokens(formatTerminalTerm({
|
|
51
|
+
type: "programName",
|
|
52
|
+
programName
|
|
53
|
+
}, theme))].map((token) => token.width));
|
|
54
|
+
const atomicWidth = usage.reduce((widest, term) => Math.max(widest, measureText(formatUsageTerm(term, {
|
|
55
|
+
theme,
|
|
56
|
+
maxWidth: 1
|
|
57
|
+
})).maxLineWidth), 0);
|
|
58
|
+
return Math.max(measureText(label).maxLineWidth, labelWidth + Math.max(programWidth, Math.min(atomicWidth, programWidth + labelWidth)));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { hasAutomaticWidth, minimumUsageWidth, reportAutomaticWidth, withAutomaticWidth };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/core",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.2567",
|
|
4
4
|
"description": "Type-safe combinatorial command-line interface parser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
},
|
|
238
238
|
"sideEffects": false,
|
|
239
239
|
"devDependencies": {
|
|
240
|
-
"@optique/env": "1.3.0-dev.
|
|
240
|
+
"@optique/env": "1.3.0-dev.2567+2ca0bc6e",
|
|
241
241
|
"@types/node": "^24.0.0",
|
|
242
242
|
"fast-check": "^4.7.0",
|
|
243
243
|
"tsdown": "^0.13.0",
|