@optique/core 1.4.0-dev.2895 → 1.4.0-dev.2897

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/facade.cjs CHANGED
@@ -818,7 +818,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
818
818
  options = optionsParam ?? {};
819
819
  }
820
820
  require_validate.validateProgramName(programName);
821
- const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, showAliases, showEnvironment, sectionOrder, helpSections, showUsage, usageLine, commandList = "recursive", aboveError = "usage", errorUsage = "root", onError = () => {
821
+ const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, showAliases, showEnvironment, sectionOrder, helpSections, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
822
822
  throw new RunParserError("Failed to parse command line arguments.");
823
823
  }, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
824
824
  let maxWidth = requestedMaxWidth;
@@ -1117,15 +1117,8 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1117
1117
  })));
1118
1118
  }
1119
1119
  if (effectiveAboveError === "usage") {
1120
- const rootUsage = augmentedParser.usage;
1121
- const optionCount = Number(helpParsers.helpOption != null) + Number(versionParsers.versionOption != null);
1122
- const alternativeCount = optionCount + Number(helpParsers.helpCommand != null) + Number(versionParsers.versionCommand != null) + Number(completionParsers.completionCommand != null);
1123
- const errorUsageTerms = aboveError === "usage" && errorUsage === "command" ? require_usage_internals.projectCommandUsage(rootUsage, classified.commandPath, alternativeCount === 0 ? void 0 : {
1124
- optionCount,
1125
- alternativeCount
1126
- }) ?? rootUsage : rootUsage;
1127
- resolveUsageWidth(errorUsageTerms);
1128
- stderr(`${usageLabel()}${indentLines(require_usage.formatUsage(programName, errorUsageTerms, {
1120
+ resolveUsageWidth(augmentedParser.usage);
1121
+ stderr(`${usageLabel()}${indentLines(require_usage.formatUsage(programName, augmentedParser.usage, {
1129
1122
  theme,
1130
1123
  colors,
1131
1124
  maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
package/dist/facade.d.cts CHANGED
@@ -326,17 +326,6 @@ interface RunOptions<THelp, TError> {
326
326
  * @default `"usage"`
327
327
  */
328
328
  readonly aboveError?: "usage" | "help" | "none";
329
- /**
330
- * Scope of the compact preamble when `aboveError` is `"usage"`.
331
- * `"command"` uses the failed parse's canonical command path and usage
332
- * metadata, retaining parent options. Hidden or unresolved paths and
333
- * unsupported compositions fall back to root usage. Neither mode applies
334
- * help-only `usageLine` overrides or evaluates the parser again.
335
- *
336
- * @default `"root"`
337
- * @since 1.4.0
338
- */
339
- readonly errorUsage?: "root" | "command";
340
329
  /**
341
330
  * Callback invoked after error output for a parse failure, an invalid
342
331
  * command path before help, or a missing or unsupported completion shell.
package/dist/facade.d.ts CHANGED
@@ -326,17 +326,6 @@ interface RunOptions<THelp, TError> {
326
326
  * @default `"usage"`
327
327
  */
328
328
  readonly aboveError?: "usage" | "help" | "none";
329
- /**
330
- * Scope of the compact preamble when `aboveError` is `"usage"`.
331
- * `"command"` uses the failed parse's canonical command path and usage
332
- * metadata, retaining parent options. Hidden or unresolved paths and
333
- * unsupported compositions fall back to root usage. Neither mode applies
334
- * help-only `usageLine` overrides or evaluates the parser again.
335
- *
336
- * @default `"root"`
337
- * @since 1.4.0
338
- */
339
- readonly errorUsage?: "root" | "command";
340
329
  /**
341
330
  * Callback invoked after error output for a parse failure, an invalid
342
331
  * command path before help, or a missing or unsupported completion shell.
package/dist/facade.js CHANGED
@@ -12,7 +12,7 @@ import { collectExplicitSourceValues, collectExplicitSourceValuesAsync, createDe
12
12
  import { createInputTrace } from "./input-trace.js";
13
13
  import { attemptParseAsync, attemptParseSync, createEffectfulCompletionSession, createParserContext, getDocPage } from "./internal/parser.js";
14
14
  import { bash, fish, nu, pwsh, zsh } from "./completion.js";
15
- import { collectActiveOptionNames, collectRootOptionNames, projectCommandUsage } from "./usage-internals.js";
15
+ import { collectActiveOptionNames, collectRootOptionNames } from "./usage-internals.js";
16
16
  import { allowDuplicateLeadingCommandNamesKey, hiddenCommandAliasesKey } from "./internal/command-alias.js";
17
17
  import { completeOrExtractPhase2Seed } from "./phase2-seed.js";
18
18
  import { multiple, optional, withDefault } from "./modifiers.js";
@@ -818,7 +818,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
818
818
  options = optionsParam ?? {};
819
819
  }
820
820
  validateProgramName(programName);
821
- const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, showAliases, showEnvironment, sectionOrder, helpSections, showUsage, usageLine, commandList = "recursive", aboveError = "usage", errorUsage = "root", onError = () => {
821
+ const { colors, messageFormatter, theme: requestedTheme, maxWidth: requestedMaxWidth, termWidth, showDefault, showChoices, showAliases, showEnvironment, sectionOrder, helpSections, showUsage, usageLine, commandList = "recursive", aboveError = "usage", onError = () => {
822
822
  throw new RunParserError("Failed to parse command line arguments.");
823
823
  }, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
824
824
  let maxWidth = requestedMaxWidth;
@@ -1117,15 +1117,8 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
1117
1117
  })));
1118
1118
  }
1119
1119
  if (effectiveAboveError === "usage") {
1120
- const rootUsage = augmentedParser.usage;
1121
- const optionCount = Number(helpParsers.helpOption != null) + Number(versionParsers.versionOption != null);
1122
- const alternativeCount = optionCount + Number(helpParsers.helpCommand != null) + Number(versionParsers.versionCommand != null) + Number(completionParsers.completionCommand != null);
1123
- const errorUsageTerms = aboveError === "usage" && errorUsage === "command" ? projectCommandUsage(rootUsage, classified.commandPath, alternativeCount === 0 ? void 0 : {
1124
- optionCount,
1125
- alternativeCount
1126
- }) ?? rootUsage : rootUsage;
1127
- resolveUsageWidth(errorUsageTerms);
1128
- stderr(`${usageLabel()}${indentLines(formatUsage(programName, errorUsageTerms, {
1120
+ resolveUsageWidth(augmentedParser.usage);
1121
+ stderr(`${usageLabel()}${indentLines(formatUsage(programName, augmentedParser.usage, {
1129
1122
  theme,
1130
1123
  colors,
1131
1124
  maxWidth: maxWidth == null ? void 0 : maxWidth - usageLabelWidth(),
@@ -2,103 +2,6 @@ const require_usage = require('./usage.cjs');
2
2
 
3
3
  //#region src/usage-internals.ts
4
4
  /**
5
- * Projects augmented runner usage onto a recorded canonical command path.
6
- * Unsupported or ambiguous metadata returns undefined, preserving root usage.
7
- * No parser, documentation, or usage-override callbacks are evaluated.
8
- * @param usage The runner's original augmented usage.
9
- * @param path The canonical path recorded by the failed parse.
10
- * @param meta The known augmentation boundary, absent without alternatives.
11
- * @returns The selected grammar, or undefined when projection is uncertain.
12
- * @internal
13
- */
14
- function projectCommandUsage(usage, path, meta) {
15
- if (path.length === 0) return void 0;
16
- if (meta == null) return projectCommandTerms(usage, path, 0);
17
- const top = usage[0];
18
- if (usage.length !== 1 || top.type !== "exclusive" || top.terms.length !== meta.alternativeCount + 1) return void 0;
19
- const selected = projectCommandTerms(top.terms[meta.optionCount], path, 0);
20
- if (selected == null) return void 0;
21
- const options = top.terms.slice(0, meta.optionCount).filter((branch) => branch.some((term) => term.type === "option" && !require_usage.isUsageHidden(term.hidden)));
22
- return options.length === 0 ? selected : [{
23
- type: "exclusive",
24
- terms: [...options, selected]
25
- }];
26
- }
27
- function containsCommand(usage) {
28
- return usage.some((term) => {
29
- switch (term.type) {
30
- case "command": return true;
31
- case "exclusive": return term.terms.some(containsCommand);
32
- case "optional":
33
- case "multiple":
34
- case "sequence": return containsCommand(term.terms);
35
- default: return false;
36
- }
37
- });
38
- }
39
- /** Undefined distinguishes unsupported metadata from a command-free branch. */
40
- function firstCommandNames(usage) {
41
- const hosts = usage.filter((term) => containsCommand([term]));
42
- const first = hosts[0];
43
- if (first == null) return [];
44
- if (first.type === "command") return [first.name];
45
- if (hosts.length !== 1) return void 0;
46
- if (first.type === "sequence") return firstCommandNames(first.terms);
47
- if (first.type !== "exclusive") return void 0;
48
- const names = [];
49
- for (const branch of first.terms) {
50
- const found = firstCommandNames(branch);
51
- if (found == null) return void 0;
52
- names.push(...found);
53
- }
54
- return names;
55
- }
56
- function projectCommandTerms(usage, path, offset) {
57
- if (offset === path.length) return usage;
58
- const index = usage.findIndex((term) => containsCommand([term]));
59
- if (index < 0) return void 0;
60
- const host = usage[index];
61
- const prefix = usage.slice(0, index);
62
- const suffix = usage.slice(index + 1);
63
- if (host.type === "command") {
64
- if (host.name !== path[offset] || require_usage.isUsageHidden(host.hidden)) return void 0;
65
- const rest = projectCommandTerms(suffix, path, offset + 1);
66
- return rest == null ? void 0 : [
67
- ...prefix,
68
- host,
69
- ...rest
70
- ];
71
- }
72
- if (containsCommand(suffix)) return void 0;
73
- if (host.type === "sequence") {
74
- const terms$1 = projectCommandTerms(host.terms, path, offset);
75
- return terms$1 == null ? void 0 : [
76
- ...prefix,
77
- {
78
- ...host,
79
- terms: terms$1
80
- },
81
- ...suffix
82
- ];
83
- }
84
- if (host.type !== "exclusive") return void 0;
85
- let selected;
86
- for (const branch of host.terms) {
87
- const names = firstCommandNames(branch);
88
- if (names == null) return void 0;
89
- if (!names.includes(path[offset])) continue;
90
- if (selected != null) return void 0;
91
- selected = branch;
92
- }
93
- if (selected == null) return void 0;
94
- const terms = projectCommandTerms(selected, path, offset);
95
- return terms == null ? void 0 : [
96
- ...prefix,
97
- ...terms,
98
- ...suffix
99
- ];
100
- }
101
- /**
102
5
  * Collects option names and command names that are valid as the *immediate*
103
6
  * next token at the current parse position ("leading candidates").
104
7
  *
@@ -249,5 +152,4 @@ exports.collectActiveOptionNames = collectActiveOptionNames;
249
152
  exports.collectLeadingCandidates = collectLeadingCandidates;
250
153
  exports.collectOptionNamesAtCurrentCommandDepth = collectOptionNamesAtCurrentCommandDepth;
251
154
  exports.collectRootOptionNames = collectRootOptionNames;
252
- exports.extractLeadingCommandNames = extractLeadingCommandNames;
253
- exports.projectCommandUsage = projectCommandUsage;
155
+ exports.extractLeadingCommandNames = extractLeadingCommandNames;
@@ -1,104 +1,7 @@
1
- import { isSuggestionHidden, isUsageHidden } from "./usage.js";
1
+ import { isSuggestionHidden } from "./usage.js";
2
2
 
3
3
  //#region src/usage-internals.ts
4
4
  /**
5
- * Projects augmented runner usage onto a recorded canonical command path.
6
- * Unsupported or ambiguous metadata returns undefined, preserving root usage.
7
- * No parser, documentation, or usage-override callbacks are evaluated.
8
- * @param usage The runner's original augmented usage.
9
- * @param path The canonical path recorded by the failed parse.
10
- * @param meta The known augmentation boundary, absent without alternatives.
11
- * @returns The selected grammar, or undefined when projection is uncertain.
12
- * @internal
13
- */
14
- function projectCommandUsage(usage, path, meta) {
15
- if (path.length === 0) return void 0;
16
- if (meta == null) return projectCommandTerms(usage, path, 0);
17
- const top = usage[0];
18
- if (usage.length !== 1 || top.type !== "exclusive" || top.terms.length !== meta.alternativeCount + 1) return void 0;
19
- const selected = projectCommandTerms(top.terms[meta.optionCount], path, 0);
20
- if (selected == null) return void 0;
21
- const options = top.terms.slice(0, meta.optionCount).filter((branch) => branch.some((term) => term.type === "option" && !isUsageHidden(term.hidden)));
22
- return options.length === 0 ? selected : [{
23
- type: "exclusive",
24
- terms: [...options, selected]
25
- }];
26
- }
27
- function containsCommand(usage) {
28
- return usage.some((term) => {
29
- switch (term.type) {
30
- case "command": return true;
31
- case "exclusive": return term.terms.some(containsCommand);
32
- case "optional":
33
- case "multiple":
34
- case "sequence": return containsCommand(term.terms);
35
- default: return false;
36
- }
37
- });
38
- }
39
- /** Undefined distinguishes unsupported metadata from a command-free branch. */
40
- function firstCommandNames(usage) {
41
- const hosts = usage.filter((term) => containsCommand([term]));
42
- const first = hosts[0];
43
- if (first == null) return [];
44
- if (first.type === "command") return [first.name];
45
- if (hosts.length !== 1) return void 0;
46
- if (first.type === "sequence") return firstCommandNames(first.terms);
47
- if (first.type !== "exclusive") return void 0;
48
- const names = [];
49
- for (const branch of first.terms) {
50
- const found = firstCommandNames(branch);
51
- if (found == null) return void 0;
52
- names.push(...found);
53
- }
54
- return names;
55
- }
56
- function projectCommandTerms(usage, path, offset) {
57
- if (offset === path.length) return usage;
58
- const index = usage.findIndex((term) => containsCommand([term]));
59
- if (index < 0) return void 0;
60
- const host = usage[index];
61
- const prefix = usage.slice(0, index);
62
- const suffix = usage.slice(index + 1);
63
- if (host.type === "command") {
64
- if (host.name !== path[offset] || isUsageHidden(host.hidden)) return void 0;
65
- const rest = projectCommandTerms(suffix, path, offset + 1);
66
- return rest == null ? void 0 : [
67
- ...prefix,
68
- host,
69
- ...rest
70
- ];
71
- }
72
- if (containsCommand(suffix)) return void 0;
73
- if (host.type === "sequence") {
74
- const terms$1 = projectCommandTerms(host.terms, path, offset);
75
- return terms$1 == null ? void 0 : [
76
- ...prefix,
77
- {
78
- ...host,
79
- terms: terms$1
80
- },
81
- ...suffix
82
- ];
83
- }
84
- if (host.type !== "exclusive") return void 0;
85
- let selected;
86
- for (const branch of host.terms) {
87
- const names = firstCommandNames(branch);
88
- if (names == null) return void 0;
89
- if (!names.includes(path[offset])) continue;
90
- if (selected != null) return void 0;
91
- selected = branch;
92
- }
93
- if (selected == null) return void 0;
94
- const terms = projectCommandTerms(selected, path, offset);
95
- return terms == null ? void 0 : [
96
- ...prefix,
97
- ...terms,
98
- ...suffix
99
- ];
100
- }
101
- /**
102
5
  * Collects option names and command names that are valid as the *immediate*
103
6
  * next token at the current parse position ("leading candidates").
104
7
  *
@@ -245,4 +148,4 @@ function collectRootOptionNamesFromTerm(term, names, rootLeadingNames) {
245
148
  }
246
149
 
247
150
  //#endregion
248
- export { collectActiveOptionNames, collectLeadingCandidates, collectOptionNamesAtCurrentCommandDepth, collectRootOptionNames, extractLeadingCommandNames, projectCommandUsage };
151
+ export { collectActiveOptionNames, collectLeadingCandidates, collectOptionNamesAtCurrentCommandDepth, collectRootOptionNames, extractLeadingCommandNames };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.4.0-dev.2895",
3
+ "version": "1.4.0-dev.2897",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -261,7 +261,7 @@
261
261
  },
262
262
  "sideEffects": false,
263
263
  "devDependencies": {
264
- "@optique/env": "1.4.0-dev.2895+fb7758c4",
264
+ "@optique/env": "1.4.0-dev.2897+0d4d0c4a",
265
265
  "@types/node": "^24.0.0",
266
266
  "fast-check": "^4.7.0",
267
267
  "tsdown": "^0.13.0",
@@ -53,9 +53,8 @@ Core rules
53
53
  - Async value parsers like *@optique/git* make containing parsers async.
54
54
  Await `run()`/`parse()`/`runParser()` or, for `bindKeyring()`, `runAsync()`.
55
55
  - Use `dependency()` when one value parser controls another's valid values.
56
- For a multi-level chain, wrap the middle derivation too:
57
- `dependency(source.deriveSync(...))`. Optique resolves such chains by
58
- dependency order, independently of object/tuple field order.
56
+ Wrap middle steps too: `dependency(source.deriveSync(...))`. Resolution
57
+ follows dependency order, independently of object/tuple field order.
59
58
  - Use `derivePromptConfig(source, resolver)` from *@optique/prompt* or its
60
59
  adapters for choices/messages depending on parsed values; use
61
60
  `[sourceA, sourceB]` for several sources. Async resolvers run at fallback
@@ -80,9 +79,9 @@ Core rules
80
79
  Show hidden `aliases` in help with `showAliases` on `command()` or runner.
81
80
  - Use `run(parser, { completion: "both" })` for completion, or the object form
82
81
  with `completion.errors` for custom shell errors. Do not hand-write scripts.
83
- - Use `usageLine: [{ type: "ellipsis" }]` for compact root full help and the
84
- override on `command()` for subcommand help. `errorUsage: "command"` scopes
85
- usage above errors with root fallback, ignoring help-only overrides.
82
+ - Use `usageLine: [{ type: "ellipsis" }]` in runner options when a large root
83
+ synopsis should become a compact `Usage: myapp ...` line. This applies only
84
+ to root full help; use `command()`'s `usageLine` for subcommand help.
86
85
  - Use `showUsage: false` in runner options when full help should show the
87
86
  brief and sections without `Usage:`. Set `command()`'s `showUsage: true`
88
87
  to restore it; children inherit the nearest explicit ancestor setting.
@@ -274,6 +273,7 @@ Reference links
274
273
  - Shell completion: <https://optique.dev/concepts/completion.md>
275
274
  - Command discovery: <https://optique.dev/concepts/discover.md>
276
275
  - Man pages: <https://optique.dev/concepts/man.md>
276
+ - Consumer skills: <https://optique.dev/consumer-skills.md>
277
277
 
278
278
 
279
279
  Integration packages