@optique/core 1.3.0-dev.2524 → 1.3.0-dev.2530

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.
Files changed (42) hide show
  1. package/dist/doc.cjs +93 -84
  2. package/dist/doc.d.cts +12 -1
  3. package/dist/doc.d.ts +12 -1
  4. package/dist/doc.js +88 -79
  5. package/dist/facade.cjs +49 -15
  6. package/dist/facade.d.cts +12 -1
  7. package/dist/facade.d.ts +12 -1
  8. package/dist/facade.js +48 -14
  9. package/dist/index.cjs +3 -0
  10. package/dist/index.d.cts +3 -2
  11. package/dist/index.d.ts +3 -2
  12. package/dist/index.js +3 -2
  13. package/dist/internal/terminal.cjs +7 -0
  14. package/dist/internal/terminal.d.cts +4 -0
  15. package/dist/internal/terminal.d.ts +4 -0
  16. package/dist/internal/terminal.js +5 -0
  17. package/dist/message-registry.cjs +6 -0
  18. package/dist/message-registry.d.cts +7 -0
  19. package/dist/message-registry.d.ts +7 -0
  20. package/dist/message-registry.js +5 -0
  21. package/dist/message-renderer.cjs +26 -0
  22. package/dist/message-renderer.d.cts +19 -0
  23. package/dist/message-renderer.d.ts +19 -0
  24. package/dist/message-renderer.js +26 -0
  25. package/dist/message.cjs +49 -85
  26. package/dist/message.d.cts +31 -1
  27. package/dist/message.d.ts +31 -1
  28. package/dist/message.js +49 -86
  29. package/dist/terminal-internal.cjs +259 -0
  30. package/dist/terminal-internal.d.cts +36 -0
  31. package/dist/terminal-internal.d.ts +36 -0
  32. package/dist/terminal-internal.js +253 -0
  33. package/dist/terminal.cjs +74 -0
  34. package/dist/terminal.d.cts +129 -0
  35. package/dist/terminal.d.ts +129 -0
  36. package/dist/terminal.js +73 -0
  37. package/dist/usage.cjs +108 -134
  38. package/dist/usage.d.cts +6 -0
  39. package/dist/usage.d.ts +6 -0
  40. package/dist/usage.js +108 -134
  41. package/package.json +18 -2
  42. package/skills/optique/SKILL.md +3 -3
package/dist/doc.cjs CHANGED
@@ -1,5 +1,8 @@
1
+ const require_message_registry = require('./message-registry.cjs');
1
2
  const require_displaywidth = require('./displaywidth.cjs');
3
+ const require_terminal_internal = require('./terminal-internal.cjs');
2
4
  const require_message = require('./message.cjs');
5
+ const require_message_renderer = require('./message-renderer.cjs');
3
6
  const require_validate = require('./validate.cjs');
4
7
  const require_usage = require('./usage.cjs');
5
8
 
@@ -211,6 +214,46 @@ function defaultSectionOrder(a, b) {
211
214
  * ```
212
215
  */
213
216
  function formatDocPage(programName, page, options = {}) {
217
+ options = {
218
+ ...options,
219
+ theme: require_terminal_internal.cacheTerminalTheme(options.theme)
220
+ };
221
+ const formatMessage = require_message_renderer.resolveMessageFormatter(options);
222
+ const opaqueFormatter = options.messageFormatter != null && !require_message_registry.messageRenderers.has(options.messageFormatter);
223
+ const defaultAmbient = options.theme?.annotationStyles?.default ?? { dim: true };
224
+ const choicesAmbient = options.theme?.annotationStyles?.choices ?? { dim: true };
225
+ const labelCache = /* @__PURE__ */ new Map();
226
+ const label = (label$1, kind) => {
227
+ const key = `${kind}:${label$1}`;
228
+ let rendered = labelCache.get(key);
229
+ if (rendered == null) {
230
+ rendered = require_terminal_internal.renderTerminalTerm({
231
+ type: "label",
232
+ label: label$1,
233
+ kind
234
+ }, options.theme, options.colors, void 0, kind === "choices" ? choicesAmbient : void 0);
235
+ labelCache.set(key, rendered);
236
+ }
237
+ return rendered;
238
+ };
239
+ const punctuationCache = /* @__PURE__ */ new Map();
240
+ const punctuation = (punctuation$1, kind) => {
241
+ const key = `${kind}:${punctuation$1}`;
242
+ let rendered = punctuationCache.get(key);
243
+ if (rendered == null) {
244
+ rendered = require_terminal_internal.renderTerminalTerm({
245
+ type: "syntaxPunctuation",
246
+ punctuation: punctuation$1,
247
+ kind
248
+ }, options.theme, options.colors, void 0, kind.startsWith("default") ? defaultAmbient : kind.startsWith("choices") ? choicesAmbient : void 0);
249
+ punctuationCache.set(key, rendered);
250
+ }
251
+ return rendered;
252
+ };
253
+ const usageLabel = page.usage != null && options.showUsage !== false ? label("Usage:", "usage") + " " : "";
254
+ const usageLabelWidth = require_displaywidth.getDisplayWidth(usageLabel);
255
+ const defaultStyle = require_terminal_internal.styleCode(options.theme?.annotationStyles?.default ?? { dim: true });
256
+ const choicesStyle = require_terminal_internal.styleCode(options.theme?.annotationStyles?.choices ?? { dim: true });
214
257
  require_validate.validateProgramName(programName);
215
258
  const termIndent = options.termIndent ?? 2;
216
259
  const showUsage = options.showUsage ?? true;
@@ -238,6 +281,7 @@ function formatDocPage(programName, page, options = {}) {
238
281
  if (!needsDescriptionColumn(entry)) continue;
239
282
  const rendered = require_usage.formatUsageTerm(entry.term, {
240
283
  colors: options.colors,
284
+ theme: options.theme,
241
285
  optionsSeparator: ", ",
242
286
  context: "doc"
243
287
  });
@@ -260,24 +304,27 @@ function formatDocPage(programName, page, options = {}) {
260
304
  let minDescWidth = 1;
261
305
  if (needsDescColumn) {
262
306
  if (options.showDefault && page.sections.some((s) => s.entries.some((e) => hasContent(e.default)))) {
263
- const prefix = typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [";
307
+ const prefix = punctuation(typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [", "defaultPrefix");
264
308
  minDescWidth = Math.max(minDescWidth, require_displaywidth.getDisplayWidth(prefix));
265
309
  }
266
310
  if (options.showChoices && page.sections.some((s) => s.entries.some((e) => hasContent(e.choices)))) {
267
- const prefix = typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (";
268
- const label = typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ";
269
- minDescWidth = Math.max(minDescWidth, require_displaywidth.getDisplayWidth(prefix) + require_displaywidth.getDisplayWidth(label));
311
+ const prefix = punctuation(typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (", "choicesPrefix");
312
+ const choicesLabelText = label(typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ", "choices");
313
+ minDescWidth = Math.max(minDescWidth, require_displaywidth.getDisplayWidth(prefix) + require_displaywidth.getDisplayWidth(choicesLabelText));
270
314
  }
271
315
  }
272
316
  const splitEntryMin = termIndent + 2 + Math.max(2, 2 * minDescWidth - 1);
273
317
  const fixedEntryMin = termIndent + 2 + termWidth + minDescWidth;
274
318
  const entryMin = needsDescColumn ? Math.min(splitEntryMin, fixedEntryMin) : hasEntries ? termIndent + 1 : 1;
275
- const programNameWidth = require_displaywidth.getDisplayWidth(programName);
276
- const usageMin = page.usage != null && showUsage ? 7 + Math.max(programNameWidth, Math.min(maxVisibleAtomicWidth(page.usage), programNameWidth + 7)) : 1;
319
+ const programNameWidth = page.usage != null && showUsage ? Math.max(0, ...[...require_terminal_internal.fragmentTokens(require_terminal_internal.formatTerminalTerm({
320
+ type: "programName",
321
+ programName
322
+ }, options.theme))].map((token) => token.width)) : 0;
323
+ const usageMin = page.usage != null && showUsage ? usageLabelWidth + Math.max(programNameWidth, Math.min(maxVisibleAtomicWidth(page.usage, options.theme), programNameWidth + usageLabelWidth)) : 1;
277
324
  let sectionMin = 1;
278
- if (hasContent(page.examples)) sectionMin = Math.max(sectionMin, 9);
279
- if (hasContent(page.author)) sectionMin = Math.max(sectionMin, 7);
280
- if (hasContent(page.bugs)) sectionMin = Math.max(sectionMin, 5);
325
+ if (hasContent(page.examples)) sectionMin = Math.max(sectionMin, require_displaywidth.getDisplayWidth(label("Examples:", "examples")));
326
+ if (hasContent(page.author)) sectionMin = Math.max(sectionMin, require_displaywidth.getDisplayWidth(label("Author:", "author")));
327
+ if (hasContent(page.bugs)) sectionMin = Math.max(sectionMin, require_displaywidth.getDisplayWidth(label("Bugs:", "bugs")));
281
328
  const minWidth = Math.max(entryMin, usageMin, sectionMin);
282
329
  if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
283
330
  if (needsDescColumn && minDescWidth > 1) {
@@ -291,7 +338,7 @@ function formatDocPage(programName, page, options = {}) {
291
338
  }
292
339
  let output = "";
293
340
  if (hasContent(page.brief)) {
294
- output += require_message.formatMessage(page.brief, {
341
+ output += formatMessage(page.brief, {
295
342
  colors: options.colors,
296
343
  maxWidth: options.maxWidth,
297
344
  quotes: !options.colors
@@ -299,18 +346,18 @@ function formatDocPage(programName, page, options = {}) {
299
346
  output += "\n";
300
347
  }
301
348
  if (page.usage != null && showUsage) {
302
- const usageLabel = options.colors ? "\x1B[1;2mUsage:\x1B[0m " : "Usage: ";
303
349
  output += usageLabel;
304
350
  output += indentLines(require_usage.formatUsage(programName, page.usage, {
305
351
  colors: options.colors,
306
- maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - 7,
352
+ theme: options.theme,
353
+ maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - usageLabelWidth,
307
354
  expandCommands: true
308
- }), 7);
355
+ }), usageLabelWidth);
309
356
  output += "\n";
310
357
  }
311
358
  if (hasContent(page.description)) {
312
359
  output += "\n";
313
- output += require_message.formatMessage(page.description, {
360
+ output += formatMessage(page.description, {
314
361
  colors: options.colors,
315
362
  maxWidth: options.maxWidth,
316
363
  quotes: !options.colors
@@ -331,12 +378,13 @@ function formatDocPage(programName, page, options = {}) {
331
378
  output += "\n";
332
379
  if (section.title != null) {
333
380
  require_validate.validateLabel(section.title);
334
- const sectionLabel = options.colors ? `\x1b[1;2m${section.title}:\x1b[0m\n` : `${section.title}:\n`;
381
+ const sectionLabel = label(`${section.title}:`, "section") + "\n";
335
382
  output += sectionLabel;
336
383
  }
337
384
  for (const entry of section.entries) {
338
385
  const term = require_usage.formatUsageTerm(entry.term, {
339
386
  colors: options.colors,
387
+ theme: options.theme,
340
388
  optionsSeparator: ", ",
341
389
  context: "doc",
342
390
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - termIndent
@@ -349,12 +397,12 @@ function formatDocPage(programName, page, options = {}) {
349
397
  colors: options.colors,
350
398
  quotes: !options.colors,
351
399
  maxWidth: descColumnWidth,
352
- startWidth: extraTermOffset > 0 ? extraTermOffset : void 0
400
+ initialWidth: extraTermOffset > 0 ? extraTermOffset : void 0
353
401
  };
354
- let description = entry.description == null ? "" : require_message.formatMessage(entry.description, descFormatOptions);
402
+ let description = entry.description == null ? "" : formatMessage(entry.description, descFormatOptions);
355
403
  if (options.showDefault && hasContent(entry.default)) {
356
- const prefix = typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [";
357
- const suffix = typeof options.showDefault === "object" ? options.showDefault.suffix ?? "]" : "]";
404
+ const prefix = punctuation(typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [", "defaultPrefix");
405
+ const suffix = punctuation(typeof options.showDefault === "object" ? options.showDefault.suffix ?? "]" : "]", "defaultSuffix");
358
406
  const prefixWidth = require_displaywidth.getDisplayWidth(prefix);
359
407
  const suffixWidth = require_displaywidth.getDisplayWidth(suffix);
360
408
  let defaultStartWidth;
@@ -367,20 +415,20 @@ function formatDocPage(programName, page, options = {}) {
367
415
  } else defaultStartWidth = effectiveLastW + prefixWidth;
368
416
  }
369
417
  const defaultFormatOptions = {
370
- colors: options.colors ? { resetSuffix: "\x1B[2m" } : false,
418
+ colors: options.colors ? { resetSuffix: defaultStyle } : false,
371
419
  quotes: !options.colors,
372
420
  maxWidth: descColumnWidth == null ? void 0 : descColumnWidth - suffixWidth,
373
- startWidth: defaultStartWidth
421
+ initialWidth: defaultStartWidth
374
422
  };
375
- const defaultContent = require_message.formatMessage(entry.default, defaultFormatOptions);
376
- const defaultText = `${prefix}${defaultContent}${suffix}`;
377
- const formattedDefault = options.colors ? `\x1b[2m${defaultText}\x1b[0m` : defaultText;
423
+ const defaultContent = formatMessage(entry.default, defaultFormatOptions, options.theme?.annotationStyles?.default ?? { dim: true });
424
+ const defaultText = `${prefix}${defaultContent}${opaqueFormatter && options.colors ? defaultStyle : ""}${suffix}`;
425
+ const formattedDefault = options.colors ? `${defaultStyle}${defaultText}${defaultStyle ? "\x1B[0m" : ""}` : defaultText;
378
426
  description += formattedDefault;
379
427
  }
380
428
  if (options.showChoices && hasContent(entry.choices)) {
381
- const prefix = typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (";
382
- const suffix = typeof options.showChoices === "object" ? options.showChoices.suffix ?? ")" : ")";
383
- const label = typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ";
429
+ const prefix = punctuation(typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (", "choicesPrefix");
430
+ const suffix = punctuation(typeof options.showChoices === "object" ? options.showChoices.suffix ?? ")" : ")", "choicesSuffix");
431
+ const choicesLabelText = label(typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ", "choices");
384
432
  const maxItems = typeof options.showChoices === "object" ? options.showChoices.maxItems ?? 8 : 8;
385
433
  const terms = Array.isArray(entry.choices) ? entry.choices : [];
386
434
  let truncatedTerms = terms;
@@ -400,7 +448,7 @@ function formatDocPage(programName, page, options = {}) {
400
448
  }
401
449
  const choicesPrefixWidth = require_displaywidth.getDisplayWidth(prefix);
402
450
  const choicesSuffixWidth = require_displaywidth.getDisplayWidth(suffix);
403
- const choicesLabelWidth = require_displaywidth.getDisplayWidth(label);
451
+ const choicesLabelWidth = require_displaywidth.getDisplayWidth(choicesLabelText);
404
452
  let choicesStartWidth;
405
453
  if (descColumnWidth != null) {
406
454
  const lastW = lastLineVisibleLength(description);
@@ -412,14 +460,14 @@ function formatDocPage(programName, page, options = {}) {
412
460
  } else choicesStartWidth = effectiveLastW + prefixLabelLen;
413
461
  }
414
462
  const choicesFormatOptions = {
415
- colors: options.colors ? { resetSuffix: "\x1B[2m" } : false,
463
+ colors: options.colors ? { resetSuffix: choicesStyle } : false,
416
464
  quotes: false,
417
465
  maxWidth: descColumnWidth == null ? void 0 : descColumnWidth - choicesSuffixWidth,
418
- startWidth: choicesStartWidth
466
+ initialWidth: choicesStartWidth
419
467
  };
420
- const choicesDisplay = require_message.formatMessage(truncatedTerms, choicesFormatOptions);
421
- const choicesText = `${prefix}${label}${choicesDisplay}${suffix}`;
422
- const formattedChoices = options.colors ? `\x1b[2m${choicesText}\x1b[0m` : choicesText;
468
+ const choicesDisplay = formatMessage(truncatedTerms, choicesFormatOptions, options.theme?.annotationStyles?.choices ?? { dim: true });
469
+ const choicesText = `${prefix}${choicesLabelText}${choicesDisplay}${opaqueFormatter && options.colors ? choicesStyle : ""}${suffix}`;
470
+ const formattedChoices = options.colors ? `${choicesStyle}${choicesText}${choicesStyle ? "\x1B[0m" : ""}` : choicesText;
423
471
  description += formattedChoices;
424
472
  }
425
473
  output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, effectiveTermWidth)}${description === "" ? "" : ` ${indentLines(description, termIndent + effectiveTermWidth + 2)}`}\n`;
@@ -427,9 +475,9 @@ function formatDocPage(programName, page, options = {}) {
427
475
  }
428
476
  if (hasContent(page.examples)) {
429
477
  output += "\n";
430
- const examplesLabel = options.colors ? "\x1B[1;2mExamples:\x1B[0m\n" : "Examples:\n";
478
+ const examplesLabel = label("Examples:", "examples") + "\n";
431
479
  output += examplesLabel;
432
- const examplesContent = require_message.formatMessage(page.examples, {
480
+ const examplesContent = formatMessage(page.examples, {
433
481
  colors: options.colors,
434
482
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - 2,
435
483
  quotes: !options.colors
@@ -439,9 +487,9 @@ function formatDocPage(programName, page, options = {}) {
439
487
  }
440
488
  if (hasContent(page.author)) {
441
489
  output += "\n";
442
- const authorLabel = options.colors ? "\x1B[1;2mAuthor:\x1B[0m\n" : "Author:\n";
490
+ const authorLabel = label("Author:", "author") + "\n";
443
491
  output += authorLabel;
444
- const authorContent = require_message.formatMessage(page.author, {
492
+ const authorContent = formatMessage(page.author, {
445
493
  colors: options.colors,
446
494
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - 2,
447
495
  quotes: !options.colors
@@ -451,9 +499,9 @@ function formatDocPage(programName, page, options = {}) {
451
499
  }
452
500
  if (hasContent(page.bugs)) {
453
501
  output += "\n";
454
- const bugsLabel = options.colors ? "\x1B[1;2mBugs:\x1B[0m\n" : "Bugs:\n";
502
+ const bugsLabel = label("Bugs:", "bugs") + "\n";
455
503
  output += bugsLabel;
456
- const bugsContent = require_message.formatMessage(page.bugs, {
504
+ const bugsContent = formatMessage(page.bugs, {
457
505
  colors: options.colors,
458
506
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - 2,
459
507
  quotes: !options.colors
@@ -463,7 +511,7 @@ function formatDocPage(programName, page, options = {}) {
463
511
  }
464
512
  if (hasContent(page.footer)) {
465
513
  output += "\n";
466
- output += require_message.formatMessage(page.footer, {
514
+ output += formatMessage(page.footer, {
467
515
  colors: options.colors,
468
516
  maxWidth: options.maxWidth,
469
517
  quotes: !options.colors
@@ -480,50 +528,11 @@ function indentLines(text$1, indent) {
480
528
  * because they are filtered out before rendering, so they do not
481
529
  * contribute to the rendered width.
482
530
  */
483
- function maxVisibleAtomicWidth(usage) {
484
- let max = 0;
485
- for (const term of usage) switch (term.type) {
486
- case "argument":
487
- if (!require_usage.isUsageHidden(term.hidden)) max = Math.max(max, require_displaywidth.getDisplayWidth(term.metavar));
488
- break;
489
- case "option":
490
- if (!require_usage.isUsageHidden(term.hidden) && term.names.length > 0) {
491
- for (const name of term.names) max = Math.max(max, require_displaywidth.getDisplayWidth(name));
492
- if (term.metavar != null) max = Math.max(max, require_displaywidth.getDisplayWidth(term.metavar));
493
- }
494
- break;
495
- case "command":
496
- if (!require_usage.isUsageHidden(term.hidden)) max = Math.max(max, require_displaywidth.getDisplayWidth(term.name));
497
- break;
498
- case "passthrough":
499
- if (!require_usage.isUsageHidden(term.hidden)) max = Math.max(max, 5);
500
- break;
501
- case "optional":
502
- max = Math.max(max, maxVisibleAtomicWidth(term.terms));
503
- break;
504
- case "multiple": {
505
- const innerMax = maxVisibleAtomicWidth(term.terms);
506
- if (innerMax > 0) max = Math.max(max, 3, innerMax);
507
- break;
508
- }
509
- case "exclusive":
510
- for (const branch of term.terms) {
511
- const first = branch[0];
512
- if (first?.type === "command" && require_usage.isUsageHidden(first.hidden)) continue;
513
- max = Math.max(max, maxVisibleAtomicWidth(branch));
514
- }
515
- break;
516
- case "sequence":
517
- max = Math.max(max, maxVisibleAtomicWidth(term.terms));
518
- break;
519
- case "literal":
520
- if (term.value !== "") max = Math.max(max, require_displaywidth.getDisplayWidth(term.value));
521
- break;
522
- case "ellipsis":
523
- max = Math.max(max, 3);
524
- break;
525
- }
526
- return max;
531
+ function maxVisibleAtomicWidth(usage, theme) {
532
+ return Math.max(0, ...usage.flatMap((term) => require_usage.formatUsageTerm(term, {
533
+ theme,
534
+ maxWidth: 1
535
+ }).split("\n").map(require_displaywidth.getDisplayWidth)));
527
536
  }
528
537
  function ansiAwareRightPad(text$1, length, char = " ") {
529
538
  const visibleWidth = lastLineVisibleLength(text$1);
package/dist/doc.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import { Message } from "./message.cjs";
1
+ import { Message, MessageFormatter } from "./message.cjs";
2
+ import { TerminalTheme } from "./terminal.cjs";
2
3
  import { Usage, UsageTerm } from "./usage.cjs";
3
4
 
4
5
  //#region src/doc.d.ts
@@ -206,6 +207,16 @@ interface ShowChoicesOptions {
206
207
  * Options for formatting a documentation page.
207
208
  */
208
209
  interface DocPageFormatOptions {
210
+ /**
211
+ * Custom message renderer, taking precedence over theme for messages.
212
+ * @since 1.3.0
213
+ */
214
+ readonly messageFormatter?: MessageFormatter;
215
+ /**
216
+ * Semantic terminal theme.
217
+ * @since 1.3.0
218
+ */
219
+ readonly theme?: TerminalTheme;
209
220
  /**
210
221
  * Whether to include ANSI color codes in the output.
211
222
  * @default `false`
package/dist/doc.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Message } from "./message.js";
1
+ import { Message, MessageFormatter } from "./message.js";
2
+ import { TerminalTheme } from "./terminal.js";
2
3
  import { Usage, UsageTerm } from "./usage.js";
3
4
 
4
5
  //#region src/doc.d.ts
@@ -206,6 +207,16 @@ interface ShowChoicesOptions {
206
207
  * Options for formatting a documentation page.
207
208
  */
208
209
  interface DocPageFormatOptions {
210
+ /**
211
+ * Custom message renderer, taking precedence over theme for messages.
212
+ * @since 1.3.0
213
+ */
214
+ readonly messageFormatter?: MessageFormatter;
215
+ /**
216
+ * Semantic terminal theme.
217
+ * @since 1.3.0
218
+ */
219
+ readonly theme?: TerminalTheme;
209
220
  /**
210
221
  * Whether to include ANSI color codes in the output.
211
222
  * @default `false`