@optique/core 1.0.16-dev.2947 → 1.0.16-dev.2983

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.
@@ -21,23 +21,102 @@ function serializePath(path) {
21
21
  if (path.length === 0) return "";
22
22
  return path.map(serializeKey).join("");
23
23
  }
24
+ function height(node$1) {
25
+ return node$1?.height ?? 0;
26
+ }
27
+ function node(key, entry, left, right) {
28
+ return {
29
+ key,
30
+ entry,
31
+ left,
32
+ right,
33
+ height: 1 + Math.max(height(left), height(right))
34
+ };
35
+ }
36
+ function balance(key, entry, left, right) {
37
+ if (height(left) - height(right) > 1 && left != null) {
38
+ const pivot = left.right;
39
+ if (height(pivot) > height(left.left) && pivot != null) return node(pivot.key, pivot.entry, node(left.key, left.entry, left.left, pivot.left), node(key, entry, pivot.right, right));
40
+ return node(left.key, left.entry, left.left, node(key, entry, left.right, right));
41
+ }
42
+ if (height(right) - height(left) > 1 && right != null) {
43
+ const pivot = right.left;
44
+ if (height(pivot) > height(right.right) && pivot != null) return node(pivot.key, pivot.entry, node(key, entry, left, pivot.left), node(right.key, right.entry, pivot.right, right.right));
45
+ return node(right.key, right.entry, node(key, entry, left, right.left), right.right);
46
+ }
47
+ return node(key, entry, left, right);
48
+ }
49
+ function setEntry(root, key, entry) {
50
+ if (root == null) return node(key, entry, void 0, void 0);
51
+ if (key === root.key) return entry === root.entry ? root : {
52
+ ...root,
53
+ entry
54
+ };
55
+ if (key < root.key) {
56
+ const left = setEntry(root.left, key, entry);
57
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
58
+ }
59
+ const right = setEntry(root.right, key, entry);
60
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
61
+ }
62
+ function popMin(root) {
63
+ if (root.left == null) return [root, root.right];
64
+ const [minimum, left] = popMin(root.left);
65
+ return [minimum, balance(root.key, root.entry, left, root.right)];
66
+ }
67
+ function deleteEntry(root, key) {
68
+ if (root == null) return void 0;
69
+ if (key === root.key) {
70
+ if (root.left == null) return root.right;
71
+ if (root.right == null) return root.left;
72
+ const [successor, right$1] = popMin(root.right);
73
+ return balance(successor.key, successor.entry, root.left, right$1);
74
+ }
75
+ if (key < root.key) {
76
+ const left = deleteEntry(root.left, key);
77
+ return left === root.left ? root : balance(root.key, root.entry, left, root.right);
78
+ }
79
+ const right = deleteEntry(root.right, key);
80
+ return right === root.right ? root : balance(root.key, root.entry, root.left, right);
81
+ }
82
+ function inspectNode(root, lower, upper) {
83
+ if (root == null) return {
84
+ size: 0,
85
+ height: 0
86
+ };
87
+ if (lower !== void 0 && root.key <= lower || upper !== void 0 && root.key >= upper) throw new TypeError("Input trace keys are not strictly ordered.");
88
+ const left = inspectNode(root.left, lower, root.key);
89
+ const right = inspectNode(root.right, root.key, upper);
90
+ const actualHeight = 1 + Math.max(left.height, right.height);
91
+ if (root.height !== actualHeight || Math.abs(left.height - right.height) > 1) throw new TypeError("Input trace heights or balance are invalid.");
92
+ return {
93
+ size: 1 + left.size + right.size,
94
+ height: actualHeight
95
+ };
96
+ }
24
97
  var InputTraceImpl = class InputTraceImpl {
25
- #entries;
26
- constructor(entries) {
27
- this.#entries = entries ?? /* @__PURE__ */ new Map();
98
+ #root;
99
+ constructor(root) {
100
+ this.#root = root;
28
101
  }
29
102
  get(path) {
30
- return this.#entries.get(serializePath(path));
103
+ const key = serializePath(path);
104
+ let current = this.#root;
105
+ while (current != null) {
106
+ if (key === current.key) return current.entry;
107
+ current = key < current.key ? current.left : current.right;
108
+ }
109
+ return void 0;
31
110
  }
32
111
  set(path, entry) {
33
- const copy = new Map(this.#entries);
34
- copy.set(serializePath(path), entry);
35
- return new InputTraceImpl(copy);
112
+ return new InputTraceImpl(setEntry(this.#root, serializePath(path), entry));
36
113
  }
37
114
  delete(path) {
38
- const copy = new Map(this.#entries);
39
- copy.delete(serializePath(path));
40
- return new InputTraceImpl(copy);
115
+ return new InputTraceImpl(deleteEntry(this.#root, serializePath(path)));
116
+ }
117
+ static inspect(trace) {
118
+ if (!(trace instanceof InputTraceImpl)) throw new TypeError("Expected an Optique input trace.");
119
+ return inspectNode(trace.#root);
41
120
  }
42
121
  };
43
122
  /**
@@ -1,7 +1,24 @@
1
+ const require_command_usage = require('./command-usage.cjs');
1
2
 
2
3
  //#region src/internal/command-doc-metadata.ts
4
+ const selectedCommandUsage = /* @__PURE__ */ new WeakMap();
5
+ /** Reads command occurrences selected by final parser state. @internal */
6
+ function getSelectedCommandUsage(metadata) {
7
+ return metadata == null ? [] : selectedCommandUsage.get(metadata) ?? [];
8
+ }
9
+ /** Attaches selection without adding public metadata properties. @internal */
10
+ function withSelectedCommandUsage(metadata, selected) {
11
+ const result = withOrigin(metadata ?? {}, metadata?.origin ?? "entry");
12
+ selectedCommandUsage.set(result, selected);
13
+ return result;
14
+ }
15
+ /** Maps selected commands to the same child scope as its usage. @internal */
16
+ function scopeCommandDocMetadata(metadata, scope) {
17
+ return metadata == null ? void 0 : withSelectedCommandUsage(metadata, getSelectedCommandUsage(metadata).map((id) => require_command_usage.scopeCommandUsageId(scope, id)));
18
+ }
3
19
  function withOrigin(metadata, origin) {
4
20
  const result = { ...metadata };
21
+ selectedCommandUsage.set(result, getSelectedCommandUsage(metadata));
5
22
  Object.defineProperty(result, "origin", {
6
23
  value: origin,
7
24
  enumerable: false
@@ -23,11 +40,11 @@ function getCommandDocMetadata(docs) {
23
40
  const customPage = origin === "entry" && (docs.brief !== carrier.brief || docs.footer !== carrier.footer);
24
41
  const description = origin === "entry" && !customPage || docs.description === carrier.description ? carrier.metadata.description : docs.description;
25
42
  const footer = docs.footer === carrier.footer ? carrier.metadata.footer : docs.footer;
26
- return withOrigin({
43
+ return withSelectedCommandUsage(withOrigin({
27
44
  ...brief == null ? {} : { brief },
28
45
  ...description == null ? {} : { description },
29
46
  ...footer == null ? {} : { footer }
30
- }, customPage ? "custom" : origin);
47
+ }, customPage ? "custom" : origin), getSelectedCommandUsage(carrier.metadata));
31
48
  }
32
49
  const metadata = docs[commandDocMetadata];
33
50
  if (metadata != null) return metadata;
@@ -67,7 +84,7 @@ function withCommandDocMetadata(docs, metadata) {
67
84
  * @param includeCustom Whether to retain custom page fields inside merge().
68
85
  * @returns The first defined value from children with the same origin.
69
86
  */
70
- function collectCommandDocMetadata(current, docs, includeCustom = false) {
87
+ function collectCommandPageMetadata(current, docs, includeCustom = false) {
71
88
  const next = getCommandDocMetadata(docs);
72
89
  if (next == null) return current;
73
90
  const origin = next.origin ?? "entry";
@@ -83,8 +100,19 @@ function collectCommandDocMetadata(current, docs, includeCustom = false) {
83
100
  ...footer == null ? {} : { footer }
84
101
  }, origin);
85
102
  }
103
+ /** Collects page fields and all selected command occurrences. @internal */
104
+ function collectCommandDocMetadata(current, docs, includeCustom = false, scope) {
105
+ const next = getCommandDocMetadata(docs);
106
+ const selected = getSelectedCommandUsage(next);
107
+ const result = collectCommandPageMetadata(current, docs, includeCustom);
108
+ const combined = [...getSelectedCommandUsage(current), ...scope == null ? selected : selected.map((id) => require_command_usage.scopeCommandUsageId(scope, id))];
109
+ return combined.length === 0 ? result : withSelectedCommandUsage(result, combined);
110
+ }
86
111
 
87
112
  //#endregion
88
113
  exports.collectCommandDocMetadata = collectCommandDocMetadata;
89
114
  exports.getCommandDocMetadata = getCommandDocMetadata;
90
- exports.withCommandDocMetadata = withCommandDocMetadata;
115
+ exports.getSelectedCommandUsage = getSelectedCommandUsage;
116
+ exports.scopeCommandDocMetadata = scopeCommandDocMetadata;
117
+ exports.withCommandDocMetadata = withCommandDocMetadata;
118
+ exports.withSelectedCommandUsage = withSelectedCommandUsage;
@@ -1,6 +1,24 @@
1
+ import { scopeCommandUsageId } from "./command-usage.js";
2
+
1
3
  //#region src/internal/command-doc-metadata.ts
4
+ const selectedCommandUsage = /* @__PURE__ */ new WeakMap();
5
+ /** Reads command occurrences selected by final parser state. @internal */
6
+ function getSelectedCommandUsage(metadata) {
7
+ return metadata == null ? [] : selectedCommandUsage.get(metadata) ?? [];
8
+ }
9
+ /** Attaches selection without adding public metadata properties. @internal */
10
+ function withSelectedCommandUsage(metadata, selected) {
11
+ const result = withOrigin(metadata ?? {}, metadata?.origin ?? "entry");
12
+ selectedCommandUsage.set(result, selected);
13
+ return result;
14
+ }
15
+ /** Maps selected commands to the same child scope as its usage. @internal */
16
+ function scopeCommandDocMetadata(metadata, scope) {
17
+ return metadata == null ? void 0 : withSelectedCommandUsage(metadata, getSelectedCommandUsage(metadata).map((id) => scopeCommandUsageId(scope, id)));
18
+ }
2
19
  function withOrigin(metadata, origin) {
3
20
  const result = { ...metadata };
21
+ selectedCommandUsage.set(result, getSelectedCommandUsage(metadata));
4
22
  Object.defineProperty(result, "origin", {
5
23
  value: origin,
6
24
  enumerable: false
@@ -22,11 +40,11 @@ function getCommandDocMetadata(docs) {
22
40
  const customPage = origin === "entry" && (docs.brief !== carrier.brief || docs.footer !== carrier.footer);
23
41
  const description = origin === "entry" && !customPage || docs.description === carrier.description ? carrier.metadata.description : docs.description;
24
42
  const footer = docs.footer === carrier.footer ? carrier.metadata.footer : docs.footer;
25
- return withOrigin({
43
+ return withSelectedCommandUsage(withOrigin({
26
44
  ...brief == null ? {} : { brief },
27
45
  ...description == null ? {} : { description },
28
46
  ...footer == null ? {} : { footer }
29
- }, customPage ? "custom" : origin);
47
+ }, customPage ? "custom" : origin), getSelectedCommandUsage(carrier.metadata));
30
48
  }
31
49
  const metadata = docs[commandDocMetadata];
32
50
  if (metadata != null) return metadata;
@@ -66,7 +84,7 @@ function withCommandDocMetadata(docs, metadata) {
66
84
  * @param includeCustom Whether to retain custom page fields inside merge().
67
85
  * @returns The first defined value from children with the same origin.
68
86
  */
69
- function collectCommandDocMetadata(current, docs, includeCustom = false) {
87
+ function collectCommandPageMetadata(current, docs, includeCustom = false) {
70
88
  const next = getCommandDocMetadata(docs);
71
89
  if (next == null) return current;
72
90
  const origin = next.origin ?? "entry";
@@ -82,6 +100,14 @@ function collectCommandDocMetadata(current, docs, includeCustom = false) {
82
100
  ...footer == null ? {} : { footer }
83
101
  }, origin);
84
102
  }
103
+ /** Collects page fields and all selected command occurrences. @internal */
104
+ function collectCommandDocMetadata(current, docs, includeCustom = false, scope) {
105
+ const next = getCommandDocMetadata(docs);
106
+ const selected = getSelectedCommandUsage(next);
107
+ const result = collectCommandPageMetadata(current, docs, includeCustom);
108
+ const combined = [...getSelectedCommandUsage(current), ...scope == null ? selected : selected.map((id) => scopeCommandUsageId(scope, id))];
109
+ return combined.length === 0 ? result : withSelectedCommandUsage(result, combined);
110
+ }
85
111
 
86
112
  //#endregion
87
- export { collectCommandDocMetadata, getCommandDocMetadata, withCommandDocMetadata };
113
+ export { collectCommandDocMetadata, getCommandDocMetadata, getSelectedCommandUsage, scopeCommandDocMetadata, withCommandDocMetadata, withSelectedCommandUsage };
@@ -0,0 +1,52 @@
1
+
2
+ //#region src/internal/command-usage.ts
3
+ const commandUsageIds = /* @__PURE__ */ new WeakMap();
4
+ /** Associates a command usage leaf with its parser occurrence. @internal */
5
+ function identifyCommandUsage(term, id) {
6
+ commandUsageIds.set(term, id);
7
+ return term;
8
+ }
9
+ /** Reads a command usage leaf's private identity. @internal */
10
+ function getCommandUsageId(term) {
11
+ return commandUsageIds.get(term);
12
+ }
13
+ /** Preserves private identity when cloning a usage leaf. @internal */
14
+ function copyCommandUsageId(source, target) {
15
+ const id = commandUsageIds.get(source);
16
+ if (id != null) commandUsageIds.set(target, id);
17
+ return target;
18
+ }
19
+ /** Distinguishes repeated uses of one parser in different children. @internal */
20
+ function scopeCommandUsageId(scope, id) {
21
+ let scoped = scope.get(id);
22
+ if (scoped == null) {
23
+ scoped = {};
24
+ scope.set(id, scoped);
25
+ }
26
+ return scoped;
27
+ }
28
+ /** Copies usage with identities scoped to this child occurrence. @internal */
29
+ function scopeCommandUsage(usage, scope) {
30
+ return usage.map((term) => {
31
+ if (term.type === "command") {
32
+ const id = getCommandUsageId(term);
33
+ return id == null ? term : identifyCommandUsage({ ...term }, scopeCommandUsageId(scope, id));
34
+ }
35
+ if (term.type === "optional" || term.type === "multiple") return {
36
+ ...term,
37
+ terms: scopeCommandUsage(term.terms, scope)
38
+ };
39
+ if (term.type === "exclusive") return {
40
+ ...term,
41
+ terms: term.terms.map((branch) => scopeCommandUsage(branch, scope))
42
+ };
43
+ return term;
44
+ });
45
+ }
46
+
47
+ //#endregion
48
+ exports.copyCommandUsageId = copyCommandUsageId;
49
+ exports.getCommandUsageId = getCommandUsageId;
50
+ exports.identifyCommandUsage = identifyCommandUsage;
51
+ exports.scopeCommandUsage = scopeCommandUsage;
52
+ exports.scopeCommandUsageId = scopeCommandUsageId;
@@ -0,0 +1,47 @@
1
+ //#region src/internal/command-usage.ts
2
+ const commandUsageIds = /* @__PURE__ */ new WeakMap();
3
+ /** Associates a command usage leaf with its parser occurrence. @internal */
4
+ function identifyCommandUsage(term, id) {
5
+ commandUsageIds.set(term, id);
6
+ return term;
7
+ }
8
+ /** Reads a command usage leaf's private identity. @internal */
9
+ function getCommandUsageId(term) {
10
+ return commandUsageIds.get(term);
11
+ }
12
+ /** Preserves private identity when cloning a usage leaf. @internal */
13
+ function copyCommandUsageId(source, target) {
14
+ const id = commandUsageIds.get(source);
15
+ if (id != null) commandUsageIds.set(target, id);
16
+ return target;
17
+ }
18
+ /** Distinguishes repeated uses of one parser in different children. @internal */
19
+ function scopeCommandUsageId(scope, id) {
20
+ let scoped = scope.get(id);
21
+ if (scoped == null) {
22
+ scoped = {};
23
+ scope.set(id, scoped);
24
+ }
25
+ return scoped;
26
+ }
27
+ /** Copies usage with identities scoped to this child occurrence. @internal */
28
+ function scopeCommandUsage(usage, scope) {
29
+ return usage.map((term) => {
30
+ if (term.type === "command") {
31
+ const id = getCommandUsageId(term);
32
+ return id == null ? term : identifyCommandUsage({ ...term }, scopeCommandUsageId(scope, id));
33
+ }
34
+ if (term.type === "optional" || term.type === "multiple") return {
35
+ ...term,
36
+ terms: scopeCommandUsage(term.terms, scope)
37
+ };
38
+ if (term.type === "exclusive") return {
39
+ ...term,
40
+ terms: term.terms.map((branch) => scopeCommandUsage(branch, scope))
41
+ };
42
+ return term;
43
+ });
44
+ }
45
+
46
+ //#endregion
47
+ export { copyCommandUsageId, getCommandUsageId, identifyCommandUsage, scopeCommandUsage, scopeCommandUsageId };
@@ -1,5 +1,7 @@
1
1
  const require_annotations = require('./annotations.cjs');
2
2
  const require_message = require('../message.cjs');
3
+ const require_command_usage = require('./command-usage.cjs');
4
+ const require_command_doc_metadata = require('./command-doc-metadata.cjs');
3
5
  const require_usage = require('../usage.cjs');
4
6
  const require_doc = require('../doc.cjs');
5
7
  const require_mode_dispatch = require('./mode-dispatch.cjs');
@@ -527,20 +529,66 @@ function suggest(parser, args, options) {
527
529
  *
528
530
  * @param term The usage term to search in
529
531
  * @param commandName The command name to find
532
+ * @param selectedCommandUsage The command occurrences selected by parser state
530
533
  * @returns The expanded usage terms if found, null otherwise
531
534
  */
532
- function findCommandInExclusive(term, commandName) {
535
+ function findCommandInExclusive(term, commandName, selectedCommandUsage) {
536
+ return findCommandInExclusiveMatching(term, commandName, selectedCommandUsage) ?? findCommandInExclusiveMatching(term, commandName, selectedCommandUsage, false);
537
+ }
538
+ function findCommandInExclusiveMatching(term, commandName, selectedCommandUsage, requireSelectedIdentity = true) {
533
539
  if (term.type !== "exclusive") return null;
534
540
  for (const termGroup of term.terms) {
535
541
  const firstTerm = termGroup[0];
536
- if (firstTerm?.type === "command" && firstTerm.name === commandName) return termGroup;
542
+ if (firstTerm?.type === "command" && firstTerm.name === commandName) {
543
+ const id = require_command_usage.getCommandUsageId(firstTerm);
544
+ if (id == null ? !requireSelectedIdentity : selectedCommandUsage.has(id)) return termGroup;
545
+ }
546
+ if (requireSelectedIdentity && (firstTerm?.type === "optional" || firstTerm?.type === "multiple") && hasSelectedLeadingCommand(firstTerm.terms, commandName, selectedCommandUsage)) return termGroup;
537
547
  if (firstTerm?.type === "exclusive") {
538
- const found = findCommandInExclusive(firstTerm, commandName);
548
+ const found = findCommandInExclusiveMatching(firstTerm, commandName, selectedCommandUsage, requireSelectedIdentity);
539
549
  if (found) return [...found, ...termGroup.slice(1)];
540
550
  }
541
551
  }
542
552
  return null;
543
553
  }
554
+ function hasSelectedLeadingCommand(usage, commandName, selectedCommandUsage) {
555
+ const first = usage[0];
556
+ if (first?.type === "command") {
557
+ const id = require_command_usage.getCommandUsageId(first);
558
+ return first.name === commandName && id != null && selectedCommandUsage.has(id);
559
+ }
560
+ if (first?.type === "optional" || first?.type === "multiple") return hasSelectedLeadingCommand(first.terms, commandName, selectedCommandUsage);
561
+ return first?.type === "exclusive" && first.terms.some((branch) => hasSelectedLeadingCommand(branch, commandName, selectedCommandUsage));
562
+ }
563
+ function applyWrappedCommandUsageLine(term, commandName, selectedCommandUsage) {
564
+ const candidates = [];
565
+ const visit = (terms, rebuild) => {
566
+ const first = terms[0];
567
+ if (first?.type === "command") {
568
+ const id = require_command_usage.getCommandUsageId(first);
569
+ if (first.name === commandName && id != null && selectedCommandUsage.has(id)) candidates.push({
570
+ command: first,
571
+ tail: terms.slice(1),
572
+ replace: (tail$1) => rebuild([first, ...tail$1])
573
+ });
574
+ } else if (first?.type === "optional" || first?.type === "multiple") visit(first.terms, (children) => rebuild([{
575
+ ...first,
576
+ terms: children
577
+ }, ...terms.slice(1)]));
578
+ else if (first?.type === "exclusive") first.terms.forEach((branch, index) => {
579
+ visit(branch, (children) => rebuild([{
580
+ ...first,
581
+ terms: first.terms.map((other, otherIndex) => otherIndex === index ? children : other)
582
+ }, ...terms.slice(1)]));
583
+ });
584
+ };
585
+ visit([term], (terms) => terms[0]);
586
+ if (candidates.length !== 1) return term;
587
+ const { command, tail, replace } = candidates[0];
588
+ if (command.usageLine == null) return term;
589
+ const customUsageLine = typeof command.usageLine === "function" ? command.usageLine(require_usage.cloneUsage(tail)) : command.usageLine;
590
+ return replace(require_usage.normalizeUsage(customUsageLine));
591
+ }
544
592
  /**
545
593
  * Generates a documentation page for a synchronous parser.
546
594
  *
@@ -651,10 +699,13 @@ async function getDocPageAsyncImpl(parser, args, options) {
651
699
  */
652
700
  function buildDocPage(parser, context, args) {
653
701
  let effectiveArgs = args;
654
- let { brief, description, fragments, footer } = parser.getDocFragments({
702
+ let matchedCommandPath = context.exec?.commandPath ?? [];
703
+ const docs = parser.getDocFragments({
655
704
  kind: "available",
656
705
  state: context.state
657
706
  }, void 0);
707
+ let selectedCommandUsage = require_command_doc_metadata.getSelectedCommandUsage(require_command_doc_metadata.getCommandDocMetadata(docs));
708
+ let { brief, description, fragments, footer } = docs;
658
709
  if (args.length === 0 && Reflect.get(parser, Symbol.for("@optique/core/commandParser")) === true && fragments.length === 1 && fragments[0].type === "entry" && fragments[0].term.type === "command") {
659
710
  const cmdName = fragments[0].term.name;
660
711
  const matchedState = require_annotations.inheritAnnotations(context.state, ["matched", cmdName]);
@@ -663,7 +714,9 @@ function buildDocPage(parser, context, args) {
663
714
  state: matchedState
664
715
  }, void 0);
665
716
  ({brief, description, fragments, footer} = matched);
717
+ selectedCommandUsage = require_command_doc_metadata.getSelectedCommandUsage(require_command_doc_metadata.getCommandDocMetadata(matched));
666
718
  effectiveArgs = [cmdName];
719
+ matchedCommandPath = [cmdName];
667
720
  }
668
721
  const buildingSections = [];
669
722
  let untitledSection = null;
@@ -698,9 +751,15 @@ function buildDocPage(parser, context, args) {
698
751
  }
699
752
  }
700
753
  const sections = buildingSections;
754
+ const selectedCommandUsageIds = new Set(selectedCommandUsage);
701
755
  const usage = [...require_usage.normalizeUsage(parser.usage)];
702
756
  const maybeApplyCommandUsageLine = (term, arg, isLastArg, usageIndex) => {
703
- if (term?.type !== "command" || term.name !== arg || !isLastArg || term.usageLine == null) return;
757
+ if (!isLastArg) return;
758
+ if (term?.type === "optional" || term?.type === "multiple" || term?.type === "exclusive") {
759
+ usage[usageIndex] = applyWrappedCommandUsageLine(term, arg, selectedCommandUsageIds);
760
+ return;
761
+ }
762
+ if (term?.type !== "command" || term.name !== arg || term.usageLine == null) return;
704
763
  const defaultUsageLine = require_usage.cloneUsage(usage.slice(usageIndex + 1));
705
764
  const customUsageLine = typeof term.usageLine === "function" ? term.usageLine(defaultUsageLine) : term.usageLine;
706
765
  const normalizedCustomUsageLine = require_usage.normalizeUsage(customUsageLine);
@@ -712,7 +771,7 @@ function buildDocPage(parser, context, args) {
712
771
  if (i >= usage.length) break;
713
772
  let term = usage[i];
714
773
  if (term.type === "exclusive") {
715
- const found = findCommandInExclusive(term, arg);
774
+ const found = findCommandInExclusive(term, arg, selectedCommandUsageIds);
716
775
  if (found) {
717
776
  usage.splice(i, 1, ...found);
718
777
  term = usage[i];
@@ -731,13 +790,58 @@ function buildDocPage(parser, context, args) {
731
790
  }
732
791
  }
733
792
  return {
734
- usage,
793
+ usage: revealMatchedCommandUsage(usage, matchedCommandPath, selectedCommandUsageIds),
735
794
  sections,
736
795
  ...brief != null && { brief: require_message.cloneMessage(brief) },
737
796
  ...description != null && { description: require_message.cloneMessage(description) },
738
797
  ...footer != null && { footer: require_message.cloneMessage(footer) }
739
798
  };
740
799
  }
800
+ function revealMatchedCommandUsage(usage, matchedCommandPath, selectedCommandUsage) {
801
+ return revealMatchedCommandUsageTerms(usage, matchedCommandPath, 0, selectedCommandUsage)[0];
802
+ }
803
+ function revealMatchedCommandUsageTerms(usage, matchedCommandPath, pathIndex, selectedCommandUsage, allowNameFallback = true) {
804
+ const terms = [];
805
+ let nextPathIndex = pathIndex;
806
+ let nameFallbackEnabled = allowNameFallback;
807
+ for (let index = 0; index < usage.length; index++) {
808
+ const term = usage[index];
809
+ if (term.type === "command") {
810
+ const id = require_command_usage.getCommandUsageId(term);
811
+ if (id != null) {
812
+ if (selectedCommandUsage.has(id)) {
813
+ const { hidden: _hidden$1,...revealed$1 } = term;
814
+ terms.push(revealed$1);
815
+ if (term.name === matchedCommandPath[nextPathIndex]) nextPathIndex++;
816
+ } else terms.push(term);
817
+ continue;
818
+ }
819
+ if (!nameFallbackEnabled || term.name !== matchedCommandPath[nextPathIndex]) {
820
+ nameFallbackEnabled = false;
821
+ terms.push(term);
822
+ continue;
823
+ }
824
+ const { hidden: _hidden,...revealed } = term;
825
+ terms.push(revealed);
826
+ nextPathIndex++;
827
+ } else if (term.type === "optional" || term.type === "multiple") {
828
+ const [nested, afterTerm] = revealMatchedCommandUsageTerms(term.terms, matchedCommandPath, nextPathIndex, selectedCommandUsage, nameFallbackEnabled);
829
+ terms.push({
830
+ ...term,
831
+ terms: nested
832
+ });
833
+ nextPathIndex = afterTerm;
834
+ } else if (term.type === "exclusive") {
835
+ const branches = term.terms.map((branch) => revealMatchedCommandUsageTerms(branch, matchedCommandPath, nextPathIndex, selectedCommandUsage, nameFallbackEnabled));
836
+ terms.push({
837
+ ...term,
838
+ terms: branches.map(([branch]) => branch)
839
+ });
840
+ nextPathIndex = Math.max(nextPathIndex, ...branches.map(([, afterBranch]) => afterBranch));
841
+ } else terms.push(term);
842
+ }
843
+ return [terms, nextPathIndex];
844
+ }
741
845
 
742
846
  //#endregion
743
847
  exports.annotationWrapperRequiresSourceBindingKey = annotationWrapperRequiresSourceBindingKey;