@optique/core 1.3.0-dev.2542 → 1.3.0-dev.2558
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/displaywidth.cjs +12 -2
- package/dist/displaywidth.d.cts +8 -1
- package/dist/displaywidth.d.ts +8 -1
- package/dist/displaywidth.js +11 -2
- package/dist/doc.cjs +63 -83
- package/dist/doc.js +63 -83
- package/dist/facade.cjs +26 -44
- package/dist/facade.js +27 -45
- package/dist/internal/terminal.cjs +6 -1
- package/dist/internal/terminal.d.cts +3 -2
- package/dist/internal/terminal.d.ts +3 -2
- package/dist/internal/terminal.js +3 -2
- package/dist/message-renderer.cjs +34 -0
- package/dist/message-renderer.d.cts +16 -1
- package/dist/message-renderer.d.ts +16 -1
- package/dist/message-renderer.js +34 -1
- package/dist/terminal-internal.cjs +43 -16
- package/dist/terminal-internal.d.cts +22 -2
- package/dist/terminal-internal.d.ts +22 -2
- package/dist/terminal-internal.js +43 -17
- package/dist/text-layout.cjs +87 -0
- package/dist/text-layout.d.cts +54 -0
- package/dist/text-layout.d.ts +54 -0
- package/dist/text-layout.js +84 -0
- package/dist/usage.cjs +72 -37
- package/dist/usage.js +73 -38
- package/package.json +2 -2
package/dist/facade.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
|
-
const require_displaywidth = require('./displaywidth.cjs');
|
|
3
2
|
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
|
+
const require_text_layout = require('./text-layout.cjs');
|
|
4
4
|
const require_message = require('./message.cjs');
|
|
5
5
|
const require_message_renderer = require('./message-renderer.cjs');
|
|
6
6
|
const require_validate = require('./validate.cjs');
|
|
@@ -517,27 +517,19 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
|
|
|
517
517
|
* @since 0.6.0
|
|
518
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
|
-
const formatMessage = require_message_renderer.resolveMessageFormatter({
|
|
521
|
-
messageFormatter,
|
|
522
|
-
theme
|
|
523
|
-
});
|
|
524
|
-
const errorLabel = () => require_terminal_internal.renderTerminalTerm({
|
|
525
|
-
type: "errorLabel",
|
|
526
|
-
label: "Error:"
|
|
527
|
-
}, theme, colors) + " ";
|
|
528
520
|
const shellName = completionArgs[0] || "";
|
|
529
521
|
const args = completionArgs.slice(1);
|
|
530
522
|
const callOnError = (code, error) => onError(code, error);
|
|
531
523
|
const callOnCompletion = (code) => onCompletion(code);
|
|
532
524
|
if (!shellName) {
|
|
533
525
|
const error = require_message.message`Missing shell name for completion.`;
|
|
534
|
-
|
|
535
|
-
|
|
526
|
+
stderr(require_message_renderer.renderErrorMessage(error, {
|
|
527
|
+
messageFormatter,
|
|
528
|
+
theme,
|
|
536
529
|
colors,
|
|
537
530
|
quotes: !colors,
|
|
538
|
-
maxWidth
|
|
539
|
-
|
|
540
|
-
})}\n`);
|
|
531
|
+
maxWidth
|
|
532
|
+
}) + "\n");
|
|
541
533
|
if (completionParser) {
|
|
542
534
|
const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
|
|
543
535
|
const doc = require_internal_parser.getDocPage(completionParser, [displayName]);
|
|
@@ -565,13 +557,13 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
565
557
|
available.push(require_message.value(name));
|
|
566
558
|
}
|
|
567
559
|
const error = require_message.message`Unsupported shell ${shellName}. Available shells: ${available}.`;
|
|
568
|
-
|
|
569
|
-
|
|
560
|
+
stderr(require_message_renderer.renderErrorMessage(error, {
|
|
561
|
+
messageFormatter,
|
|
562
|
+
theme,
|
|
570
563
|
colors,
|
|
571
564
|
quotes: !colors,
|
|
572
|
-
maxWidth
|
|
573
|
-
|
|
574
|
-
})}`);
|
|
565
|
+
maxWidth
|
|
566
|
+
}));
|
|
575
567
|
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
576
568
|
const result = callOnError(1, error);
|
|
577
569
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -882,21 +874,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
882
874
|
const { colors, messageFormatter, theme, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
883
875
|
throw new RunParserError("Failed to parse command line arguments.");
|
|
884
876
|
}, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
|
|
885
|
-
const formatMessage = require_message_renderer.resolveMessageFormatter({
|
|
886
|
-
messageFormatter,
|
|
887
|
-
theme
|
|
888
|
-
});
|
|
889
|
-
const errorLabel = () => require_terminal_internal.renderTerminalTerm({
|
|
890
|
-
type: "errorLabel",
|
|
891
|
-
label: "Error:"
|
|
892
|
-
}, theme, colors) + " ";
|
|
893
877
|
let usagePrefix;
|
|
894
|
-
const usageLabel = () => usagePrefix ??= require_terminal_internal.renderTerminalTerm({
|
|
878
|
+
const usageLabel = () => usagePrefix ??= require_text_layout.spaceAfterLabel(require_terminal_internal.renderTerminalTerm({
|
|
895
879
|
type: "label",
|
|
896
880
|
label: "Usage:",
|
|
897
881
|
kind: "usageSummary"
|
|
898
|
-
}, theme, colors)
|
|
899
|
-
const usageLabelWidth = () =>
|
|
882
|
+
}, theme, colors));
|
|
883
|
+
const usageLabelWidth = () => require_text_layout.measureText(usageLabel()).lastLineWidth;
|
|
900
884
|
const norm = (c) => c === true ? {} : c;
|
|
901
885
|
const helpCommandConfig = norm(options.help?.command);
|
|
902
886
|
const helpOptionConfig = norm(options.help?.option);
|
|
@@ -1057,14 +1041,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1057
1041
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1058
1042
|
expandCommands: true
|
|
1059
1043
|
}), usageLabelWidth())}`);
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
maxWidth,
|
|
1044
|
+
stderr(require_message_renderer.renderErrorMessage(validationError, {
|
|
1045
|
+
messageFormatter,
|
|
1046
|
+
theme,
|
|
1064
1047
|
colors,
|
|
1065
|
-
quotes: !colors
|
|
1066
|
-
|
|
1067
|
-
|
|
1048
|
+
quotes: !colors,
|
|
1049
|
+
maxWidth
|
|
1050
|
+
}));
|
|
1068
1051
|
return onError(1, validationError);
|
|
1069
1052
|
};
|
|
1070
1053
|
const displayHelp = (doc) => {
|
|
@@ -1177,14 +1160,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1177
1160
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1178
1161
|
expandCommands: true
|
|
1179
1162
|
}), usageLabelWidth())}`);
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
maxWidth,
|
|
1163
|
+
stderr(require_message_renderer.renderErrorMessage(classified.error, {
|
|
1164
|
+
messageFormatter,
|
|
1165
|
+
theme,
|
|
1184
1166
|
colors,
|
|
1185
|
-
quotes: !colors
|
|
1186
|
-
|
|
1187
|
-
|
|
1167
|
+
quotes: !colors,
|
|
1168
|
+
maxWidth
|
|
1169
|
+
}));
|
|
1188
1170
|
return onError(1, classified.error);
|
|
1189
1171
|
};
|
|
1190
1172
|
if (aboveError === "help") {
|
package/dist/facade.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { injectAnnotations } from "./internal/annotations.js";
|
|
2
|
-
import { getDisplayWidth } from "./displaywidth.js";
|
|
3
2
|
import { renderTerminalTerm } from "./terminal-internal.js";
|
|
3
|
+
import { measureText, spaceAfterLabel } from "./text-layout.js";
|
|
4
4
|
import { commandLine, lineBreak, message, optionName, text, value } from "./message.js";
|
|
5
|
-
import {
|
|
5
|
+
import { renderErrorMessage } from "./message-renderer.js";
|
|
6
6
|
import { validateCommandNames, validateContextIds, validateMetaNameCollisions, validateOptionNames, validateProgramName } from "./validate.js";
|
|
7
7
|
import { cloneUsage, formatUsage, isSuggestionHidden, normalizeUsage } from "./usage.js";
|
|
8
8
|
import { formatDocPage } from "./doc.js";
|
|
@@ -517,27 +517,19 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
|
|
|
517
517
|
* @since 0.6.0
|
|
518
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
|
-
const formatMessage = resolveMessageFormatter({
|
|
521
|
-
messageFormatter,
|
|
522
|
-
theme
|
|
523
|
-
});
|
|
524
|
-
const errorLabel = () => renderTerminalTerm({
|
|
525
|
-
type: "errorLabel",
|
|
526
|
-
label: "Error:"
|
|
527
|
-
}, theme, colors) + " ";
|
|
528
520
|
const shellName = completionArgs[0] || "";
|
|
529
521
|
const args = completionArgs.slice(1);
|
|
530
522
|
const callOnError = (code, error) => onError(code, error);
|
|
531
523
|
const callOnCompletion = (code) => onCompletion(code);
|
|
532
524
|
if (!shellName) {
|
|
533
525
|
const error = message`Missing shell name for completion.`;
|
|
534
|
-
|
|
535
|
-
|
|
526
|
+
stderr(renderErrorMessage(error, {
|
|
527
|
+
messageFormatter,
|
|
528
|
+
theme,
|
|
536
529
|
colors,
|
|
537
530
|
quotes: !colors,
|
|
538
|
-
maxWidth
|
|
539
|
-
|
|
540
|
-
})}\n`);
|
|
531
|
+
maxWidth
|
|
532
|
+
}) + "\n");
|
|
541
533
|
if (completionParser) {
|
|
542
534
|
const displayName = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
|
|
543
535
|
const doc = getDocPage(completionParser, [displayName]);
|
|
@@ -565,13 +557,13 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
565
557
|
available.push(value(name));
|
|
566
558
|
}
|
|
567
559
|
const error = message`Unsupported shell ${shellName}. Available shells: ${available}.`;
|
|
568
|
-
|
|
569
|
-
|
|
560
|
+
stderr(renderErrorMessage(error, {
|
|
561
|
+
messageFormatter,
|
|
562
|
+
theme,
|
|
570
563
|
colors,
|
|
571
564
|
quotes: !colors,
|
|
572
|
-
maxWidth
|
|
573
|
-
|
|
574
|
-
})}`);
|
|
565
|
+
maxWidth
|
|
566
|
+
}));
|
|
575
567
|
return dispatchByMode(parser.mode, () => {
|
|
576
568
|
const result = callOnError(1, error);
|
|
577
569
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
@@ -882,21 +874,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
882
874
|
const { colors, messageFormatter, theme, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
|
|
883
875
|
throw new RunParserError("Failed to parse command line arguments.");
|
|
884
876
|
}, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
|
|
885
|
-
const formatMessage = resolveMessageFormatter({
|
|
886
|
-
messageFormatter,
|
|
887
|
-
theme
|
|
888
|
-
});
|
|
889
|
-
const errorLabel = () => renderTerminalTerm({
|
|
890
|
-
type: "errorLabel",
|
|
891
|
-
label: "Error:"
|
|
892
|
-
}, theme, colors) + " ";
|
|
893
877
|
let usagePrefix;
|
|
894
|
-
const usageLabel = () => usagePrefix ??= renderTerminalTerm({
|
|
878
|
+
const usageLabel = () => usagePrefix ??= spaceAfterLabel(renderTerminalTerm({
|
|
895
879
|
type: "label",
|
|
896
880
|
label: "Usage:",
|
|
897
881
|
kind: "usageSummary"
|
|
898
|
-
}, theme, colors)
|
|
899
|
-
const usageLabelWidth = () =>
|
|
882
|
+
}, theme, colors));
|
|
883
|
+
const usageLabelWidth = () => measureText(usageLabel()).lastLineWidth;
|
|
900
884
|
const norm = (c) => c === true ? {} : c;
|
|
901
885
|
const helpCommandConfig = norm(options.help?.command);
|
|
902
886
|
const helpOptionConfig = norm(options.help?.option);
|
|
@@ -1057,14 +1041,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1057
1041
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1058
1042
|
expandCommands: true
|
|
1059
1043
|
}), usageLabelWidth())}`);
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
maxWidth,
|
|
1044
|
+
stderr(renderErrorMessage(validationError, {
|
|
1045
|
+
messageFormatter,
|
|
1046
|
+
theme,
|
|
1064
1047
|
colors,
|
|
1065
|
-
quotes: !colors
|
|
1066
|
-
|
|
1067
|
-
|
|
1048
|
+
quotes: !colors,
|
|
1049
|
+
maxWidth
|
|
1050
|
+
}));
|
|
1068
1051
|
return onError(1, validationError);
|
|
1069
1052
|
};
|
|
1070
1053
|
const displayHelp = (doc) => {
|
|
@@ -1177,14 +1160,13 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
1177
1160
|
maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
|
|
1178
1161
|
expandCommands: true
|
|
1179
1162
|
}), usageLabelWidth())}`);
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
maxWidth,
|
|
1163
|
+
stderr(renderErrorMessage(classified.error, {
|
|
1164
|
+
messageFormatter,
|
|
1165
|
+
theme,
|
|
1184
1166
|
colors,
|
|
1185
|
-
quotes: !colors
|
|
1186
|
-
|
|
1187
|
-
|
|
1167
|
+
quotes: !colors,
|
|
1168
|
+
maxWidth
|
|
1169
|
+
}));
|
|
1188
1170
|
return onError(1, classified.error);
|
|
1189
1171
|
};
|
|
1190
1172
|
if (aboveError === "help") {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
const require_displaywidth = require('../displaywidth.cjs');
|
|
2
2
|
const require_terminal_internal = require('../terminal-internal.cjs');
|
|
3
|
+
const require_text_layout = require('../text-layout.cjs');
|
|
3
4
|
const require_message_renderer = require('../message-renderer.cjs');
|
|
4
5
|
|
|
5
6
|
exports.getDisplayWidth = require_displaywidth.getDisplayWidth;
|
|
7
|
+
exports.measureText = require_text_layout.measureText;
|
|
8
|
+
exports.placeText = require_text_layout.placeText;
|
|
9
|
+
exports.renderErrorMessage = require_message_renderer.renderErrorMessage;
|
|
6
10
|
exports.renderTerminalTerm = require_terminal_internal.renderTerminalTerm;
|
|
7
|
-
exports.resolveMessageFormatter = require_message_renderer.resolveMessageFormatter;
|
|
11
|
+
exports.resolveMessageFormatter = require_message_renderer.resolveMessageFormatter;
|
|
12
|
+
exports.spaceAfterLabel = require_text_layout.spaceAfterLabel;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDisplayWidth } from "../displaywidth.cjs";
|
|
2
|
-
import { resolveMessageFormatter } from "../message-renderer.cjs";
|
|
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
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDisplayWidth } from "../displaywidth.js";
|
|
2
|
-
import { resolveMessageFormatter } from "../message-renderer.js";
|
|
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
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getDisplayWidth } from "../displaywidth.js";
|
|
2
2
|
import { renderTerminalTerm } from "../terminal-internal.js";
|
|
3
|
-
import {
|
|
3
|
+
import { measureText, placeText, spaceAfterLabel } from "../text-layout.js";
|
|
4
|
+
import { renderErrorMessage, resolveMessageFormatter } from "../message-renderer.js";
|
|
4
5
|
|
|
5
|
-
export { getDisplayWidth, renderTerminalTerm, resolveMessageFormatter };
|
|
6
|
+
export { getDisplayWidth, measureText, placeText, renderErrorMessage, renderTerminalTerm, resolveMessageFormatter, spaceAfterLabel };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const require_message_registry = require('./message-registry.cjs');
|
|
2
|
+
const require_terminal_internal = require('./terminal-internal.cjs');
|
|
3
|
+
const require_text_layout = require('./text-layout.cjs');
|
|
2
4
|
const require_message = require('./message.cjs');
|
|
3
5
|
|
|
4
6
|
//#region src/message-renderer.ts
|
|
@@ -21,6 +23,38 @@ function resolveMessageFormatter(options) {
|
|
|
21
23
|
});
|
|
22
24
|
};
|
|
23
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Assembles a themed error prefix and a message at one layout boundary.
|
|
28
|
+
* Callers own streams, trailing newlines, and the default quoting policy.
|
|
29
|
+
* Opaque formatter output is appended unchanged, including empty output.
|
|
30
|
+
* @param message The original, unprefixed error message.
|
|
31
|
+
* @param options Theme, formatter, and physical-line layout options.
|
|
32
|
+
* @returns The prefixed message without an added trailing newline.
|
|
33
|
+
* @throws {TypeError} If initialWidth is not a finite integer.
|
|
34
|
+
* @throws {RangeError} If initialWidth is negative or a theme color is invalid.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
function renderErrorMessage(message, options = {}) {
|
|
38
|
+
const occupied = options.initialWidth ?? 0;
|
|
39
|
+
if (!Number.isFinite(occupied) || !Number.isInteger(occupied)) throw new TypeError("Initial width must be a finite integer.");
|
|
40
|
+
if (occupied < 0) throw new RangeError("Initial width must be nonnegative.");
|
|
41
|
+
const colors = options.colors;
|
|
42
|
+
const prefix = require_text_layout.placeText(require_text_layout.spaceAfterLabel(require_terminal_internal.renderTerminalTerm({
|
|
43
|
+
type: "errorLabel",
|
|
44
|
+
label: "Error:"
|
|
45
|
+
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0)), {
|
|
46
|
+
line: "",
|
|
47
|
+
column: occupied
|
|
48
|
+
}, options.maxWidth);
|
|
49
|
+
const formatted = resolveMessageFormatter(options)(message, {
|
|
50
|
+
colors,
|
|
51
|
+
quotes: options.quotes,
|
|
52
|
+
maxWidth: options.maxWidth,
|
|
53
|
+
initialWidth: prefix.cursor.column
|
|
54
|
+
});
|
|
55
|
+
return prefix.text + formatted;
|
|
56
|
+
}
|
|
24
57
|
|
|
25
58
|
//#endregion
|
|
59
|
+
exports.renderErrorMessage = renderErrorMessage;
|
|
26
60
|
exports.resolveMessageFormatter = resolveMessageFormatter;
|
|
@@ -15,5 +15,20 @@ declare function resolveMessageFormatter(options: {
|
|
|
15
15
|
readonly messageFormatter?: MessageFormatter;
|
|
16
16
|
readonly theme?: TerminalTheme;
|
|
17
17
|
}): (message: Message, options?: MessageFormatOptions, ambient?: TerminalStyle) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Assembles a themed error prefix and a message at one layout boundary.
|
|
20
|
+
* Callers own streams, trailing newlines, and the default quoting policy.
|
|
21
|
+
* Opaque formatter output is appended unchanged, including empty output.
|
|
22
|
+
* @param message The original, unprefixed error message.
|
|
23
|
+
* @param options Theme, formatter, and physical-line layout options.
|
|
24
|
+
* @returns The prefixed message without an added trailing newline.
|
|
25
|
+
* @throws {TypeError} If initialWidth is not a finite integer.
|
|
26
|
+
* @throws {RangeError} If initialWidth is negative or a theme color is invalid.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
declare function renderErrorMessage(message: Message, options?: MessageFormatOptions & {
|
|
30
|
+
readonly theme?: TerminalTheme;
|
|
31
|
+
readonly messageFormatter?: MessageFormatter;
|
|
32
|
+
}): string;
|
|
18
33
|
//#endregion
|
|
19
|
-
export { resolveMessageFormatter };
|
|
34
|
+
export { renderErrorMessage, resolveMessageFormatter };
|
|
@@ -15,5 +15,20 @@ declare function resolveMessageFormatter(options: {
|
|
|
15
15
|
readonly messageFormatter?: MessageFormatter;
|
|
16
16
|
readonly theme?: TerminalTheme;
|
|
17
17
|
}): (message: Message, options?: MessageFormatOptions, ambient?: TerminalStyle) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Assembles a themed error prefix and a message at one layout boundary.
|
|
20
|
+
* Callers own streams, trailing newlines, and the default quoting policy.
|
|
21
|
+
* Opaque formatter output is appended unchanged, including empty output.
|
|
22
|
+
* @param message The original, unprefixed error message.
|
|
23
|
+
* @param options Theme, formatter, and physical-line layout options.
|
|
24
|
+
* @returns The prefixed message without an added trailing newline.
|
|
25
|
+
* @throws {TypeError} If initialWidth is not a finite integer.
|
|
26
|
+
* @throws {RangeError} If initialWidth is negative or a theme color is invalid.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
declare function renderErrorMessage(message: Message, options?: MessageFormatOptions & {
|
|
30
|
+
readonly theme?: TerminalTheme;
|
|
31
|
+
readonly messageFormatter?: MessageFormatter;
|
|
32
|
+
}): string;
|
|
18
33
|
//#endregion
|
|
19
|
-
export { resolveMessageFormatter };
|
|
34
|
+
export { renderErrorMessage, resolveMessageFormatter };
|
package/dist/message-renderer.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { messageRenderers } from "./message-registry.js";
|
|
2
|
+
import { renderTerminalTerm } from "./terminal-internal.js";
|
|
3
|
+
import { placeText, spaceAfterLabel } from "./text-layout.js";
|
|
2
4
|
import { createMessageFormatter, formatMessage } from "./message.js";
|
|
3
5
|
|
|
4
6
|
//#region src/message-renderer.ts
|
|
@@ -21,6 +23,37 @@ function resolveMessageFormatter(options) {
|
|
|
21
23
|
});
|
|
22
24
|
};
|
|
23
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Assembles a themed error prefix and a message at one layout boundary.
|
|
28
|
+
* Callers own streams, trailing newlines, and the default quoting policy.
|
|
29
|
+
* Opaque formatter output is appended unchanged, including empty output.
|
|
30
|
+
* @param message The original, unprefixed error message.
|
|
31
|
+
* @param options Theme, formatter, and physical-line layout options.
|
|
32
|
+
* @returns The prefixed message without an added trailing newline.
|
|
33
|
+
* @throws {TypeError} If initialWidth is not a finite integer.
|
|
34
|
+
* @throws {RangeError} If initialWidth is negative or a theme color is invalid.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
function renderErrorMessage(message, options = {}) {
|
|
38
|
+
const occupied = options.initialWidth ?? 0;
|
|
39
|
+
if (!Number.isFinite(occupied) || !Number.isInteger(occupied)) throw new TypeError("Initial width must be a finite integer.");
|
|
40
|
+
if (occupied < 0) throw new RangeError("Initial width must be nonnegative.");
|
|
41
|
+
const colors = options.colors;
|
|
42
|
+
const prefix = placeText(spaceAfterLabel(renderTerminalTerm({
|
|
43
|
+
type: "errorLabel",
|
|
44
|
+
label: "Error:"
|
|
45
|
+
}, options.theme, typeof colors === "object" ? true : colors, void 0, void 0, typeof colors === "object" ? colors.resetSuffix : void 0)), {
|
|
46
|
+
line: "",
|
|
47
|
+
column: occupied
|
|
48
|
+
}, options.maxWidth);
|
|
49
|
+
const formatted = resolveMessageFormatter(options)(message, {
|
|
50
|
+
colors,
|
|
51
|
+
quotes: options.quotes,
|
|
52
|
+
maxWidth: options.maxWidth,
|
|
53
|
+
initialWidth: prefix.cursor.column
|
|
54
|
+
});
|
|
55
|
+
return prefix.text + formatted;
|
|
56
|
+
}
|
|
24
57
|
|
|
25
58
|
//#endregion
|
|
26
|
-
export { resolveMessageFormatter };
|
|
59
|
+
export { renderErrorMessage, resolveMessageFormatter };
|
|
@@ -17,11 +17,29 @@ function valuesFormatter(theme) {
|
|
|
17
17
|
children: [require_terminal.defaultTerminalTheme.values(term, context)]
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
+
/** Default callback identity survives any number of per-pass caches. */
|
|
21
|
+
const defaultFormatters = new WeakSet(Object.values(require_terminal.defaultTerminalTheme).filter((value) => typeof value === "function"));
|
|
20
22
|
function formatTerminalTerm(term, theme = {}, quotes = false, usage) {
|
|
23
|
+
return formatTerminalLeaf(term, theme, quotes, usage).fragment;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Renders a semantic leaf and records the selected callback's provenance.
|
|
27
|
+
* @param term The semantic leaf to render.
|
|
28
|
+
* @param theme The optional role overrides.
|
|
29
|
+
* @param quotes Whether values should use their quoted representation.
|
|
30
|
+
* @param usage The leaf's position within a usage expression.
|
|
31
|
+
* @returns The fragment and whether its callback has default origin.
|
|
32
|
+
* @throws {TypeError} If the term is invalid or is a message-level hard break.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
function formatTerminalLeaf(term, theme = {}, quotes = false, usage) {
|
|
21
36
|
const quote = (s) => quotes ? `\`${s}\`` : s;
|
|
22
37
|
let text;
|
|
23
38
|
switch (term.type) {
|
|
24
|
-
case "text": return
|
|
39
|
+
case "text": return {
|
|
40
|
+
fragment: terminalText(term.text),
|
|
41
|
+
defaultOrigin: true
|
|
42
|
+
};
|
|
25
43
|
case "lineBreak": throw new TypeError("Hard breaks must be rendered at the message level.");
|
|
26
44
|
case "optionName":
|
|
27
45
|
text = quote(term.optionName);
|
|
@@ -65,19 +83,25 @@ function formatTerminalTerm(term, theme = {}, quotes = false, usage) {
|
|
|
65
83
|
usage,
|
|
66
84
|
format: (child) => formatTerminalTerm(child, theme, quotes, usage)
|
|
67
85
|
};
|
|
86
|
+
function render(formatter, value) {
|
|
87
|
+
return {
|
|
88
|
+
fragment: formatter(value, ctx),
|
|
89
|
+
defaultOrigin: defaultFormatters.has(formatter)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
68
92
|
switch (term.type) {
|
|
69
|
-
case "optionName": return (theme.optionName ?? require_terminal.defaultTerminalTheme.optionName
|
|
70
|
-
case "optionNames": return (theme.optionNames ?? require_terminal.defaultTerminalTheme.optionNames
|
|
71
|
-
case "metavar": return (theme.metavar ?? require_terminal.defaultTerminalTheme.metavar
|
|
72
|
-
case "value": return (theme.value ?? require_terminal.defaultTerminalTheme.value
|
|
73
|
-
case "values": return valuesFormatter(theme)
|
|
74
|
-
case "envVar": return (theme.envVar ?? require_terminal.defaultTerminalTheme.envVar
|
|
75
|
-
case "commandLine": return (theme.commandLine ?? require_terminal.defaultTerminalTheme.commandLine
|
|
76
|
-
case "url": return (theme.url ?? require_terminal.defaultTerminalTheme.url
|
|
77
|
-
case "programName": return (theme.programName ?? require_terminal.defaultTerminalTheme.programName
|
|
78
|
-
case "label": return (theme.label ?? require_terminal.defaultTerminalTheme.label
|
|
79
|
-
case "syntaxPunctuation": return (theme.syntaxPunctuation ?? require_terminal.defaultTerminalTheme.syntaxPunctuation
|
|
80
|
-
case "errorLabel": return (theme.errorLabel ?? require_terminal.defaultTerminalTheme.errorLabel
|
|
93
|
+
case "optionName": return render(theme.optionName ?? require_terminal.defaultTerminalTheme.optionName, term);
|
|
94
|
+
case "optionNames": return render(theme.optionNames ?? require_terminal.defaultTerminalTheme.optionNames, term);
|
|
95
|
+
case "metavar": return render(theme.metavar ?? require_terminal.defaultTerminalTheme.metavar, term);
|
|
96
|
+
case "value": return render(theme.value ?? require_terminal.defaultTerminalTheme.value, term);
|
|
97
|
+
case "values": return render(valuesFormatter(theme), term);
|
|
98
|
+
case "envVar": return render(theme.envVar ?? require_terminal.defaultTerminalTheme.envVar, term);
|
|
99
|
+
case "commandLine": return render(theme.commandLine ?? require_terminal.defaultTerminalTheme.commandLine, term);
|
|
100
|
+
case "url": return render(theme.url ?? require_terminal.defaultTerminalTheme.url, term);
|
|
101
|
+
case "programName": return render(theme.programName ?? require_terminal.defaultTerminalTheme.programName, term);
|
|
102
|
+
case "label": return render(theme.label ?? require_terminal.defaultTerminalTheme.label, term);
|
|
103
|
+
case "syntaxPunctuation": return render(theme.syntaxPunctuation ?? require_terminal.defaultTerminalTheme.syntaxPunctuation, term);
|
|
104
|
+
case "errorLabel": return render(theme.errorLabel ?? require_terminal.defaultTerminalTheme.errorLabel, term);
|
|
81
105
|
}
|
|
82
106
|
}
|
|
83
107
|
const colorNames = [
|
|
@@ -225,14 +249,14 @@ function serializeTokens(tokens, colors = false, resetSuffix = "", ambient = {})
|
|
|
225
249
|
* @since 1.3.0
|
|
226
250
|
* @internal
|
|
227
251
|
*/
|
|
228
|
-
function renderTerminalTerm(term, theme, colors, usage, ambient) {
|
|
229
|
-
return serializeTokens(fragmentTokens(formatTerminalTerm(term, theme, false, usage)), colors,
|
|
252
|
+
function renderTerminalTerm(term, theme, colors, usage, ambient, resetSuffix = "") {
|
|
253
|
+
return serializeTokens(fragmentTokens(formatTerminalTerm(term, theme, false, usage)), colors, resetSuffix, ambient);
|
|
230
254
|
}
|
|
231
255
|
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
232
256
|
function cacheTerminalTheme(theme = {}) {
|
|
233
257
|
function cache(formatter) {
|
|
234
258
|
const fragments = /* @__PURE__ */ new Map();
|
|
235
|
-
|
|
259
|
+
const cached = (term, context) => {
|
|
236
260
|
const key = JSON.stringify([
|
|
237
261
|
term,
|
|
238
262
|
context.quotes,
|
|
@@ -245,6 +269,8 @@ function cacheTerminalTheme(theme = {}) {
|
|
|
245
269
|
}
|
|
246
270
|
return fragment;
|
|
247
271
|
};
|
|
272
|
+
if (defaultFormatters.has(formatter)) defaultFormatters.add(cached);
|
|
273
|
+
return cached;
|
|
248
274
|
}
|
|
249
275
|
return {
|
|
250
276
|
optionName: cache(theme.optionName ?? require_terminal.defaultTerminalTheme.optionName),
|
|
@@ -268,6 +294,7 @@ function cacheTerminalTheme(theme = {}) {
|
|
|
268
294
|
|
|
269
295
|
//#endregion
|
|
270
296
|
exports.cacheTerminalTheme = cacheTerminalTheme;
|
|
297
|
+
exports.formatTerminalLeaf = formatTerminalLeaf;
|
|
271
298
|
exports.formatTerminalTerm = formatTerminalTerm;
|
|
272
299
|
exports.fragmentTokens = fragmentTokens;
|
|
273
300
|
exports.renderTerminalTerm = renderTerminalTerm;
|
|
@@ -10,9 +10,29 @@ interface TerminalToken {
|
|
|
10
10
|
readonly text: string;
|
|
11
11
|
readonly width: number;
|
|
12
12
|
readonly scopes: readonly Scope[];
|
|
13
|
+
/** Layout-owned space, removable beside an explicit hard break. */
|
|
14
|
+
readonly separator?: boolean;
|
|
15
|
+
/** The historical program separator wraps before its following atom. */
|
|
16
|
+
readonly programBoundary?: boolean;
|
|
17
|
+
/** Enables only the legacy default formatter whitespace behavior. */
|
|
18
|
+
readonly legacyWhitespace?: boolean;
|
|
13
19
|
}
|
|
14
20
|
declare function terminalText(text: string): TerminalFragment;
|
|
15
21
|
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
22
|
+
/**
|
|
23
|
+
* Renders a semantic leaf and records the selected callback's provenance.
|
|
24
|
+
* @param term The semantic leaf to render.
|
|
25
|
+
* @param theme The optional role overrides.
|
|
26
|
+
* @param quotes Whether values should use their quoted representation.
|
|
27
|
+
* @param usage The leaf's position within a usage expression.
|
|
28
|
+
* @returns The fragment and whether its callback has default origin.
|
|
29
|
+
* @throws {TypeError} If the term is invalid or is a message-level hard break.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
declare function formatTerminalLeaf(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): {
|
|
33
|
+
readonly fragment: TerminalFragment;
|
|
34
|
+
readonly defaultOrigin: boolean;
|
|
35
|
+
};
|
|
16
36
|
declare function styleCode(style: TerminalStyle): string;
|
|
17
37
|
declare function fragmentTokens(fragment: TerminalFragment, scopes?: readonly Scope[], inherited?: TerminalStyle): Generator<TerminalToken>;
|
|
18
38
|
declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boolean, resetSuffix?: string, ambient?: TerminalStyle): string;
|
|
@@ -29,8 +49,8 @@ declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boole
|
|
|
29
49
|
* @since 1.3.0
|
|
30
50
|
* @internal
|
|
31
51
|
*/
|
|
32
|
-
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle): string;
|
|
52
|
+
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle, resetSuffix?: string): string;
|
|
33
53
|
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
34
54
|
declare function cacheTerminalTheme(theme?: TerminalTheme): TerminalTheme;
|
|
35
55
|
//#endregion
|
|
36
|
-
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|
|
56
|
+
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalLeaf, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|
|
@@ -10,9 +10,29 @@ interface TerminalToken {
|
|
|
10
10
|
readonly text: string;
|
|
11
11
|
readonly width: number;
|
|
12
12
|
readonly scopes: readonly Scope[];
|
|
13
|
+
/** Layout-owned space, removable beside an explicit hard break. */
|
|
14
|
+
readonly separator?: boolean;
|
|
15
|
+
/** The historical program separator wraps before its following atom. */
|
|
16
|
+
readonly programBoundary?: boolean;
|
|
17
|
+
/** Enables only the legacy default formatter whitespace behavior. */
|
|
18
|
+
readonly legacyWhitespace?: boolean;
|
|
13
19
|
}
|
|
14
20
|
declare function terminalText(text: string): TerminalFragment;
|
|
15
21
|
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
22
|
+
/**
|
|
23
|
+
* Renders a semantic leaf and records the selected callback's provenance.
|
|
24
|
+
* @param term The semantic leaf to render.
|
|
25
|
+
* @param theme The optional role overrides.
|
|
26
|
+
* @param quotes Whether values should use their quoted representation.
|
|
27
|
+
* @param usage The leaf's position within a usage expression.
|
|
28
|
+
* @returns The fragment and whether its callback has default origin.
|
|
29
|
+
* @throws {TypeError} If the term is invalid or is a message-level hard break.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
declare function formatTerminalLeaf(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): {
|
|
33
|
+
readonly fragment: TerminalFragment;
|
|
34
|
+
readonly defaultOrigin: boolean;
|
|
35
|
+
};
|
|
16
36
|
declare function styleCode(style: TerminalStyle): string;
|
|
17
37
|
declare function fragmentTokens(fragment: TerminalFragment, scopes?: readonly Scope[], inherited?: TerminalStyle): Generator<TerminalToken>;
|
|
18
38
|
declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boolean, resetSuffix?: string, ambient?: TerminalStyle): string;
|
|
@@ -29,8 +49,8 @@ declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boole
|
|
|
29
49
|
* @since 1.3.0
|
|
30
50
|
* @internal
|
|
31
51
|
*/
|
|
32
|
-
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle): string;
|
|
52
|
+
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle, resetSuffix?: string): string;
|
|
33
53
|
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
34
54
|
declare function cacheTerminalTheme(theme?: TerminalTheme): TerminalTheme;
|
|
35
55
|
//#endregion
|
|
36
|
-
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|
|
56
|
+
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalLeaf, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|