@optique/core 1.4.0-dev.2731 → 1.4.0-dev.2737
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/constructs.cjs +19 -9
- package/dist/constructs.js +19 -9
- package/dist/doc.cjs +2 -2
- package/dist/doc.d.cts +10 -2
- package/dist/doc.d.ts +10 -2
- package/dist/doc.js +2 -2
- package/dist/execution-context.cjs +3 -2
- package/dist/execution-context.js +3 -2
- package/dist/facade.cjs +13 -9
- package/dist/facade.d.cts +4 -3
- package/dist/facade.d.ts +4 -3
- package/dist/facade.js +13 -9
- package/dist/internal/command-doc-policy.cjs +168 -0
- package/dist/internal/command-doc-policy.d.cts +77 -0
- package/dist/internal/command-doc-policy.d.ts +77 -0
- package/dist/internal/command-doc-policy.js +160 -0
- package/dist/internal/parser.cjs +8 -4
- package/dist/internal/parser.js +8 -4
- package/dist/primitives.cjs +20 -3
- package/dist/primitives.d.cts +10 -1
- package/dist/primitives.d.ts +10 -1
- package/dist/primitives.js +20 -3
- package/package.json +10 -2
- package/skills/optique/SKILL.md +3 -3
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/internal/command-doc-policy.ts
|
|
3
|
+
const policyKey = Symbol("commandDocPolicy");
|
|
4
|
+
const barePolicyKey = Symbol("bareCommandDocPolicy");
|
|
5
|
+
function policy(exec) {
|
|
6
|
+
return exec?.[policyKey];
|
|
7
|
+
}
|
|
8
|
+
function samePath(a, b) {
|
|
9
|
+
return a.length === b.length && a.every((part, i) => part === b[i]);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Enables command policy tracking for document generation only.
|
|
13
|
+
* @param exec The initial execution context.
|
|
14
|
+
* @returns A context with an empty immutable policy trace.
|
|
15
|
+
* @internal
|
|
16
|
+
* @since 1.4.0
|
|
17
|
+
*/
|
|
18
|
+
function trackCommandDocPolicy(exec) {
|
|
19
|
+
return {
|
|
20
|
+
...exec,
|
|
21
|
+
[policyKey]: { records: [] }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Records a successfully matched command occurrence.
|
|
26
|
+
* @param exec The command's execution context.
|
|
27
|
+
* @param id The constructor identity.
|
|
28
|
+
* @param showUsage The declared command policy.
|
|
29
|
+
* @returns A new context when tracking is enabled, otherwise the original.
|
|
30
|
+
* @internal
|
|
31
|
+
* @since 1.4.0
|
|
32
|
+
*/
|
|
33
|
+
function matchCommandDocPolicy(exec, id, showUsage) {
|
|
34
|
+
const current = policy(exec);
|
|
35
|
+
if (exec == null || current == null) return exec;
|
|
36
|
+
const scope = {
|
|
37
|
+
id,
|
|
38
|
+
path: [...exec.path],
|
|
39
|
+
parent: current.active,
|
|
40
|
+
showUsage
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
...exec,
|
|
44
|
+
[policyKey]: {
|
|
45
|
+
...current,
|
|
46
|
+
records: [...current.records, scope]
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Enters the actual parent command while delegating to its inner parser.
|
|
52
|
+
* @param exec The context before appending the inner command path.
|
|
53
|
+
* @param id The command constructor identity.
|
|
54
|
+
* @returns A child context with the matching occurrence as active scope.
|
|
55
|
+
* @internal
|
|
56
|
+
* @since 1.4.0
|
|
57
|
+
*/
|
|
58
|
+
function enterCommandDocPolicy(exec, id) {
|
|
59
|
+
const current = policy(exec);
|
|
60
|
+
if (exec == null || current == null) return exec;
|
|
61
|
+
const active = current.records.findLast((scope) => scope.id === id && samePath(scope.path, exec.path));
|
|
62
|
+
return {
|
|
63
|
+
...exec,
|
|
64
|
+
[policyKey]: {
|
|
65
|
+
...current,
|
|
66
|
+
active
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Transfers the selected child's policy and restores the caller's scope.
|
|
72
|
+
* Empty child records deliberately replace previous records.
|
|
73
|
+
* @param parent The caller's context.
|
|
74
|
+
* @param child The selected child's context.
|
|
75
|
+
* @param merged The otherwise merged context.
|
|
76
|
+
* @returns The merged context with document policy forwarding.
|
|
77
|
+
* @internal
|
|
78
|
+
* @since 1.4.0
|
|
79
|
+
*/
|
|
80
|
+
function mergeCommandDocPolicy(parent, child, merged) {
|
|
81
|
+
const parentPolicy = policy(parent);
|
|
82
|
+
const childPolicy = policy(child);
|
|
83
|
+
if (parentPolicy == null && childPolicy == null) return merged;
|
|
84
|
+
return {
|
|
85
|
+
...merged,
|
|
86
|
+
[policyKey]: {
|
|
87
|
+
active: parentPolicy?.active,
|
|
88
|
+
records: childPolicy?.records ?? []
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Removes an abandoned parser branch from a speculative context copy.
|
|
94
|
+
* @param exec The context before trying a replacement branch.
|
|
95
|
+
* @param path The structural path of the abandoned branch.
|
|
96
|
+
* @returns A context containing only retained scope occurrences.
|
|
97
|
+
* @internal
|
|
98
|
+
* @since 1.4.0
|
|
99
|
+
*/
|
|
100
|
+
function withoutCommandDocPolicySubtree(exec, path) {
|
|
101
|
+
const current = policy(exec);
|
|
102
|
+
if (exec == null || current == null) return exec;
|
|
103
|
+
const retained = /* @__PURE__ */ new Set();
|
|
104
|
+
const records = current.records.filter((scope) => {
|
|
105
|
+
const inside = scope.path.length >= path.length && path.every((part, i) => part === scope.path[i]);
|
|
106
|
+
if (inside || scope.parent != null && !retained.has(scope.parent)) return false;
|
|
107
|
+
retained.add(scope);
|
|
108
|
+
return true;
|
|
109
|
+
});
|
|
110
|
+
let active = current.active;
|
|
111
|
+
while (active != null && !retained.has(active)) active = active.parent;
|
|
112
|
+
return {
|
|
113
|
+
...exec,
|
|
114
|
+
[policyKey]: {
|
|
115
|
+
active,
|
|
116
|
+
records
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolves the selected command's nearest explicit ancestor policy.
|
|
122
|
+
* @param exec The final successful document parsing context.
|
|
123
|
+
* @returns A command default, or undefined when no selected command sets one.
|
|
124
|
+
* @internal
|
|
125
|
+
* @since 1.4.0
|
|
126
|
+
*/
|
|
127
|
+
function getCommandDocPolicy(exec) {
|
|
128
|
+
let scope = policy(exec)?.records.at(-1);
|
|
129
|
+
while (scope != null) {
|
|
130
|
+
if (scope.showUsage != null) return scope.showUsage;
|
|
131
|
+
scope = scope.parent;
|
|
132
|
+
}
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Stores a bare command's static default, preserved by transparent spreads.
|
|
137
|
+
* @param parser The newly constructed command parser.
|
|
138
|
+
* @param showUsage Its declared policy.
|
|
139
|
+
* @internal
|
|
140
|
+
* @since 1.4.0
|
|
141
|
+
*/
|
|
142
|
+
function defineBareCommandDocPolicy(parser, showUsage) {
|
|
143
|
+
Object.defineProperty(parser, barePolicyKey, {
|
|
144
|
+
value: showUsage,
|
|
145
|
+
enumerable: true
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Reads static policy after the existing bare-command brand check.
|
|
150
|
+
* @param parser The branded command parser.
|
|
151
|
+
* @returns Its declared policy, or undefined.
|
|
152
|
+
* @internal
|
|
153
|
+
* @since 1.4.0
|
|
154
|
+
*/
|
|
155
|
+
function getBareCommandDocPolicy(parser) {
|
|
156
|
+
const value = Reflect.get(parser, barePolicyKey);
|
|
157
|
+
return typeof value === "boolean" ? value : void 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
//#endregion
|
|
161
|
+
exports.defineBareCommandDocPolicy = defineBareCommandDocPolicy;
|
|
162
|
+
exports.enterCommandDocPolicy = enterCommandDocPolicy;
|
|
163
|
+
exports.getBareCommandDocPolicy = getBareCommandDocPolicy;
|
|
164
|
+
exports.getCommandDocPolicy = getCommandDocPolicy;
|
|
165
|
+
exports.matchCommandDocPolicy = matchCommandDocPolicy;
|
|
166
|
+
exports.mergeCommandDocPolicy = mergeCommandDocPolicy;
|
|
167
|
+
exports.trackCommandDocPolicy = trackCommandDocPolicy;
|
|
168
|
+
exports.withoutCommandDocPolicySubtree = withoutCommandDocPolicySubtree;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ExecutionContext } from "./parser.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/command-doc-policy.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Enables command policy tracking for document generation only.
|
|
7
|
+
* @param exec The initial execution context.
|
|
8
|
+
* @returns A context with an empty immutable policy trace.
|
|
9
|
+
* @internal
|
|
10
|
+
* @since 1.4.0
|
|
11
|
+
*/
|
|
12
|
+
declare function trackCommandDocPolicy(exec: ExecutionContext): ExecutionContext;
|
|
13
|
+
/**
|
|
14
|
+
* Records a successfully matched command occurrence.
|
|
15
|
+
* @param exec The command's execution context.
|
|
16
|
+
* @param id The constructor identity.
|
|
17
|
+
* @param showUsage The declared command policy.
|
|
18
|
+
* @returns A new context when tracking is enabled, otherwise the original.
|
|
19
|
+
* @internal
|
|
20
|
+
* @since 1.4.0
|
|
21
|
+
*/
|
|
22
|
+
declare function matchCommandDocPolicy(exec: ExecutionContext | undefined, id: symbol, showUsage: boolean | undefined): ExecutionContext | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Enters the actual parent command while delegating to its inner parser.
|
|
25
|
+
* @param exec The context before appending the inner command path.
|
|
26
|
+
* @param id The command constructor identity.
|
|
27
|
+
* @returns A child context with the matching occurrence as active scope.
|
|
28
|
+
* @internal
|
|
29
|
+
* @since 1.4.0
|
|
30
|
+
*/
|
|
31
|
+
declare function enterCommandDocPolicy(exec: ExecutionContext | undefined, id: symbol): ExecutionContext | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Transfers the selected child's policy and restores the caller's scope.
|
|
34
|
+
* Empty child records deliberately replace previous records.
|
|
35
|
+
* @param parent The caller's context.
|
|
36
|
+
* @param child The selected child's context.
|
|
37
|
+
* @param merged The otherwise merged context.
|
|
38
|
+
* @returns The merged context with document policy forwarding.
|
|
39
|
+
* @internal
|
|
40
|
+
* @since 1.4.0
|
|
41
|
+
*/
|
|
42
|
+
declare function mergeCommandDocPolicy(parent: ExecutionContext | undefined, child: ExecutionContext | undefined, merged: ExecutionContext): ExecutionContext;
|
|
43
|
+
/**
|
|
44
|
+
* Removes an abandoned parser branch from a speculative context copy.
|
|
45
|
+
* @param exec The context before trying a replacement branch.
|
|
46
|
+
* @param path The structural path of the abandoned branch.
|
|
47
|
+
* @returns A context containing only retained scope occurrences.
|
|
48
|
+
* @internal
|
|
49
|
+
* @since 1.4.0
|
|
50
|
+
*/
|
|
51
|
+
declare function withoutCommandDocPolicySubtree(exec: ExecutionContext | undefined, path: readonly PropertyKey[]): ExecutionContext | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Resolves the selected command's nearest explicit ancestor policy.
|
|
54
|
+
* @param exec The final successful document parsing context.
|
|
55
|
+
* @returns A command default, or undefined when no selected command sets one.
|
|
56
|
+
* @internal
|
|
57
|
+
* @since 1.4.0
|
|
58
|
+
*/
|
|
59
|
+
declare function getCommandDocPolicy(exec: ExecutionContext | undefined): boolean | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Stores a bare command's static default, preserved by transparent spreads.
|
|
62
|
+
* @param parser The newly constructed command parser.
|
|
63
|
+
* @param showUsage Its declared policy.
|
|
64
|
+
* @internal
|
|
65
|
+
* @since 1.4.0
|
|
66
|
+
*/
|
|
67
|
+
declare function defineBareCommandDocPolicy(parser: object, showUsage: boolean | undefined): void;
|
|
68
|
+
/**
|
|
69
|
+
* Reads static policy after the existing bare-command brand check.
|
|
70
|
+
* @param parser The branded command parser.
|
|
71
|
+
* @returns Its declared policy, or undefined.
|
|
72
|
+
* @internal
|
|
73
|
+
* @since 1.4.0
|
|
74
|
+
*/
|
|
75
|
+
declare function getBareCommandDocPolicy(parser: object): boolean | undefined;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { defineBareCommandDocPolicy, enterCommandDocPolicy, getBareCommandDocPolicy, getCommandDocPolicy, matchCommandDocPolicy, mergeCommandDocPolicy, trackCommandDocPolicy, withoutCommandDocPolicySubtree };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ExecutionContext } from "./parser.js";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/command-doc-policy.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Enables command policy tracking for document generation only.
|
|
7
|
+
* @param exec The initial execution context.
|
|
8
|
+
* @returns A context with an empty immutable policy trace.
|
|
9
|
+
* @internal
|
|
10
|
+
* @since 1.4.0
|
|
11
|
+
*/
|
|
12
|
+
declare function trackCommandDocPolicy(exec: ExecutionContext): ExecutionContext;
|
|
13
|
+
/**
|
|
14
|
+
* Records a successfully matched command occurrence.
|
|
15
|
+
* @param exec The command's execution context.
|
|
16
|
+
* @param id The constructor identity.
|
|
17
|
+
* @param showUsage The declared command policy.
|
|
18
|
+
* @returns A new context when tracking is enabled, otherwise the original.
|
|
19
|
+
* @internal
|
|
20
|
+
* @since 1.4.0
|
|
21
|
+
*/
|
|
22
|
+
declare function matchCommandDocPolicy(exec: ExecutionContext | undefined, id: symbol, showUsage: boolean | undefined): ExecutionContext | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Enters the actual parent command while delegating to its inner parser.
|
|
25
|
+
* @param exec The context before appending the inner command path.
|
|
26
|
+
* @param id The command constructor identity.
|
|
27
|
+
* @returns A child context with the matching occurrence as active scope.
|
|
28
|
+
* @internal
|
|
29
|
+
* @since 1.4.0
|
|
30
|
+
*/
|
|
31
|
+
declare function enterCommandDocPolicy(exec: ExecutionContext | undefined, id: symbol): ExecutionContext | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Transfers the selected child's policy and restores the caller's scope.
|
|
34
|
+
* Empty child records deliberately replace previous records.
|
|
35
|
+
* @param parent The caller's context.
|
|
36
|
+
* @param child The selected child's context.
|
|
37
|
+
* @param merged The otherwise merged context.
|
|
38
|
+
* @returns The merged context with document policy forwarding.
|
|
39
|
+
* @internal
|
|
40
|
+
* @since 1.4.0
|
|
41
|
+
*/
|
|
42
|
+
declare function mergeCommandDocPolicy(parent: ExecutionContext | undefined, child: ExecutionContext | undefined, merged: ExecutionContext): ExecutionContext;
|
|
43
|
+
/**
|
|
44
|
+
* Removes an abandoned parser branch from a speculative context copy.
|
|
45
|
+
* @param exec The context before trying a replacement branch.
|
|
46
|
+
* @param path The structural path of the abandoned branch.
|
|
47
|
+
* @returns A context containing only retained scope occurrences.
|
|
48
|
+
* @internal
|
|
49
|
+
* @since 1.4.0
|
|
50
|
+
*/
|
|
51
|
+
declare function withoutCommandDocPolicySubtree(exec: ExecutionContext | undefined, path: readonly PropertyKey[]): ExecutionContext | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Resolves the selected command's nearest explicit ancestor policy.
|
|
54
|
+
* @param exec The final successful document parsing context.
|
|
55
|
+
* @returns A command default, or undefined when no selected command sets one.
|
|
56
|
+
* @internal
|
|
57
|
+
* @since 1.4.0
|
|
58
|
+
*/
|
|
59
|
+
declare function getCommandDocPolicy(exec: ExecutionContext | undefined): boolean | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Stores a bare command's static default, preserved by transparent spreads.
|
|
62
|
+
* @param parser The newly constructed command parser.
|
|
63
|
+
* @param showUsage Its declared policy.
|
|
64
|
+
* @internal
|
|
65
|
+
* @since 1.4.0
|
|
66
|
+
*/
|
|
67
|
+
declare function defineBareCommandDocPolicy(parser: object, showUsage: boolean | undefined): void;
|
|
68
|
+
/**
|
|
69
|
+
* Reads static policy after the existing bare-command brand check.
|
|
70
|
+
* @param parser The branded command parser.
|
|
71
|
+
* @returns Its declared policy, or undefined.
|
|
72
|
+
* @internal
|
|
73
|
+
* @since 1.4.0
|
|
74
|
+
*/
|
|
75
|
+
declare function getBareCommandDocPolicy(parser: object): boolean | undefined;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { defineBareCommandDocPolicy, enterCommandDocPolicy, getBareCommandDocPolicy, getCommandDocPolicy, matchCommandDocPolicy, mergeCommandDocPolicy, trackCommandDocPolicy, withoutCommandDocPolicySubtree };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
//#region src/internal/command-doc-policy.ts
|
|
2
|
+
const policyKey = Symbol("commandDocPolicy");
|
|
3
|
+
const barePolicyKey = Symbol("bareCommandDocPolicy");
|
|
4
|
+
function policy(exec) {
|
|
5
|
+
return exec?.[policyKey];
|
|
6
|
+
}
|
|
7
|
+
function samePath(a, b) {
|
|
8
|
+
return a.length === b.length && a.every((part, i) => part === b[i]);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Enables command policy tracking for document generation only.
|
|
12
|
+
* @param exec The initial execution context.
|
|
13
|
+
* @returns A context with an empty immutable policy trace.
|
|
14
|
+
* @internal
|
|
15
|
+
* @since 1.4.0
|
|
16
|
+
*/
|
|
17
|
+
function trackCommandDocPolicy(exec) {
|
|
18
|
+
return {
|
|
19
|
+
...exec,
|
|
20
|
+
[policyKey]: { records: [] }
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Records a successfully matched command occurrence.
|
|
25
|
+
* @param exec The command's execution context.
|
|
26
|
+
* @param id The constructor identity.
|
|
27
|
+
* @param showUsage The declared command policy.
|
|
28
|
+
* @returns A new context when tracking is enabled, otherwise the original.
|
|
29
|
+
* @internal
|
|
30
|
+
* @since 1.4.0
|
|
31
|
+
*/
|
|
32
|
+
function matchCommandDocPolicy(exec, id, showUsage) {
|
|
33
|
+
const current = policy(exec);
|
|
34
|
+
if (exec == null || current == null) return exec;
|
|
35
|
+
const scope = {
|
|
36
|
+
id,
|
|
37
|
+
path: [...exec.path],
|
|
38
|
+
parent: current.active,
|
|
39
|
+
showUsage
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
...exec,
|
|
43
|
+
[policyKey]: {
|
|
44
|
+
...current,
|
|
45
|
+
records: [...current.records, scope]
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Enters the actual parent command while delegating to its inner parser.
|
|
51
|
+
* @param exec The context before appending the inner command path.
|
|
52
|
+
* @param id The command constructor identity.
|
|
53
|
+
* @returns A child context with the matching occurrence as active scope.
|
|
54
|
+
* @internal
|
|
55
|
+
* @since 1.4.0
|
|
56
|
+
*/
|
|
57
|
+
function enterCommandDocPolicy(exec, id) {
|
|
58
|
+
const current = policy(exec);
|
|
59
|
+
if (exec == null || current == null) return exec;
|
|
60
|
+
const active = current.records.findLast((scope) => scope.id === id && samePath(scope.path, exec.path));
|
|
61
|
+
return {
|
|
62
|
+
...exec,
|
|
63
|
+
[policyKey]: {
|
|
64
|
+
...current,
|
|
65
|
+
active
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Transfers the selected child's policy and restores the caller's scope.
|
|
71
|
+
* Empty child records deliberately replace previous records.
|
|
72
|
+
* @param parent The caller's context.
|
|
73
|
+
* @param child The selected child's context.
|
|
74
|
+
* @param merged The otherwise merged context.
|
|
75
|
+
* @returns The merged context with document policy forwarding.
|
|
76
|
+
* @internal
|
|
77
|
+
* @since 1.4.0
|
|
78
|
+
*/
|
|
79
|
+
function mergeCommandDocPolicy(parent, child, merged) {
|
|
80
|
+
const parentPolicy = policy(parent);
|
|
81
|
+
const childPolicy = policy(child);
|
|
82
|
+
if (parentPolicy == null && childPolicy == null) return merged;
|
|
83
|
+
return {
|
|
84
|
+
...merged,
|
|
85
|
+
[policyKey]: {
|
|
86
|
+
active: parentPolicy?.active,
|
|
87
|
+
records: childPolicy?.records ?? []
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Removes an abandoned parser branch from a speculative context copy.
|
|
93
|
+
* @param exec The context before trying a replacement branch.
|
|
94
|
+
* @param path The structural path of the abandoned branch.
|
|
95
|
+
* @returns A context containing only retained scope occurrences.
|
|
96
|
+
* @internal
|
|
97
|
+
* @since 1.4.0
|
|
98
|
+
*/
|
|
99
|
+
function withoutCommandDocPolicySubtree(exec, path) {
|
|
100
|
+
const current = policy(exec);
|
|
101
|
+
if (exec == null || current == null) return exec;
|
|
102
|
+
const retained = /* @__PURE__ */ new Set();
|
|
103
|
+
const records = current.records.filter((scope) => {
|
|
104
|
+
const inside = scope.path.length >= path.length && path.every((part, i) => part === scope.path[i]);
|
|
105
|
+
if (inside || scope.parent != null && !retained.has(scope.parent)) return false;
|
|
106
|
+
retained.add(scope);
|
|
107
|
+
return true;
|
|
108
|
+
});
|
|
109
|
+
let active = current.active;
|
|
110
|
+
while (active != null && !retained.has(active)) active = active.parent;
|
|
111
|
+
return {
|
|
112
|
+
...exec,
|
|
113
|
+
[policyKey]: {
|
|
114
|
+
active,
|
|
115
|
+
records
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Resolves the selected command's nearest explicit ancestor policy.
|
|
121
|
+
* @param exec The final successful document parsing context.
|
|
122
|
+
* @returns A command default, or undefined when no selected command sets one.
|
|
123
|
+
* @internal
|
|
124
|
+
* @since 1.4.0
|
|
125
|
+
*/
|
|
126
|
+
function getCommandDocPolicy(exec) {
|
|
127
|
+
let scope = policy(exec)?.records.at(-1);
|
|
128
|
+
while (scope != null) {
|
|
129
|
+
if (scope.showUsage != null) return scope.showUsage;
|
|
130
|
+
scope = scope.parent;
|
|
131
|
+
}
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Stores a bare command's static default, preserved by transparent spreads.
|
|
136
|
+
* @param parser The newly constructed command parser.
|
|
137
|
+
* @param showUsage Its declared policy.
|
|
138
|
+
* @internal
|
|
139
|
+
* @since 1.4.0
|
|
140
|
+
*/
|
|
141
|
+
function defineBareCommandDocPolicy(parser, showUsage) {
|
|
142
|
+
Object.defineProperty(parser, barePolicyKey, {
|
|
143
|
+
value: showUsage,
|
|
144
|
+
enumerable: true
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Reads static policy after the existing bare-command brand check.
|
|
149
|
+
* @param parser The branded command parser.
|
|
150
|
+
* @returns Its declared policy, or undefined.
|
|
151
|
+
* @internal
|
|
152
|
+
* @since 1.4.0
|
|
153
|
+
*/
|
|
154
|
+
function getBareCommandDocPolicy(parser) {
|
|
155
|
+
const value = Reflect.get(parser, barePolicyKey);
|
|
156
|
+
return typeof value === "boolean" ? value : void 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
export { defineBareCommandDocPolicy, enterCommandDocPolicy, getBareCommandDocPolicy, getCommandDocPolicy, matchCommandDocPolicy, mergeCommandDocPolicy, trackCommandDocPolicy, withoutCommandDocPolicySubtree };
|
package/dist/internal/parser.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_internal_annotations = require('./annotations.cjs');
|
|
2
|
+
const require_internal_command_doc_policy = require('./command-doc-policy.cjs');
|
|
2
3
|
const require_usage = require('../usage.cjs');
|
|
3
4
|
const require_message = require('../message.cjs');
|
|
4
5
|
const require_doc = require('../doc.cjs');
|
|
@@ -800,12 +801,12 @@ function getDocPage(parser, argsOrOptions, options) {
|
|
|
800
801
|
*/
|
|
801
802
|
function getDocPageSyncImpl(parser, args, options) {
|
|
802
803
|
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
803
|
-
const exec = {
|
|
804
|
+
const exec = require_internal_command_doc_policy.trackCommandDocPolicy({
|
|
804
805
|
usage: parser.usage,
|
|
805
806
|
phase: "parse",
|
|
806
807
|
path: [],
|
|
807
808
|
trace: require_input_trace.createInputTrace()
|
|
808
|
-
};
|
|
809
|
+
});
|
|
809
810
|
let context = createParserContext({
|
|
810
811
|
buffer: args,
|
|
811
812
|
state: initialState,
|
|
@@ -829,12 +830,12 @@ function getDocPageSyncImpl(parser, args, options) {
|
|
|
829
830
|
*/
|
|
830
831
|
async function getDocPageAsyncImpl(parser, args, options) {
|
|
831
832
|
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
832
|
-
const exec = {
|
|
833
|
+
const exec = require_internal_command_doc_policy.trackCommandDocPolicy({
|
|
833
834
|
usage: parser.usage,
|
|
834
835
|
phase: "parse",
|
|
835
836
|
path: [],
|
|
836
837
|
trace: require_input_trace.createInputTrace()
|
|
837
|
-
};
|
|
838
|
+
});
|
|
838
839
|
let context = createParserContext({
|
|
839
840
|
buffer: args,
|
|
840
841
|
state: initialState,
|
|
@@ -859,6 +860,7 @@ async function getDocPageAsyncImpl(parser, args, options) {
|
|
|
859
860
|
*/
|
|
860
861
|
function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
861
862
|
let effectiveArgs = args;
|
|
863
|
+
let showUsage = require_internal_command_doc_policy.getCommandDocPolicy(context.exec);
|
|
862
864
|
let { brief, description, fragments, footer, environmentBindings } = parser.getDocFragments({
|
|
863
865
|
kind: "available",
|
|
864
866
|
state: context.state
|
|
@@ -872,6 +874,7 @@ function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
|
872
874
|
}, void 0);
|
|
873
875
|
({brief, description, fragments, footer, environmentBindings} = matched);
|
|
874
876
|
effectiveArgs = [cmdName];
|
|
877
|
+
showUsage = require_internal_command_doc_policy.getBareCommandDocPolicy(parser);
|
|
875
878
|
}
|
|
876
879
|
const buildingSections = [];
|
|
877
880
|
let untitledSection = null;
|
|
@@ -949,6 +952,7 @@ function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
|
949
952
|
...binding.description != null && { description: require_message.cloneMessage(binding.description) }
|
|
950
953
|
}));
|
|
951
954
|
return {
|
|
955
|
+
...showUsage != null && { showUsage },
|
|
952
956
|
...visibleBindings != null && visibleBindings.length > 0 && { environmentBindings: visibleBindings },
|
|
953
957
|
usage: revealMatchedCommandUsage(usage, effectiveArgs, commandArgIndices ?? null),
|
|
954
958
|
sections,
|
package/dist/internal/parser.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { hasMeaningfulAnnotations, inheritAnnotations, injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotationWrapper } from "./annotations.js";
|
|
2
|
+
import { getBareCommandDocPolicy, getCommandDocPolicy, trackCommandDocPolicy } from "./command-doc-policy.js";
|
|
2
3
|
import { cloneUsage, isDocHidden, normalizeUsage } from "../usage.js";
|
|
3
4
|
import { cloneMessage, message } from "../message.js";
|
|
4
5
|
import { cloneDocEntry, isDocEntryHidden } from "../doc.js";
|
|
@@ -800,12 +801,12 @@ function getDocPage(parser, argsOrOptions, options) {
|
|
|
800
801
|
*/
|
|
801
802
|
function getDocPageSyncImpl(parser, args, options) {
|
|
802
803
|
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
803
|
-
const exec = {
|
|
804
|
+
const exec = trackCommandDocPolicy({
|
|
804
805
|
usage: parser.usage,
|
|
805
806
|
phase: "parse",
|
|
806
807
|
path: [],
|
|
807
808
|
trace: createInputTrace()
|
|
808
|
-
};
|
|
809
|
+
});
|
|
809
810
|
let context = createParserContext({
|
|
810
811
|
buffer: args,
|
|
811
812
|
state: initialState,
|
|
@@ -829,12 +830,12 @@ function getDocPageSyncImpl(parser, args, options) {
|
|
|
829
830
|
*/
|
|
830
831
|
async function getDocPageAsyncImpl(parser, args, options) {
|
|
831
832
|
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
832
|
-
const exec = {
|
|
833
|
+
const exec = trackCommandDocPolicy({
|
|
833
834
|
usage: parser.usage,
|
|
834
835
|
phase: "parse",
|
|
835
836
|
path: [],
|
|
836
837
|
trace: createInputTrace()
|
|
837
|
-
};
|
|
838
|
+
});
|
|
838
839
|
let context = createParserContext({
|
|
839
840
|
buffer: args,
|
|
840
841
|
state: initialState,
|
|
@@ -859,6 +860,7 @@ async function getDocPageAsyncImpl(parser, args, options) {
|
|
|
859
860
|
*/
|
|
860
861
|
function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
861
862
|
let effectiveArgs = args;
|
|
863
|
+
let showUsage = getCommandDocPolicy(context.exec);
|
|
862
864
|
let { brief, description, fragments, footer, environmentBindings } = parser.getDocFragments({
|
|
863
865
|
kind: "available",
|
|
864
866
|
state: context.state
|
|
@@ -872,6 +874,7 @@ function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
|
872
874
|
}, void 0);
|
|
873
875
|
({brief, description, fragments, footer, environmentBindings} = matched);
|
|
874
876
|
effectiveArgs = [cmdName];
|
|
877
|
+
showUsage = getBareCommandDocPolicy(parser);
|
|
875
878
|
}
|
|
876
879
|
const buildingSections = [];
|
|
877
880
|
let untitledSection = null;
|
|
@@ -949,6 +952,7 @@ function buildDocPage(parser, context, args, matchedCommandArgIndices) {
|
|
|
949
952
|
...binding.description != null && { description: cloneMessage(binding.description) }
|
|
950
953
|
}));
|
|
951
954
|
return {
|
|
955
|
+
...showUsage != null && { showUsage },
|
|
952
956
|
...visibleBindings != null && visibleBindings.length > 0 && { environmentBindings: visibleBindings },
|
|
953
957
|
usage: revealMatchedCommandUsage(usage, effectiveArgs, commandArgIndices ?? null),
|
|
954
958
|
sections,
|
package/dist/primitives.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_internal_annotations = require('./internal/annotations.cjs');
|
|
2
|
+
const require_internal_command_doc_policy = require('./internal/command-doc-policy.cjs');
|
|
2
3
|
const require_validate = require('./validate.cjs');
|
|
3
4
|
const require_usage = require('./usage.cjs');
|
|
4
5
|
const require_message = require('./message.cjs');
|
|
@@ -1447,6 +1448,12 @@ function getShowCommandAliases(options) {
|
|
|
1447
1448
|
if (typeof showAliases !== "boolean") throw new TypeError("Command showAliases must be a boolean.");
|
|
1448
1449
|
return showAliases;
|
|
1449
1450
|
}
|
|
1451
|
+
function getShowCommandUsage(options) {
|
|
1452
|
+
const showUsage = options.showUsage;
|
|
1453
|
+
if (showUsage == null) return void 0;
|
|
1454
|
+
if (typeof showUsage !== "boolean") throw new TypeError("Command showUsage must be a boolean.");
|
|
1455
|
+
return showUsage;
|
|
1456
|
+
}
|
|
1450
1457
|
function getHiddenCommandAliases(options) {
|
|
1451
1458
|
const hiddenAliases = options[require_command_alias.hiddenCommandAliasesKey];
|
|
1452
1459
|
if (hiddenAliases == null) return [];
|
|
@@ -1511,12 +1518,15 @@ async function* suggestCommandAsync(context, prefix, name, aliases, parser, opti
|
|
|
1511
1518
|
* to the inner parser for the remaining arguments.
|
|
1512
1519
|
* @throws {TypeError} If `name` is empty, whitespace-only, contains
|
|
1513
1520
|
* embedded whitespace, or contains control characters.
|
|
1514
|
-
* @throws {TypeError} If `options.showAliases`
|
|
1521
|
+
* @throws {TypeError} If `options.showAliases` or `options.showUsage` is
|
|
1522
|
+
* non-nullish and not a boolean.
|
|
1515
1523
|
*/
|
|
1516
1524
|
function command(name, parser, options = {}) {
|
|
1517
1525
|
const commandNames = getCommandNames(name, options);
|
|
1518
1526
|
const aliases = getVisibleCommandAliases(options);
|
|
1519
1527
|
const showAliases = getShowCommandAliases(options);
|
|
1528
|
+
const showUsage = getShowCommandUsage(options);
|
|
1529
|
+
const commandId = Symbol("commandDocScope");
|
|
1520
1530
|
const hiddenAliases = getHiddenCommandAliases(options);
|
|
1521
1531
|
require_validate.validateCommandNames(commandNames, "Command");
|
|
1522
1532
|
validateUniqueCommandNames(commandNames);
|
|
@@ -1602,7 +1612,7 @@ function command(name, parser, options = {}) {
|
|
|
1602
1612
|
...context,
|
|
1603
1613
|
buffer: context.buffer.slice(1),
|
|
1604
1614
|
state: createCommandState(context.state, ["matched", name]),
|
|
1605
|
-
...context.exec != null ? { exec: appendCommandPath(context.exec, name) } : {}
|
|
1615
|
+
...context.exec != null ? { exec: require_internal_command_doc_policy.matchCommandDocPolicy(appendCommandPath(context.exec, name), commandId, showUsage) } : {}
|
|
1606
1616
|
},
|
|
1607
1617
|
consumed: context.buffer.slice(0, 1)
|
|
1608
1618
|
};
|
|
@@ -1626,7 +1636,13 @@ function command(name, parser, options = {}) {
|
|
|
1626
1636
|
}
|
|
1627
1637
|
return parseResult;
|
|
1628
1638
|
};
|
|
1629
|
-
return require_mode_dispatch.dispatchByMode(parser.mode, () => wrapState(syncInnerParser.parse(require_execution_context.withChildContext(
|
|
1639
|
+
return require_mode_dispatch.dispatchByMode(parser.mode, () => wrapState(syncInnerParser.parse(require_execution_context.withChildContext({
|
|
1640
|
+
...context,
|
|
1641
|
+
exec: require_internal_command_doc_policy.enterCommandDocPolicy(context.exec, commandId)
|
|
1642
|
+
}, name, innerState, parser.usage))), async () => wrapState(await parser.parse(require_execution_context.withChildContext({
|
|
1643
|
+
...context,
|
|
1644
|
+
exec: require_internal_command_doc_policy.enterCommandDocPolicy(context.exec, commandId)
|
|
1645
|
+
}, name, innerState, parser.usage))));
|
|
1630
1646
|
}
|
|
1631
1647
|
return {
|
|
1632
1648
|
success: false,
|
|
@@ -1744,6 +1760,7 @@ function command(name, parser, options = {}) {
|
|
|
1744
1760
|
return `command(${JSON.stringify(name)})`;
|
|
1745
1761
|
}
|
|
1746
1762
|
};
|
|
1763
|
+
require_internal_command_doc_policy.defineBareCommandDocPolicy(result, showUsage);
|
|
1747
1764
|
if (typeof parser.normalizeValue === "function") Object.defineProperty(result, "normalizeValue", {
|
|
1748
1765
|
value: parser.normalizeValue.bind(parser),
|
|
1749
1766
|
configurable: true,
|
package/dist/primitives.d.cts
CHANGED
|
@@ -451,6 +451,14 @@ interface CommandOptions {
|
|
|
451
451
|
* @since 1.0.0
|
|
452
452
|
*/
|
|
453
453
|
readonly usageLine?: Usage | ((defaultUsageLine: Usage) => Usage);
|
|
454
|
+
/**
|
|
455
|
+
* Whether to show the usage synopsis in this command's full help.
|
|
456
|
+
* Descendants inherit this setting unless they explicitly override it.
|
|
457
|
+
* Omission inherits the nearest ancestor setting, then the runner setting,
|
|
458
|
+
* with a final default of `true`. Usage-only error preambles are unaffected.
|
|
459
|
+
* @since 1.4.0
|
|
460
|
+
*/
|
|
461
|
+
readonly showUsage?: boolean;
|
|
454
462
|
/**
|
|
455
463
|
* Controls command visibility:
|
|
456
464
|
*
|
|
@@ -537,7 +545,8 @@ type CommandState<TState> = undefined | ["matched", string] | ["parsing", TState
|
|
|
537
545
|
* to the inner parser for the remaining arguments.
|
|
538
546
|
* @throws {TypeError} If `name` is empty, whitespace-only, contains
|
|
539
547
|
* embedded whitespace, or contains control characters.
|
|
540
|
-
* @throws {TypeError} If `options.showAliases`
|
|
548
|
+
* @throws {TypeError} If `options.showAliases` or `options.showUsage` is
|
|
549
|
+
* non-nullish and not a boolean.
|
|
541
550
|
*/
|
|
542
551
|
declare function command<M extends Mode, T, TState>(name: string, parser: Parser<M, T, TState>, options?: CommandOptions): FluentParser<M, T, CommandState<TState>>;
|
|
543
552
|
/**
|