@optique/core 1.3.0-dev.2380 → 1.3.0-dev.2383

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.
@@ -130,7 +130,8 @@ function isDeferredCompletionResult(result) {
130
130
  function settledPreCompletedKeys(preCompleted) {
131
131
  const keys = /* @__PURE__ */ new Set();
132
132
  for (const [key, result] of preCompleted) {
133
- if (isDeferredCompletionResult(result)) continue;
133
+ const completion = require_internal_dependency.isDependencySourceState(result) ? result.result : result;
134
+ if (isDeferredCompletionResult(completion)) continue;
134
135
  keys.add(key);
135
136
  }
136
137
  return keys;
@@ -145,7 +146,10 @@ function settledPreCompletedKeys(preCompleted) {
145
146
  * immediately.
146
147
  */
147
148
  function firstPreCompletedFailure(preCompleted) {
148
- for (const result of preCompleted.values()) if (typeof result === "object" && result !== null && "success" in result && result.success === false && "error" in result) return result.error;
149
+ for (const result of preCompleted.values()) {
150
+ const completion = require_internal_dependency.isDependencySourceState(result) ? result.result : result;
151
+ if (typeof completion === "object" && completion !== null && "success" in completion && completion.success === false && "error" in completion) return completion.error;
152
+ }
149
153
  return void 0;
150
154
  }
151
155
  async function scheduleEffectfulSourceCompletions(nodes, state, runtime, exec, preCompleted, demandNodes) {
@@ -130,7 +130,8 @@ function isDeferredCompletionResult(result) {
130
130
  function settledPreCompletedKeys(preCompleted) {
131
131
  const keys = /* @__PURE__ */ new Set();
132
132
  for (const [key, result] of preCompleted) {
133
- if (isDeferredCompletionResult(result)) continue;
133
+ const completion = isDependencySourceState(result) ? result.result : result;
134
+ if (isDeferredCompletionResult(completion)) continue;
134
135
  keys.add(key);
135
136
  }
136
137
  return keys;
@@ -145,7 +146,10 @@ function settledPreCompletedKeys(preCompleted) {
145
146
  * immediately.
146
147
  */
147
148
  function firstPreCompletedFailure(preCompleted) {
148
- for (const result of preCompleted.values()) if (typeof result === "object" && result !== null && "success" in result && result.success === false && "error" in result) return result.error;
149
+ for (const result of preCompleted.values()) {
150
+ const completion = isDependencySourceState(result) ? result.result : result;
151
+ if (typeof completion === "object" && completion !== null && "success" in completion && completion.success === false && "error" in completion) return completion.error;
152
+ }
149
153
  return void 0;
150
154
  }
151
155
  async function scheduleEffectfulSourceCompletions(nodes, state, runtime, exec, preCompleted, demandNodes) {
@@ -679,15 +679,7 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
679
679
  * length-prefixed segments so no separator escaping is needed.
680
680
  */
681
681
  function serializeSchedulingPath(path) {
682
- return path.map((segment) => {
683
- if (typeof segment === "symbol") {
684
- const key = stableSymbolKey(segment);
685
- return `y${key.length}:${key}`;
686
- }
687
- const tag = typeof segment === "number" ? "n" : "s";
688
- const text = String(segment);
689
- return `${tag}${text.length}:${text}`;
690
- }).join("");
682
+ return path.map(serializePathSegment).join("");
691
683
  }
692
684
  /**
693
685
  * Checks if a value is a plain object (not a class instance) for the
@@ -679,15 +679,7 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
679
679
  * length-prefixed segments so no separator escaping is needed.
680
680
  */
681
681
  function serializeSchedulingPath(path) {
682
- return path.map((segment) => {
683
- if (typeof segment === "symbol") {
684
- const key = stableSymbolKey(segment);
685
- return `y${key.length}:${key}`;
686
- }
687
- const tag = typeof segment === "number" ? "n" : "s";
688
- const text = String(segment);
689
- return `${tag}${text.length}:${text}`;
690
- }).join("");
682
+ return path.map(serializePathSegment).join("");
691
683
  }
692
684
  /**
693
685
  * Checks if a value is a plain object (not a class instance) for the
package/dist/doc.cjs CHANGED
@@ -213,7 +213,6 @@ function defaultSectionOrder(a, b) {
213
213
  function formatDocPage(programName, page, options = {}) {
214
214
  require_validate.validateProgramName(programName);
215
215
  const termIndent = options.termIndent ?? 2;
216
- const termWidth = options.termWidth ?? 26;
217
216
  const showUsage = options.showUsage ?? true;
218
217
  if (options.maxWidth != null && (!Number.isFinite(options.maxWidth) || !Number.isInteger(options.maxWidth))) throw new TypeError(`maxWidth must be a finite integer, got ${options.maxWidth}.`);
219
218
  const filteredSections = page.sections.map((s) => ({
@@ -232,9 +231,32 @@ function formatDocPage(programName, page, options = {}) {
232
231
  if (maxItems < 1) throw new RangeError(`showChoices.maxItems must be at least 1, but got ${maxItems}.`);
233
232
  }
234
233
  const hasContent = (msg) => Array.isArray(msg) && msg.length > 0;
234
+ const needsDescriptionColumn = (entry) => hasContent(entry.description) || (options.showDefault === true || typeof options.showDefault === "object") && hasContent(entry.default) || (options.showChoices === true || typeof options.showChoices === "object") && hasContent(entry.choices);
235
+ const automaticTermWidth = () => {
236
+ let widest;
237
+ for (const section of page.sections) for (const entry of section.entries) {
238
+ if (!needsDescriptionColumn(entry)) continue;
239
+ const rendered = require_usage.formatUsageTerm(entry.term, {
240
+ colors: options.colors,
241
+ optionsSeparator: ", ",
242
+ context: "doc"
243
+ });
244
+ const width = Math.max(...rendered.split("\n").map((line) => require_displaywidth.getDisplayWidth(line)));
245
+ widest = widest == null ? width : Math.max(widest, width);
246
+ }
247
+ return widest;
248
+ };
249
+ const termWidth = options.termWidth === "auto" ? automaticTermWidth() ?? 26 : options.termWidth ?? 26;
250
+ const hasEntries = page.sections.some((s) => s.entries.length > 0);
251
+ const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some(needsDescriptionColumn));
252
+ let effectiveTermWidth;
253
+ if (options.maxWidth == null) effectiveTermWidth = termWidth;
254
+ else {
255
+ const availableForColumns = options.maxWidth - termIndent - 2;
256
+ const evenlySplitTermWidth = Math.max(1, Math.floor(availableForColumns / 2));
257
+ effectiveTermWidth = options.termWidth === "auto" && needsDescColumn ? Math.min(termWidth, evenlySplitTermWidth) : availableForColumns >= termWidth + 1 ? termWidth : evenlySplitTermWidth;
258
+ }
235
259
  if (options.maxWidth != null) {
236
- const hasEntries = page.sections.some((s) => s.entries.length > 0);
237
- const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && hasContent(e.default) || options.showChoices && hasContent(e.choices)));
238
260
  let minDescWidth = 1;
239
261
  if (needsDescColumn) {
240
262
  if (options.showDefault && page.sections.some((s) => s.entries.some((e) => hasContent(e.default)))) {
@@ -260,20 +282,13 @@ function formatDocPage(programName, page, options = {}) {
260
282
  if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
261
283
  if (needsDescColumn && minDescWidth > 1) {
262
284
  const avail = options.maxWidth - termIndent - 2;
263
- const effTW = avail >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(avail / 2));
264
- const descW = avail - effTW;
285
+ const descW = avail - effectiveTermWidth;
265
286
  if (descW < minDescWidth) {
266
- const needed = termIndent + termWidth + 2 + minDescWidth;
287
+ const needed = termIndent + effectiveTermWidth + 2 + minDescWidth;
267
288
  throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
268
289
  }
269
290
  }
270
291
  }
271
- let effectiveTermWidth;
272
- if (options.maxWidth == null) effectiveTermWidth = termWidth;
273
- else {
274
- const availableForColumns = options.maxWidth - termIndent - 2;
275
- effectiveTermWidth = availableForColumns >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(availableForColumns / 2));
276
- }
277
292
  let output = "";
278
293
  if (hasContent(page.brief)) {
279
294
  output += require_message.formatMessage(page.brief, {
package/dist/doc.d.cts CHANGED
@@ -217,10 +217,14 @@ interface DocPageFormatOptions {
217
217
  */
218
218
  termIndent?: number;
219
219
  /**
220
- * Width allocated for terms before descriptions start.
220
+ * Width allocated for terms before descriptions start. Set to `"auto"`
221
+ * to align descriptions after the widest visible term that has content.
222
+ * Terminal display width is used for automatic measurement.
223
+ *
221
224
  * @default `26`
225
+ * @since 1.3.0 Added automatic term width.
222
226
  */
223
- termWidth?: number;
227
+ termWidth?: number | "auto";
224
228
  /**
225
229
  * Maximum width of the entire formatted output.
226
230
  */
package/dist/doc.d.ts CHANGED
@@ -217,10 +217,14 @@ interface DocPageFormatOptions {
217
217
  */
218
218
  termIndent?: number;
219
219
  /**
220
- * Width allocated for terms before descriptions start.
220
+ * Width allocated for terms before descriptions start. Set to `"auto"`
221
+ * to align descriptions after the widest visible term that has content.
222
+ * Terminal display width is used for automatic measurement.
223
+ *
221
224
  * @default `26`
225
+ * @since 1.3.0 Added automatic term width.
222
226
  */
223
- termWidth?: number;
227
+ termWidth?: number | "auto";
224
228
  /**
225
229
  * Maximum width of the entire formatted output.
226
230
  */
package/dist/doc.js CHANGED
@@ -213,7 +213,6 @@ function defaultSectionOrder(a, b) {
213
213
  function formatDocPage(programName, page, options = {}) {
214
214
  validateProgramName(programName);
215
215
  const termIndent = options.termIndent ?? 2;
216
- const termWidth = options.termWidth ?? 26;
217
216
  const showUsage = options.showUsage ?? true;
218
217
  if (options.maxWidth != null && (!Number.isFinite(options.maxWidth) || !Number.isInteger(options.maxWidth))) throw new TypeError(`maxWidth must be a finite integer, got ${options.maxWidth}.`);
219
218
  const filteredSections = page.sections.map((s) => ({
@@ -232,9 +231,32 @@ function formatDocPage(programName, page, options = {}) {
232
231
  if (maxItems < 1) throw new RangeError(`showChoices.maxItems must be at least 1, but got ${maxItems}.`);
233
232
  }
234
233
  const hasContent = (msg) => Array.isArray(msg) && msg.length > 0;
234
+ const needsDescriptionColumn = (entry) => hasContent(entry.description) || (options.showDefault === true || typeof options.showDefault === "object") && hasContent(entry.default) || (options.showChoices === true || typeof options.showChoices === "object") && hasContent(entry.choices);
235
+ const automaticTermWidth = () => {
236
+ let widest;
237
+ for (const section of page.sections) for (const entry of section.entries) {
238
+ if (!needsDescriptionColumn(entry)) continue;
239
+ const rendered = formatUsageTerm(entry.term, {
240
+ colors: options.colors,
241
+ optionsSeparator: ", ",
242
+ context: "doc"
243
+ });
244
+ const width = Math.max(...rendered.split("\n").map((line) => getDisplayWidth(line)));
245
+ widest = widest == null ? width : Math.max(widest, width);
246
+ }
247
+ return widest;
248
+ };
249
+ const termWidth = options.termWidth === "auto" ? automaticTermWidth() ?? 26 : options.termWidth ?? 26;
250
+ const hasEntries = page.sections.some((s) => s.entries.length > 0);
251
+ const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some(needsDescriptionColumn));
252
+ let effectiveTermWidth;
253
+ if (options.maxWidth == null) effectiveTermWidth = termWidth;
254
+ else {
255
+ const availableForColumns = options.maxWidth - termIndent - 2;
256
+ const evenlySplitTermWidth = Math.max(1, Math.floor(availableForColumns / 2));
257
+ effectiveTermWidth = options.termWidth === "auto" && needsDescColumn ? Math.min(termWidth, evenlySplitTermWidth) : availableForColumns >= termWidth + 1 ? termWidth : evenlySplitTermWidth;
258
+ }
235
259
  if (options.maxWidth != null) {
236
- const hasEntries = page.sections.some((s) => s.entries.length > 0);
237
- const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && hasContent(e.default) || options.showChoices && hasContent(e.choices)));
238
260
  let minDescWidth = 1;
239
261
  if (needsDescColumn) {
240
262
  if (options.showDefault && page.sections.some((s) => s.entries.some((e) => hasContent(e.default)))) {
@@ -260,20 +282,13 @@ function formatDocPage(programName, page, options = {}) {
260
282
  if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
261
283
  if (needsDescColumn && minDescWidth > 1) {
262
284
  const avail = options.maxWidth - termIndent - 2;
263
- const effTW = avail >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(avail / 2));
264
- const descW = avail - effTW;
285
+ const descW = avail - effectiveTermWidth;
265
286
  if (descW < minDescWidth) {
266
- const needed = termIndent + termWidth + 2 + minDescWidth;
287
+ const needed = termIndent + effectiveTermWidth + 2 + minDescWidth;
267
288
  throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
268
289
  }
269
290
  }
270
291
  }
271
- let effectiveTermWidth;
272
- if (options.maxWidth == null) effectiveTermWidth = termWidth;
273
- else {
274
- const availableForColumns = options.maxWidth - termIndent - 2;
275
- effectiveTermWidth = availableForColumns >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(availableForColumns / 2));
276
- }
277
292
  let output = "";
278
293
  if (hasContent(page.brief)) {
279
294
  output += formatMessage(page.brief, {
package/dist/facade.cjs CHANGED
@@ -126,6 +126,31 @@ function withEffectfulSessionOption(options, session) {
126
126
  [effectfulSessionOptionsKey]: session
127
127
  };
128
128
  }
129
+ /**
130
+ * Creates the run-scoped effectful completion sessions shared by a
131
+ * `runWith()` two-phase run, so an effectful source (e.g., a prompt)
132
+ * runs at most once per invocation. The seed pass uses the demand-only
133
+ * policy: an effectful source completes there only when a phase-one
134
+ * consumer demands its value; others defer to the final pass. The
135
+ * final pass shares the run-scoped results cache and demand set, but
136
+ * recomputes structural precedence from scratch: phase-two annotations
137
+ * may introduce environment/configuration values that must win over a
138
+ * cached seed prompt answer, so the effectful-source markers do not
139
+ * carry over.
140
+ */
141
+ function createRunWithSessions() {
142
+ const seedSession = require_internal_parser.createEffectfulCompletionSession("demand-only");
143
+ const finalSession = {
144
+ ...seedSession,
145
+ policy: "eager",
146
+ effectfulSources: /* @__PURE__ */ new Set(),
147
+ completedByPath: /* @__PURE__ */ new Map()
148
+ };
149
+ return {
150
+ seedSession,
151
+ finalSession
152
+ };
153
+ }
129
154
  function createCompleteExec(exec, context, session) {
130
155
  const runtime = require_dependency_runtime.createDependencyRuntimeContext();
131
156
  return {
@@ -623,7 +648,7 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
623
648
  * Handles shell completion requests.
624
649
  * @since 0.6.0
625
650
  */
626
- function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
651
+ function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
627
652
  const shellName = completionArgs[0] || "";
628
653
  const args = completionArgs.slice(1);
629
654
  const callOnError = (code) => onError(code);
@@ -636,6 +661,7 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
636
661
  if (doc) stderr(require_doc.formatDocPage(programName, doc, {
637
662
  colors,
638
663
  maxWidth,
664
+ termWidth,
639
665
  sectionOrder,
640
666
  showUsage
641
667
  }));
@@ -964,7 +990,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
964
990
  options = optionsParam ?? {};
965
991
  }
966
992
  require_validate.validateProgramName(programName);
967
- const { colors, maxWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
993
+ const { colors, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
968
994
  throw new RunParserError("Failed to parse command line arguments.");
969
995
  }, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
970
996
  const norm = (c) => c === true ? {} : c;
@@ -1102,7 +1128,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1102
1128
  classified.shell,
1103
1129
  ...classified.commandPath ?? [],
1104
1130
  ...classified.args
1105
- ], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions);
1131
+ ], 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);
1106
1132
  case "help": {
1107
1133
  let helpGeneratorParser;
1108
1134
  let docGeneratorParser;
@@ -1152,6 +1178,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1152
1178
  stdout(require_doc.formatDocPage(programName, renderedDoc, {
1153
1179
  colors,
1154
1180
  maxWidth,
1181
+ termWidth,
1155
1182
  showDefault,
1156
1183
  showChoices,
1157
1184
  sectionOrder,
@@ -1224,6 +1251,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1224
1251
  stderr(require_doc.formatDocPage(programName, renderedDoc, {
1225
1252
  colors,
1226
1253
  maxWidth,
1254
+ termWidth,
1227
1255
  showDefault,
1228
1256
  showChoices,
1229
1257
  sectionOrder,
@@ -1612,13 +1640,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1612
1640
  if (parser.mode === "async") return runParser(augmentedParser1, programName, args, options);
1613
1641
  return Promise.resolve(runParser(augmentedParser1, programName, args, options));
1614
1642
  }
1615
- const seedSession = require_internal_parser.createEffectfulCompletionSession("demand-only");
1616
- const finalSession = {
1617
- ...seedSession,
1618
- policy: "eager",
1619
- effectfulSources: /* @__PURE__ */ new Set(),
1620
- completedByPath: /* @__PURE__ */ new Map()
1621
- };
1643
+ const { seedSession, finalSession } = createRunWithSessions();
1622
1644
  const sessionOptions = withEffectfulSessionOption(options, finalSession);
1623
1645
  const firstPassSeed = await require_mode_dispatch.dispatchByMode(parser.mode, () => extractPhase2SeedSync(augmentedParser1, args, seedSession), () => extractPhase2SeedAsync(augmentedParser1, args, seedSession));
1624
1646
  if (firstPassSeed == null) {
@@ -1735,13 +1757,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1735
1757
  }
1736
1758
  const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
1737
1759
  if (!needsTwoPhase) return runParser(augmentedParser1, programName, args, options);
1738
- const seedSession = require_internal_parser.createEffectfulCompletionSession("demand-only");
1739
- const finalSession = {
1740
- ...seedSession,
1741
- policy: "eager",
1742
- effectfulSources: /* @__PURE__ */ new Set(),
1743
- completedByPath: /* @__PURE__ */ new Map()
1744
- };
1760
+ const { seedSession, finalSession } = createRunWithSessions();
1745
1761
  const sessionOptions = withEffectfulSessionOption(options, finalSession);
1746
1762
  const firstPassSeed = extractPhase2SeedSync(augmentedParser1, args, seedSession);
1747
1763
  if (firstPassSeed == null) {
package/dist/facade.d.cts CHANGED
@@ -89,6 +89,14 @@ interface RunOptions<THelp, TError> {
89
89
  * this width. If not specified, text will not be wrapped.
90
90
  */
91
91
  readonly maxWidth?: number;
92
+ /**
93
+ * Width allocated for help terms before descriptions start. Set to
94
+ * `"auto"` to align descriptions after the widest visible term.
95
+ *
96
+ * @default `26`
97
+ * @since 1.3.0
98
+ */
99
+ readonly termWidth?: number | "auto";
92
100
  /**
93
101
  * Whether and how to display default values for options and arguments.
94
102
  *
package/dist/facade.d.ts CHANGED
@@ -89,6 +89,14 @@ interface RunOptions<THelp, TError> {
89
89
  * this width. If not specified, text will not be wrapped.
90
90
  */
91
91
  readonly maxWidth?: number;
92
+ /**
93
+ * Width allocated for help terms before descriptions start. Set to
94
+ * `"auto"` to align descriptions after the widest visible term.
95
+ *
96
+ * @default `26`
97
+ * @since 1.3.0
98
+ */
99
+ readonly termWidth?: number | "auto";
92
100
  /**
93
101
  * Whether and how to display default values for options and arguments.
94
102
  *
package/dist/facade.js CHANGED
@@ -126,6 +126,31 @@ function withEffectfulSessionOption(options, session) {
126
126
  [effectfulSessionOptionsKey]: session
127
127
  };
128
128
  }
129
+ /**
130
+ * Creates the run-scoped effectful completion sessions shared by a
131
+ * `runWith()` two-phase run, so an effectful source (e.g., a prompt)
132
+ * runs at most once per invocation. The seed pass uses the demand-only
133
+ * policy: an effectful source completes there only when a phase-one
134
+ * consumer demands its value; others defer to the final pass. The
135
+ * final pass shares the run-scoped results cache and demand set, but
136
+ * recomputes structural precedence from scratch: phase-two annotations
137
+ * may introduce environment/configuration values that must win over a
138
+ * cached seed prompt answer, so the effectful-source markers do not
139
+ * carry over.
140
+ */
141
+ function createRunWithSessions() {
142
+ const seedSession = createEffectfulCompletionSession("demand-only");
143
+ const finalSession = {
144
+ ...seedSession,
145
+ policy: "eager",
146
+ effectfulSources: /* @__PURE__ */ new Set(),
147
+ completedByPath: /* @__PURE__ */ new Map()
148
+ };
149
+ return {
150
+ seedSession,
151
+ finalSession
152
+ };
153
+ }
129
154
  function createCompleteExec(exec, context, session) {
130
155
  const runtime = createDependencyRuntimeContext();
131
156
  return {
@@ -623,7 +648,7 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
623
648
  * Handles shell completion requests.
624
649
  * @since 0.6.0
625
650
  */
626
- function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
651
+ function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, termWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, showUsage, rootOptionSuggestions = []) {
627
652
  const shellName = completionArgs[0] || "";
628
653
  const args = completionArgs.slice(1);
629
654
  const callOnError = (code) => onError(code);
@@ -636,6 +661,7 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
636
661
  if (doc) stderr(formatDocPage(programName, doc, {
637
662
  colors,
638
663
  maxWidth,
664
+ termWidth,
639
665
  sectionOrder,
640
666
  showUsage
641
667
  }));
@@ -964,7 +990,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
964
990
  options = optionsParam ?? {};
965
991
  }
966
992
  validateProgramName(programName);
967
- const { colors, maxWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
993
+ const { colors, maxWidth, termWidth, showDefault, showChoices, sectionOrder, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
968
994
  throw new RunParserError("Failed to parse command line arguments.");
969
995
  }, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
970
996
  const norm = (c) => c === true ? {} : c;
@@ -1102,7 +1128,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1102
1128
  classified.shell,
1103
1129
  ...classified.commandPath ?? [],
1104
1130
  ...classified.args
1105
- ], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, showUsage, rootOptionSuggestions);
1131
+ ], 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);
1106
1132
  case "help": {
1107
1133
  let helpGeneratorParser;
1108
1134
  let docGeneratorParser;
@@ -1152,6 +1178,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1152
1178
  stdout(formatDocPage(programName, renderedDoc, {
1153
1179
  colors,
1154
1180
  maxWidth,
1181
+ termWidth,
1155
1182
  showDefault,
1156
1183
  showChoices,
1157
1184
  sectionOrder,
@@ -1224,6 +1251,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1224
1251
  stderr(formatDocPage(programName, renderedDoc, {
1225
1252
  colors,
1226
1253
  maxWidth,
1254
+ termWidth,
1227
1255
  showDefault,
1228
1256
  showChoices,
1229
1257
  sectionOrder,
@@ -1612,13 +1640,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1612
1640
  if (parser.mode === "async") return runParser(augmentedParser1, programName, args, options);
1613
1641
  return Promise.resolve(runParser(augmentedParser1, programName, args, options));
1614
1642
  }
1615
- const seedSession = createEffectfulCompletionSession("demand-only");
1616
- const finalSession = {
1617
- ...seedSession,
1618
- policy: "eager",
1619
- effectfulSources: /* @__PURE__ */ new Set(),
1620
- completedByPath: /* @__PURE__ */ new Map()
1621
- };
1643
+ const { seedSession, finalSession } = createRunWithSessions();
1622
1644
  const sessionOptions = withEffectfulSessionOption(options, finalSession);
1623
1645
  const firstPassSeed = await dispatchByMode(parser.mode, () => extractPhase2SeedSync(augmentedParser1, args, seedSession), () => extractPhase2SeedAsync(augmentedParser1, args, seedSession));
1624
1646
  if (firstPassSeed == null) {
@@ -1735,13 +1757,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1735
1757
  }
1736
1758
  const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
1737
1759
  if (!needsTwoPhase) return runParser(augmentedParser1, programName, args, options);
1738
- const seedSession = createEffectfulCompletionSession("demand-only");
1739
- const finalSession = {
1740
- ...seedSession,
1741
- policy: "eager",
1742
- effectfulSources: /* @__PURE__ */ new Set(),
1743
- completedByPath: /* @__PURE__ */ new Map()
1744
- };
1760
+ const { seedSession, finalSession } = createRunWithSessions();
1745
1761
  const sessionOptions = withEffectfulSessionOption(options, finalSession);
1746
1762
  const firstPassSeed = extractPhase2SeedSync(augmentedParser1, args, seedSession);
1747
1763
  if (firstPassSeed == null) {
package/dist/index.cjs CHANGED
@@ -108,6 +108,7 @@ exports.passThrough = require_primitives.passThrough;
108
108
  exports.port = require_valueparser.port;
109
109
  exports.portRange = require_valueparser.portRange;
110
110
  exports.pwsh = require_completion.pwsh;
111
+ exports.regExp = require_valueparser.regExp;
111
112
  exports.runParser = require_facade.runParser;
112
113
  exports.runParserAsync = require_facade.runParserAsync;
113
114
  exports.runParserSync = require_facade.runParserSync;
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonemp
3
3
  import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLine, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.cjs";
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.cjs";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.cjs";
6
- import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.cjs";
6
+ import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.cjs";
7
7
  import { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.cjs";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.cjs";
9
9
  import { DeferredValue, DeferredValueOptions, DeferredValueSource, FluentParser, MultipleErrorOptions, MultipleOptions, ParserModifiers, WithDefaultError, WithDefaultOptions, deferredValue, fluent, isDeferredValue, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.cjs";
@@ -12,4 +12,4 @@ import { ParserValuePlaceholder, SourceContext, SourceContextRequest } from "./c
12
12
  import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, dependency, deriveFrom, deriveFromAsync, deriveFromSync, isDependencySource, isDerivedValueParser } from "./internal/dependency.cjs";
13
13
  import { CommandListMode, CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.cjs";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.cjs";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonemp
3
3
  import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLine, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.js";
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.js";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.js";
6
- import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.js";
6
+ import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.js";
7
7
  import { CombineModes, DocState, EffectfulCompletionSession, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.js";
9
9
  import { DeferredValue, DeferredValueOptions, DeferredValueSource, FluentParser, MultipleErrorOptions, MultipleOptions, ParserModifiers, WithDefaultError, WithDefaultOptions, deferredValue, fluent, isDeferredValue, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
@@ -12,4 +12,4 @@ import { ParserValuePlaceholder, SourceContext, SourceContextRequest } from "./c
12
12
  import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, dependency, deriveFrom, deriveFromAsync, deriveFromSync, isDependencySource, isDerivedValueParser } from "./internal/dependency.js";
13
13
  import { CommandListMode, CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.js";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.js";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandListMode, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DeferredValue, DeferredValueOptions, DeferredValueSource, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EffectfulCompletionSession, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, FluentParser, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserModifiers, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TransformMapping, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@ import { bash, fish, nu, pwsh, zsh } from "./completion.js";
8
8
  import { WithDefaultError, deferredValue, fluent, isDeferredValue, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
9
9
  import { DuplicateOptionError, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.js";
10
10
  import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
11
- import { biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.js";
11
+ import { biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid } from "./valueparser.js";
12
12
  import { argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.js";
13
13
  import { RunParserError, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.js";
14
14
 
15
- export { DuplicateOptionError, RunParserError, WithDefaultError, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { DuplicateOptionError, RunParserError, WithDefaultError, argument, bash, biject, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, cron, deduplicateDocEntries, deduplicateDocFragments, deferredValue, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, fluent, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDeferredValue, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, regExp, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, transform, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
@@ -419,9 +419,9 @@ type ExecutionPhase = "parse" | "precomplete" | "resolve" | "complete" | "sugges
419
419
  * run, shared by the phase-two seed pass and the final pass) and threaded
420
420
  * through {@link ExecutionContext}. It guarantees that an effectful source
421
421
  * completion runs at most once per run: the completion result is cached by
422
- * dependency source ID, and a cache hit is returned without repeating the
423
- * effect. Results never leak between runs because the session is discarded
424
- * when the run ends.
422
+ * completion occurrence (see {@link EffectfulCompletionSession.results}),
423
+ * and a cache hit is returned without repeating the effect. Results never
424
+ * leak between runs because the session is discarded when the run ends.
425
425
  *
426
426
  * @internal
427
427
  * @since 1.3.0
@@ -419,9 +419,9 @@ type ExecutionPhase = "parse" | "precomplete" | "resolve" | "complete" | "sugges
419
419
  * run, shared by the phase-two seed pass and the final pass) and threaded
420
420
  * through {@link ExecutionContext}. It guarantees that an effectful source
421
421
  * completion runs at most once per run: the completion result is cached by
422
- * dependency source ID, and a cache hit is returned without repeating the
423
- * effect. Results never leak between runs because the session is discarded
424
- * when the run ends.
422
+ * completion occurrence (see {@link EffectfulCompletionSession.results}),
423
+ * and a cache hit is returned without repeating the effect. Results never
424
+ * leak between runs because the session is discarded when the run ends.
425
425
  *
426
426
  * @internal
427
427
  * @since 1.3.0
@@ -620,6 +620,71 @@ function string(options = {}) {
620
620
  }
621
621
  };
622
622
  }
623
+ /**
624
+ * Creates a {@link ValueParser} that compiles regular expression sources.
625
+ *
626
+ * The entire input is treated as the source. Slash-delimited notation such
627
+ * as `/pattern/flags` is not interpreted; use {@link RegExpOptions.flags} to
628
+ * configure fixed flags for the parser.
629
+ *
630
+ * **Security note**: Compiling a source does not establish that it is safe to
631
+ * execute. Patterns from untrusted input can cause Regular Expression Denial
632
+ * of Service (ReDoS) when matched. Limit pattern and subject lengths, execute
633
+ * matches in an environment that can be terminated, or use a linear-time
634
+ * regular expression engine when accepting untrusted patterns.
635
+ *
636
+ * @param options Configuration options for the regular expression parser.
637
+ * @returns A sync value parser producing JavaScript {@link RegExp} objects.
638
+ * @throws {TypeError} If `options.metavar` is an empty string or
639
+ * `options.flags` is not a string.
640
+ * @throws {SyntaxError} If `options.flags` contains invalid, duplicate, or
641
+ * incompatible regular expression flags.
642
+ * @since 1.3.0
643
+ */
644
+ function regExp(options = {}) {
645
+ const metavar$1 = options.metavar ?? "REGEXP";
646
+ require_nonempty.ensureNonEmptyString(metavar$1);
647
+ if (options.flags !== void 0 && typeof options.flags !== "string") throw new TypeError(`Expected flags to be a string, but got ${typeof options.flags}: ${String(options.flags)}.`);
648
+ const flags = new RegExp("", options.flags ?? "").flags;
649
+ const invalidRegExp = options.errors?.invalidRegExp;
650
+ const parseRegExp = (input) => {
651
+ try {
652
+ return {
653
+ success: true,
654
+ value: new RegExp(input, flags)
655
+ };
656
+ } catch (error) {
657
+ if (!(error instanceof SyntaxError)) throw error;
658
+ return {
659
+ success: false,
660
+ error: invalidRegExp ? typeof invalidRegExp === "function" ? invalidRegExp(input) : invalidRegExp : require_message.message`Invalid regular expression: ${input}.`
661
+ };
662
+ }
663
+ };
664
+ return {
665
+ mode: "sync",
666
+ metavar: metavar$1,
667
+ get placeholder() {
668
+ return new RegExp("", flags);
669
+ },
670
+ parse: parseRegExp,
671
+ validate(value) {
672
+ if (!(value instanceof RegExp)) return {
673
+ success: false,
674
+ error: require_message.message`Expected a RegExp value.`
675
+ };
676
+ return parseRegExp(value.source);
677
+ },
678
+ normalize(value) {
679
+ if (!(value instanceof RegExp)) return value;
680
+ const result = parseRegExp(value.source);
681
+ return result.success ? result.value : value;
682
+ },
683
+ format(value) {
684
+ return value.source;
685
+ }
686
+ };
687
+ }
623
688
  function keyValue(options = {}) {
624
689
  const separator = options.separator ?? "=";
625
690
  if (typeof separator !== "string") throw new TypeError(`Expected separator to be a string, but got ${typeof separator}: ${String(separator)}.`);
@@ -6628,6 +6693,7 @@ exports.locale = locale;
6628
6693
  exports.macAddress = macAddress;
6629
6694
  exports.port = port;
6630
6695
  exports.portRange = portRange;
6696
+ exports.regExp = regExp;
6631
6697
  exports.semVer = semVer;
6632
6698
  exports.socketAddress = socketAddress;
6633
6699
  exports.string = string;
@@ -498,6 +498,64 @@ declare function checkEnumOption<T extends object>(options: T | undefined, key:
498
498
  * `RegExp` instance.
499
499
  */
500
500
  declare function string(options?: StringOptions): ValueParser<"sync", string>;
501
+ /**
502
+ * Options for creating a {@link regExp} value parser.
503
+ *
504
+ * @since 1.3.0
505
+ */
506
+ interface RegExpOptions {
507
+ /**
508
+ * The metavariable name for this parser. This is used in help messages to
509
+ * indicate what kind of value this parser expects.
510
+ * @default `"REGEXP"`
511
+ * @since 1.3.0
512
+ */
513
+ readonly metavar?: NonEmptyString;
514
+ /**
515
+ * Fixed flags used to compile every input source.
516
+ * @default `""`
517
+ * @since 1.3.0
518
+ */
519
+ readonly flags?: string;
520
+ /**
521
+ * Custom error messages for regular expression parsing failures.
522
+ * @since 1.3.0
523
+ */
524
+ readonly errors?: {
525
+ /**
526
+ * Custom error message when the input is not a valid regular expression
527
+ * source. Can be a static message or a function that receives the input.
528
+ *
529
+ * **Security note**: Successful compilation does not guarantee safe
530
+ * execution. Vulnerable patterns can cause catastrophic backtracking when
531
+ * later matched against untrusted data.
532
+ * @since 1.3.0
533
+ */
534
+ readonly invalidRegExp?: Message | ((input: string) => Message);
535
+ };
536
+ }
537
+ /**
538
+ * Creates a {@link ValueParser} that compiles regular expression sources.
539
+ *
540
+ * The entire input is treated as the source. Slash-delimited notation such
541
+ * as `/pattern/flags` is not interpreted; use {@link RegExpOptions.flags} to
542
+ * configure fixed flags for the parser.
543
+ *
544
+ * **Security note**: Compiling a source does not establish that it is safe to
545
+ * execute. Patterns from untrusted input can cause Regular Expression Denial
546
+ * of Service (ReDoS) when matched. Limit pattern and subject lengths, execute
547
+ * matches in an environment that can be terminated, or use a linear-time
548
+ * regular expression engine when accepting untrusted patterns.
549
+ *
550
+ * @param options Configuration options for the regular expression parser.
551
+ * @returns A sync value parser producing JavaScript {@link RegExp} objects.
552
+ * @throws {TypeError} If `options.metavar` is an empty string or
553
+ * `options.flags` is not a string.
554
+ * @throws {SyntaxError} If `options.flags` contains invalid, duplicate, or
555
+ * incompatible regular expression flags.
556
+ * @since 1.3.0
557
+ */
558
+ declare function regExp(options?: RegExpOptions): ValueParser<"sync", RegExp>;
501
559
  interface KeyValueOptionsBase {
502
560
  /**
503
561
  * The metavariable name for this parser. Used in help messages to
@@ -3279,4 +3337,4 @@ declare function firstOf<const TParsers extends readonly [ValueParser<"sync", un
3279
3337
  */
3280
3338
  declare function firstOf<const TParsers extends readonly ValueParser<"sync", unknown>[]>(parsers: TParsers, options?: FirstOfOptions): ValueParser<"sync", ValueParserValue<TParsers[number]>>;
3281
3339
  //#endregion
3282
- export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid };
3340
+ export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid };
@@ -498,6 +498,64 @@ declare function checkEnumOption<T extends object>(options: T | undefined, key:
498
498
  * `RegExp` instance.
499
499
  */
500
500
  declare function string(options?: StringOptions): ValueParser<"sync", string>;
501
+ /**
502
+ * Options for creating a {@link regExp} value parser.
503
+ *
504
+ * @since 1.3.0
505
+ */
506
+ interface RegExpOptions {
507
+ /**
508
+ * The metavariable name for this parser. This is used in help messages to
509
+ * indicate what kind of value this parser expects.
510
+ * @default `"REGEXP"`
511
+ * @since 1.3.0
512
+ */
513
+ readonly metavar?: NonEmptyString;
514
+ /**
515
+ * Fixed flags used to compile every input source.
516
+ * @default `""`
517
+ * @since 1.3.0
518
+ */
519
+ readonly flags?: string;
520
+ /**
521
+ * Custom error messages for regular expression parsing failures.
522
+ * @since 1.3.0
523
+ */
524
+ readonly errors?: {
525
+ /**
526
+ * Custom error message when the input is not a valid regular expression
527
+ * source. Can be a static message or a function that receives the input.
528
+ *
529
+ * **Security note**: Successful compilation does not guarantee safe
530
+ * execution. Vulnerable patterns can cause catastrophic backtracking when
531
+ * later matched against untrusted data.
532
+ * @since 1.3.0
533
+ */
534
+ readonly invalidRegExp?: Message | ((input: string) => Message);
535
+ };
536
+ }
537
+ /**
538
+ * Creates a {@link ValueParser} that compiles regular expression sources.
539
+ *
540
+ * The entire input is treated as the source. Slash-delimited notation such
541
+ * as `/pattern/flags` is not interpreted; use {@link RegExpOptions.flags} to
542
+ * configure fixed flags for the parser.
543
+ *
544
+ * **Security note**: Compiling a source does not establish that it is safe to
545
+ * execute. Patterns from untrusted input can cause Regular Expression Denial
546
+ * of Service (ReDoS) when matched. Limit pattern and subject lengths, execute
547
+ * matches in an environment that can be terminated, or use a linear-time
548
+ * regular expression engine when accepting untrusted patterns.
549
+ *
550
+ * @param options Configuration options for the regular expression parser.
551
+ * @returns A sync value parser producing JavaScript {@link RegExp} objects.
552
+ * @throws {TypeError} If `options.metavar` is an empty string or
553
+ * `options.flags` is not a string.
554
+ * @throws {SyntaxError} If `options.flags` contains invalid, duplicate, or
555
+ * incompatible regular expression flags.
556
+ * @since 1.3.0
557
+ */
558
+ declare function regExp(options?: RegExpOptions): ValueParser<"sync", RegExp>;
501
559
  interface KeyValueOptionsBase {
502
560
  /**
503
561
  * The metavariable name for this parser. Used in help messages to
@@ -3279,4 +3337,4 @@ declare function firstOf<const TParsers extends readonly [ValueParser<"sync", un
3279
3337
  */
3280
3338
  declare function firstOf<const TParsers extends readonly ValueParser<"sync", unknown>[]>(parsers: TParsers, options?: FirstOfOptions): ValueParser<"sync", ValueParserValue<TParsers[number]>>;
3281
3339
  //#endregion
3282
- export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid };
3340
+ export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CronExpression, CronExpressionForOptions, CronOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, RegExpOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, TransformMapping, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid };
@@ -620,6 +620,71 @@ function string(options = {}) {
620
620
  }
621
621
  };
622
622
  }
623
+ /**
624
+ * Creates a {@link ValueParser} that compiles regular expression sources.
625
+ *
626
+ * The entire input is treated as the source. Slash-delimited notation such
627
+ * as `/pattern/flags` is not interpreted; use {@link RegExpOptions.flags} to
628
+ * configure fixed flags for the parser.
629
+ *
630
+ * **Security note**: Compiling a source does not establish that it is safe to
631
+ * execute. Patterns from untrusted input can cause Regular Expression Denial
632
+ * of Service (ReDoS) when matched. Limit pattern and subject lengths, execute
633
+ * matches in an environment that can be terminated, or use a linear-time
634
+ * regular expression engine when accepting untrusted patterns.
635
+ *
636
+ * @param options Configuration options for the regular expression parser.
637
+ * @returns A sync value parser producing JavaScript {@link RegExp} objects.
638
+ * @throws {TypeError} If `options.metavar` is an empty string or
639
+ * `options.flags` is not a string.
640
+ * @throws {SyntaxError} If `options.flags` contains invalid, duplicate, or
641
+ * incompatible regular expression flags.
642
+ * @since 1.3.0
643
+ */
644
+ function regExp(options = {}) {
645
+ const metavar$1 = options.metavar ?? "REGEXP";
646
+ ensureNonEmptyString(metavar$1);
647
+ if (options.flags !== void 0 && typeof options.flags !== "string") throw new TypeError(`Expected flags to be a string, but got ${typeof options.flags}: ${String(options.flags)}.`);
648
+ const flags = new RegExp("", options.flags ?? "").flags;
649
+ const invalidRegExp = options.errors?.invalidRegExp;
650
+ const parseRegExp = (input) => {
651
+ try {
652
+ return {
653
+ success: true,
654
+ value: new RegExp(input, flags)
655
+ };
656
+ } catch (error) {
657
+ if (!(error instanceof SyntaxError)) throw error;
658
+ return {
659
+ success: false,
660
+ error: invalidRegExp ? typeof invalidRegExp === "function" ? invalidRegExp(input) : invalidRegExp : message`Invalid regular expression: ${input}.`
661
+ };
662
+ }
663
+ };
664
+ return {
665
+ mode: "sync",
666
+ metavar: metavar$1,
667
+ get placeholder() {
668
+ return new RegExp("", flags);
669
+ },
670
+ parse: parseRegExp,
671
+ validate(value) {
672
+ if (!(value instanceof RegExp)) return {
673
+ success: false,
674
+ error: message`Expected a RegExp value.`
675
+ };
676
+ return parseRegExp(value.source);
677
+ },
678
+ normalize(value) {
679
+ if (!(value instanceof RegExp)) return value;
680
+ const result = parseRegExp(value.source);
681
+ return result.success ? result.value : value;
682
+ },
683
+ format(value) {
684
+ return value.source;
685
+ }
686
+ };
687
+ }
623
688
  function keyValue(options = {}) {
624
689
  const separator = options.separator ?? "=";
625
690
  if (typeof separator !== "string") throw new TypeError(`Expected separator to be a string, but got ${typeof separator}: ${String(separator)}.`);
@@ -6602,4 +6667,4 @@ function plainObjectsEqual(a, b) {
6602
6667
  }
6603
6668
 
6604
6669
  //#endregion
6605
- export { biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, transform, url, uuid };
6670
+ export { biject, checkBooleanOption, checkEnumOption, choice, cidr, color, cron, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, regExp, semVer, socketAddress, string, transform, url, uuid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.3.0-dev.2380",
3
+ "version": "1.3.0-dev.2383",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  "sideEffects": false,
223
223
  "devDependencies": {
224
- "@optique/env": "1.3.0-dev.2380+4bce39a7",
224
+ "@optique/env": "1.3.0-dev.2383+4053ebf3",
225
225
  "@types/node": "^24.0.0",
226
226
  "fast-check": "^4.7.0",
227
227
  "tsdown": "^0.13.0",
@@ -40,11 +40,12 @@ Core rules
40
40
  - Use `message` from *@optique/core/message* for descriptions, help text, and
41
41
  custom errors. Prefer semantic message helpers such as `optionName()` and
42
42
  `metavar()` over string concatenation when naming CLI elements.
43
- - Use value parsers such as `integer()`, `choice()`, `biject()`, `url()`,
44
- and `uuid()` instead of validating raw strings after parsing. Use
45
- `biject()` for one-to-one string-to-value choices, and use `transform()`
46
- when an existing value parser describes the accepted CLI spelling but your
47
- app needs a different result type. Use `path()` from
43
+ - Use value parsers such as `integer()`, `choice()`, `biject()`, `regExp()`,
44
+ `url()`, and `uuid()` instead of validating raw strings after parsing. Use
45
+ `regExp({ flags })` for user-supplied regular expression sources,
46
+ `biject()` for one-to-one string-to-value choices, and `transform()` when
47
+ an existing value parser describes the accepted CLI spelling but your app
48
+ needs a different result type. Use `path()` from
48
49
  `@optique/run/valueparser` for file-system paths. Write a custom
49
50
  `{ mode, metavar, parse, format }` value parser only when the catalog does
50
51
  not cover the domain.
@@ -63,6 +64,9 @@ Core rules
63
64
  brief and command or option sections without the `Usage:` synopsis.
64
65
  For deeply nested command trees, add `commandList: "top-level"` when root
65
66
  help should list only first-level command groups.
67
+ - Use `termWidth: "auto"` in runner options when descriptions should align
68
+ after the widest visible help term. Optique measures terminal display
69
+ width after adding built-in help/version/completion entries.
66
70
 
67
71
 
68
72
  Canonical app shape
@@ -96,6 +100,7 @@ const config = run(parser, {
96
100
  brief: message`Process a file.`,
97
101
  completion: "both",
98
102
  showDefault: true,
103
+ termWidth: "auto",
99
104
  });
100
105
 
101
106
  console.log(`Processing ${config.input} on port ${config.port}.`);