@optique/core 0.10.7 → 1.0.0-dev.1109
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/README.md +4 -6
- package/dist/annotations.cjs +209 -1
- package/dist/annotations.d.cts +78 -1
- package/dist/annotations.d.ts +78 -1
- package/dist/annotations.js +201 -1
- package/dist/completion.cjs +186 -50
- package/dist/completion.js +186 -50
- package/dist/constructs.cjs +310 -78
- package/dist/constructs.d.cts +525 -644
- package/dist/constructs.d.ts +525 -644
- package/dist/constructs.js +311 -79
- package/dist/context.cjs +43 -3
- package/dist/context.d.cts +113 -5
- package/dist/context.d.ts +113 -5
- package/dist/context.js +41 -3
- package/dist/dependency.cjs +172 -66
- package/dist/dependency.d.cts +22 -2
- package/dist/dependency.d.ts +22 -2
- package/dist/dependency.js +172 -66
- package/dist/doc.cjs +46 -1
- package/dist/doc.d.cts +24 -0
- package/dist/doc.d.ts +24 -0
- package/dist/doc.js +46 -1
- package/dist/facade.cjs +702 -322
- package/dist/facade.d.cts +124 -190
- package/dist/facade.d.ts +124 -190
- package/dist/facade.js +703 -323
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/message.cjs +7 -4
- package/dist/message.js +7 -4
- package/dist/mode-dispatch.cjs +23 -1
- package/dist/mode-dispatch.d.cts +55 -0
- package/dist/mode-dispatch.d.ts +55 -0
- package/dist/mode-dispatch.js +21 -1
- package/dist/modifiers.cjs +210 -55
- package/dist/modifiers.js +211 -56
- package/dist/parser.cjs +80 -47
- package/dist/parser.d.cts +18 -3
- package/dist/parser.d.ts +18 -3
- package/dist/parser.js +82 -50
- package/dist/primitives.cjs +102 -37
- package/dist/primitives.d.cts +81 -24
- package/dist/primitives.d.ts +81 -24
- package/dist/primitives.js +103 -39
- package/dist/usage.cjs +88 -6
- package/dist/usage.d.cts +51 -13
- package/dist/usage.d.ts +51 -13
- package/dist/usage.js +85 -7
- package/dist/valueparser.cjs +371 -99
- package/dist/valueparser.d.cts +56 -7
- package/dist/valueparser.d.ts +56 -7
- package/dist/valueparser.js +371 -99
- package/package.json +10 -1
package/dist/facade.cjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const require_annotations = require('./annotations.cjs');
|
|
2
2
|
const require_message = require('./message.cjs');
|
|
3
3
|
const require_completion = require('./completion.cjs');
|
|
4
|
+
const require_mode_dispatch = require('./mode-dispatch.cjs');
|
|
4
5
|
const require_usage = require('./usage.cjs');
|
|
5
6
|
const require_constructs = require('./constructs.cjs');
|
|
7
|
+
const require_context = require('./context.cjs');
|
|
6
8
|
const require_doc = require('./doc.cjs');
|
|
7
9
|
const require_modifiers = require('./modifiers.cjs');
|
|
8
10
|
const require_valueparser = require('./valueparser.cjs');
|
|
@@ -10,52 +12,345 @@ const require_primitives = require('./primitives.cjs');
|
|
|
10
12
|
const require_parser = require('./parser.cjs');
|
|
11
13
|
|
|
12
14
|
//#region src/facade.ts
|
|
15
|
+
function isPlainObject(value$1) {
|
|
16
|
+
const proto = Object.getPrototypeOf(value$1);
|
|
17
|
+
return proto === Object.prototype || proto === null;
|
|
18
|
+
}
|
|
19
|
+
function shouldSkipCollectionOwnKey(value$1, key) {
|
|
20
|
+
if (Array.isArray(value$1)) return key === "length" || typeof key === "string" && Number.isInteger(Number(key)) && String(Number(key)) === key;
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
function containsPlaceholderValuesInOwnProperties(value$1, seen) {
|
|
24
|
+
for (const key of Reflect.ownKeys(value$1)) {
|
|
25
|
+
if (shouldSkipCollectionOwnKey(value$1, key)) continue;
|
|
26
|
+
const descriptor = Object.getOwnPropertyDescriptor(value$1, key);
|
|
27
|
+
if (descriptor != null && "value" in descriptor && containsPlaceholderValues(descriptor.value, seen)) return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
function copySanitizedOwnProperties(source, target, seen) {
|
|
32
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
33
|
+
if (shouldSkipCollectionOwnKey(source, key)) continue;
|
|
34
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
35
|
+
if (descriptor == null) continue;
|
|
36
|
+
if ("value" in descriptor) descriptor.value = stripPlaceholderValues(descriptor.value, seen);
|
|
37
|
+
Object.defineProperty(target, key, descriptor);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function createArrayCloneLike(value$1) {
|
|
41
|
+
try {
|
|
42
|
+
const arrayCtor = value$1.constructor;
|
|
43
|
+
return Reflect.construct(Array, [value$1.length], arrayCtor);
|
|
44
|
+
} catch {
|
|
45
|
+
return new Array(value$1.length);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function createSetCloneLike(value$1) {
|
|
49
|
+
try {
|
|
50
|
+
const setCtor = value$1.constructor;
|
|
51
|
+
return Reflect.construct(Set, [], setCtor);
|
|
52
|
+
} catch {
|
|
53
|
+
return /* @__PURE__ */ new Set();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function createMapCloneLike(value$1) {
|
|
57
|
+
try {
|
|
58
|
+
const mapCtor = value$1.constructor;
|
|
59
|
+
return Reflect.construct(Map, [], mapCtor);
|
|
60
|
+
} catch {
|
|
61
|
+
return /* @__PURE__ */ new Map();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function containsPlaceholderValues(value$1, seen = /* @__PURE__ */ new WeakSet()) {
|
|
65
|
+
if (require_context.isPlaceholderValue(value$1)) return true;
|
|
66
|
+
if (value$1 == null || typeof value$1 !== "object") return false;
|
|
67
|
+
if (seen.has(value$1)) return false;
|
|
68
|
+
seen.add(value$1);
|
|
69
|
+
if (Array.isArray(value$1)) {
|
|
70
|
+
if (value$1.some((item) => containsPlaceholderValues(item, seen))) return true;
|
|
71
|
+
return containsPlaceholderValuesInOwnProperties(value$1, seen);
|
|
72
|
+
}
|
|
73
|
+
if (value$1 instanceof Set) {
|
|
74
|
+
for (const entryValue of value$1) if (containsPlaceholderValues(entryValue, seen)) return true;
|
|
75
|
+
return containsPlaceholderValuesInOwnProperties(value$1, seen);
|
|
76
|
+
}
|
|
77
|
+
if (value$1 instanceof Map) {
|
|
78
|
+
for (const [key, entryValue] of value$1) if (containsPlaceholderValues(key, seen) || containsPlaceholderValues(entryValue, seen)) return true;
|
|
79
|
+
return containsPlaceholderValuesInOwnProperties(value$1, seen);
|
|
80
|
+
}
|
|
81
|
+
return containsPlaceholderValuesInOwnProperties(value$1, seen);
|
|
82
|
+
}
|
|
83
|
+
function stripPlaceholderValues(value$1, seen = /* @__PURE__ */ new WeakMap()) {
|
|
84
|
+
if (require_context.isPlaceholderValue(value$1)) return void 0;
|
|
85
|
+
if (value$1 == null || typeof value$1 !== "object") return value$1;
|
|
86
|
+
const cached = seen.get(value$1);
|
|
87
|
+
if (cached !== void 0) return cached;
|
|
88
|
+
if (Array.isArray(value$1)) {
|
|
89
|
+
if (!containsPlaceholderValues(value$1)) return value$1;
|
|
90
|
+
const clone$1 = createArrayCloneLike(value$1);
|
|
91
|
+
seen.set(value$1, clone$1);
|
|
92
|
+
for (let i = 0; i < value$1.length; i++) clone$1[i] = stripPlaceholderValues(value$1[i], seen);
|
|
93
|
+
copySanitizedOwnProperties(value$1, clone$1, seen);
|
|
94
|
+
return clone$1;
|
|
95
|
+
}
|
|
96
|
+
if (value$1 instanceof Set) {
|
|
97
|
+
if (!containsPlaceholderValues(value$1)) return value$1;
|
|
98
|
+
const clone$1 = createSetCloneLike(value$1);
|
|
99
|
+
seen.set(value$1, clone$1);
|
|
100
|
+
for (const entryValue of value$1) clone$1.add(stripPlaceholderValues(entryValue, seen));
|
|
101
|
+
copySanitizedOwnProperties(value$1, clone$1, seen);
|
|
102
|
+
return clone$1;
|
|
103
|
+
}
|
|
104
|
+
if (value$1 instanceof Map) {
|
|
105
|
+
if (!containsPlaceholderValues(value$1)) return value$1;
|
|
106
|
+
const clone$1 = createMapCloneLike(value$1);
|
|
107
|
+
seen.set(value$1, clone$1);
|
|
108
|
+
for (const [key, entryValue] of value$1) clone$1.set(stripPlaceholderValues(key, seen), stripPlaceholderValues(entryValue, seen));
|
|
109
|
+
copySanitizedOwnProperties(value$1, clone$1, seen);
|
|
110
|
+
return clone$1;
|
|
111
|
+
}
|
|
112
|
+
if (!isPlainObject(value$1)) {
|
|
113
|
+
if (!containsPlaceholderValues(value$1)) return value$1;
|
|
114
|
+
return createSanitizedNonPlainView(value$1, seen);
|
|
115
|
+
}
|
|
116
|
+
const clone = Object.create(Object.getPrototypeOf(value$1));
|
|
117
|
+
seen.set(value$1, clone);
|
|
118
|
+
for (const key of Reflect.ownKeys(value$1)) {
|
|
119
|
+
const descriptor = Object.getOwnPropertyDescriptor(value$1, key);
|
|
120
|
+
if (descriptor == null) continue;
|
|
121
|
+
if ("value" in descriptor) descriptor.value = stripPlaceholderValues(descriptor.value, seen);
|
|
122
|
+
Object.defineProperty(clone, key, descriptor);
|
|
123
|
+
}
|
|
124
|
+
return clone;
|
|
125
|
+
}
|
|
126
|
+
function finalizeParsedForContext(context, parsed) {
|
|
127
|
+
return context.finalizeParsed != null ? context.finalizeParsed(parsed) : parsed;
|
|
128
|
+
}
|
|
129
|
+
const SANITIZE_FAILED = Symbol("sanitizeFailed");
|
|
130
|
+
const activeSanitizations = /* @__PURE__ */ new WeakMap();
|
|
131
|
+
function callWithSanitizedOwnProperties(target, fn, args, strip, seen) {
|
|
132
|
+
let active = activeSanitizations.get(target);
|
|
133
|
+
if (active != null) active.count++;
|
|
134
|
+
else {
|
|
135
|
+
const saved = /* @__PURE__ */ new Map();
|
|
136
|
+
const sanitizedValues = /* @__PURE__ */ new Map();
|
|
137
|
+
for (const key of Reflect.ownKeys(target)) {
|
|
138
|
+
const desc = Object.getOwnPropertyDescriptor(target, key);
|
|
139
|
+
if (desc != null && "value" in desc) {
|
|
140
|
+
let stripped;
|
|
141
|
+
try {
|
|
142
|
+
stripped = strip(desc.value, seen);
|
|
143
|
+
} catch {
|
|
144
|
+
for (const [k, d] of saved) try {
|
|
145
|
+
Object.defineProperty(target, k, d);
|
|
146
|
+
} catch {}
|
|
147
|
+
return SANITIZE_FAILED;
|
|
148
|
+
}
|
|
149
|
+
if (stripped !== desc.value) try {
|
|
150
|
+
Object.defineProperty(target, key, {
|
|
151
|
+
...desc,
|
|
152
|
+
value: stripped
|
|
153
|
+
});
|
|
154
|
+
saved.set(key, desc);
|
|
155
|
+
sanitizedValues.set(key, stripped);
|
|
156
|
+
} catch {
|
|
157
|
+
for (const [k, d] of saved) try {
|
|
158
|
+
Object.defineProperty(target, k, d);
|
|
159
|
+
} catch {}
|
|
160
|
+
return SANITIZE_FAILED;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
active = {
|
|
165
|
+
saved,
|
|
166
|
+
sanitizedValues,
|
|
167
|
+
count: 1
|
|
168
|
+
};
|
|
169
|
+
activeSanitizations.set(target, active);
|
|
170
|
+
}
|
|
171
|
+
function release() {
|
|
172
|
+
active.count--;
|
|
173
|
+
if (active.count === 0) {
|
|
174
|
+
activeSanitizations.delete(target);
|
|
175
|
+
for (const [key, desc] of active.saved) try {
|
|
176
|
+
const current = Object.getOwnPropertyDescriptor(target, key);
|
|
177
|
+
if (current == null) continue;
|
|
178
|
+
if ("value" in current && current.value !== active.sanitizedValues.get(key)) continue;
|
|
179
|
+
Object.defineProperty(target, key, desc);
|
|
180
|
+
} catch {}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
let result;
|
|
184
|
+
try {
|
|
185
|
+
result = fn.apply(target, args);
|
|
186
|
+
} catch (e) {
|
|
187
|
+
release();
|
|
188
|
+
throw e;
|
|
189
|
+
}
|
|
190
|
+
if (result instanceof Promise) return result.then((v) => {
|
|
191
|
+
release();
|
|
192
|
+
return strip(v, seen);
|
|
193
|
+
}, (e) => {
|
|
194
|
+
release();
|
|
195
|
+
throw e;
|
|
196
|
+
});
|
|
197
|
+
release();
|
|
198
|
+
return strip(result, seen);
|
|
199
|
+
}
|
|
200
|
+
function callMethodOnSanitizedTarget(fn, proxy, target, args, strip, seen) {
|
|
201
|
+
const result = callWithSanitizedOwnProperties(target, fn, args, strip, seen);
|
|
202
|
+
if (result !== SANITIZE_FAILED) return result;
|
|
203
|
+
const fallback = fn.apply(proxy, args);
|
|
204
|
+
if (fallback instanceof Promise) return fallback.then((v) => strip(v, seen));
|
|
205
|
+
return strip(fallback, seen);
|
|
206
|
+
}
|
|
207
|
+
function createSanitizedNonPlainView(value$1, seen) {
|
|
208
|
+
const methodCache = /* @__PURE__ */ new Map();
|
|
209
|
+
const proxy = new Proxy(value$1, {
|
|
210
|
+
get(target, key, receiver) {
|
|
211
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
212
|
+
if (descriptor != null && "value" in descriptor) {
|
|
213
|
+
if (!descriptor.configurable && !descriptor.writable) return descriptor.value;
|
|
214
|
+
const val = stripPlaceholderValues(descriptor.value, seen);
|
|
215
|
+
if (typeof val === "function") {
|
|
216
|
+
if (!descriptor.configurable && !descriptor.writable || /^class[\s{]/.test(Function.prototype.toString.call(val))) return val;
|
|
217
|
+
const cached = methodCache.get(key);
|
|
218
|
+
if (cached != null && cached.fn === val) return cached.wrapper;
|
|
219
|
+
const wrapper = function(...args) {
|
|
220
|
+
if (this !== proxy) return stripPlaceholderValues(val.apply(this, args), seen);
|
|
221
|
+
return callMethodOnSanitizedTarget(val, proxy, target, args, stripPlaceholderValues, seen);
|
|
222
|
+
};
|
|
223
|
+
methodCache.set(key, {
|
|
224
|
+
fn: val,
|
|
225
|
+
wrapper
|
|
226
|
+
});
|
|
227
|
+
return wrapper;
|
|
228
|
+
}
|
|
229
|
+
return val;
|
|
230
|
+
}
|
|
231
|
+
let isAccessor = false;
|
|
232
|
+
for (let proto = target; proto != null; proto = Object.getPrototypeOf(proto)) {
|
|
233
|
+
const d = Object.getOwnPropertyDescriptor(proto, key);
|
|
234
|
+
if (d != null) {
|
|
235
|
+
isAccessor = "get" in d;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const result = Reflect.get(target, key, receiver);
|
|
240
|
+
if (typeof result === "function") {
|
|
241
|
+
if (/^class[\s{]/.test(Function.prototype.toString.call(result))) return result;
|
|
242
|
+
if (!isAccessor) {
|
|
243
|
+
const cached = methodCache.get(key);
|
|
244
|
+
if (cached != null && cached.fn === result) return cached.wrapper;
|
|
245
|
+
const wrapper = function(...args) {
|
|
246
|
+
if (this !== proxy) return stripPlaceholderValues(result.apply(this, args), seen);
|
|
247
|
+
return callMethodOnSanitizedTarget(result, proxy, target, args, stripPlaceholderValues, seen);
|
|
248
|
+
};
|
|
249
|
+
methodCache.set(key, {
|
|
250
|
+
fn: result,
|
|
251
|
+
wrapper
|
|
252
|
+
});
|
|
253
|
+
return wrapper;
|
|
254
|
+
}
|
|
255
|
+
return function(...args) {
|
|
256
|
+
if (this !== proxy) return stripPlaceholderValues(result.apply(this, args), seen);
|
|
257
|
+
return callMethodOnSanitizedTarget(result, proxy, target, args, stripPlaceholderValues, seen);
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
return stripPlaceholderValues(result, seen);
|
|
261
|
+
},
|
|
262
|
+
getOwnPropertyDescriptor(target, key) {
|
|
263
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
264
|
+
if (descriptor == null || !("value" in descriptor)) return descriptor;
|
|
265
|
+
if (!descriptor.configurable && !descriptor.writable) return descriptor;
|
|
266
|
+
return {
|
|
267
|
+
...descriptor,
|
|
268
|
+
value: stripPlaceholderValues(descriptor.value, seen)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
seen.set(value$1, proxy);
|
|
273
|
+
return proxy;
|
|
274
|
+
}
|
|
275
|
+
function prepareParsedForContexts(parsed) {
|
|
276
|
+
if (parsed == null || typeof parsed !== "object") return stripPlaceholderValues(parsed);
|
|
277
|
+
if (require_context.isPlaceholderValue(parsed)) return void 0;
|
|
278
|
+
if (Array.isArray(parsed) || isPlainObject(parsed) || parsed instanceof Set || parsed instanceof Map) {
|
|
279
|
+
if (!containsPlaceholderValues(parsed)) return parsed;
|
|
280
|
+
return stripPlaceholderValues(parsed);
|
|
281
|
+
}
|
|
282
|
+
if (!containsPlaceholderValues(parsed)) return parsed;
|
|
283
|
+
return createSanitizedNonPlainView(parsed, /* @__PURE__ */ new WeakMap());
|
|
284
|
+
}
|
|
285
|
+
function withPreparedParsedForContext(context, preparedParsed, run) {
|
|
286
|
+
return run(finalizeParsedForContext(context, preparedParsed));
|
|
287
|
+
}
|
|
13
288
|
/**
|
|
14
|
-
* Creates help parsers based on the
|
|
289
|
+
* Creates help parsers based on the sub-config.
|
|
15
290
|
*/
|
|
16
|
-
function createHelpParser(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
291
|
+
function createHelpParser(commandConfig, optionConfig) {
|
|
292
|
+
let helpCommand = null;
|
|
293
|
+
let helpOption = null;
|
|
294
|
+
if (commandConfig) {
|
|
295
|
+
const names = commandConfig.names ?? ["help"];
|
|
296
|
+
const innerParser = require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "COMMAND" }), { description: require_message.message`Command name to show help for.` }));
|
|
297
|
+
const commandParsers = [];
|
|
298
|
+
for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], innerParser, {
|
|
299
|
+
description: require_message.message`Show help information.`,
|
|
300
|
+
hidden: i === 0 ? commandConfig.hidden : true
|
|
301
|
+
}));
|
|
302
|
+
helpCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
|
|
303
|
+
}
|
|
304
|
+
if (optionConfig) {
|
|
305
|
+
const names = optionConfig.names ?? ["--help"];
|
|
306
|
+
helpOption = require_primitives.flag(...names, {
|
|
307
|
+
description: require_message.message`Show help information.`,
|
|
308
|
+
hidden: optionConfig.hidden
|
|
309
|
+
});
|
|
32
310
|
}
|
|
311
|
+
return {
|
|
312
|
+
helpCommand,
|
|
313
|
+
helpOption
|
|
314
|
+
};
|
|
33
315
|
}
|
|
34
316
|
/**
|
|
35
|
-
* Creates version parsers based on the
|
|
317
|
+
* Creates version parsers based on the sub-config.
|
|
36
318
|
*/
|
|
37
|
-
function createVersionParser(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
case "both": return {
|
|
50
|
-
versionCommand,
|
|
51
|
-
versionOption
|
|
52
|
-
};
|
|
319
|
+
function createVersionParser(commandConfig, optionConfig) {
|
|
320
|
+
let versionCommand = null;
|
|
321
|
+
let versionOption = null;
|
|
322
|
+
if (commandConfig) {
|
|
323
|
+
const names = commandConfig.names ?? ["version"];
|
|
324
|
+
const innerParser = require_constructs.object({});
|
|
325
|
+
const commandParsers = [];
|
|
326
|
+
for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], innerParser, {
|
|
327
|
+
description: require_message.message`Show version information.`,
|
|
328
|
+
hidden: i === 0 ? commandConfig.hidden : true
|
|
329
|
+
}));
|
|
330
|
+
versionCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
|
|
53
331
|
}
|
|
332
|
+
if (optionConfig) {
|
|
333
|
+
const names = optionConfig.names ?? ["--version"];
|
|
334
|
+
versionOption = require_primitives.flag(...names, {
|
|
335
|
+
description: require_message.message`Show version information.`,
|
|
336
|
+
hidden: optionConfig.hidden
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
versionCommand,
|
|
341
|
+
versionOption
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
const metaResultBrand = Symbol("@optique/core/facade/meta");
|
|
345
|
+
function isMetaParseResult(value$1) {
|
|
346
|
+
return typeof value$1 === "object" && value$1 != null && metaResultBrand in value$1;
|
|
54
347
|
}
|
|
55
348
|
/**
|
|
56
|
-
* Creates completion parsers based on the
|
|
349
|
+
* Creates completion parsers based on the sub-config.
|
|
57
350
|
*/
|
|
58
|
-
function createCompletionParser(
|
|
351
|
+
function createCompletionParser(programName, availableShells, commandConfig, optionConfig) {
|
|
352
|
+
let completionCommand = null;
|
|
353
|
+
let completionOption = null;
|
|
59
354
|
const shellList = [];
|
|
60
355
|
for (const shell in availableShells) {
|
|
61
356
|
if (shellList.length > 0) shellList.push(require_message.text(", "));
|
|
@@ -65,56 +360,44 @@ function createCompletionParser(mode, programName, availableShells, name = "both
|
|
|
65
360
|
shell: require_modifiers.optional(require_primitives.argument(require_valueparser.string({ metavar: "SHELL" }), { description: require_message.message`Shell type (${shellList}). Generate completion script when used alone, or provide completions when followed by arguments.` })),
|
|
66
361
|
args: require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` }))
|
|
67
362
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const showSingular = helpVisibility === "singular" || helpVisibility === "both";
|
|
76
|
-
const showPlural = helpVisibility === "plural" || helpVisibility === "both";
|
|
77
|
-
if (name === "singular" || name === "both") completionCommands.push(require_primitives.command("completion", completionInner, {
|
|
78
|
-
...completionCommandConfig,
|
|
79
|
-
hidden: !showSingular
|
|
80
|
-
}));
|
|
81
|
-
if (name === "plural" || name === "both") completionCommands.push(require_primitives.command("completions", completionInner, {
|
|
82
|
-
...completionCommandConfig,
|
|
83
|
-
hidden: !showPlural
|
|
84
|
-
}));
|
|
85
|
-
const completionCommand = require_constructs.longestMatch(...completionCommands);
|
|
86
|
-
const completionOptions = [];
|
|
87
|
-
if (name === "singular" || name === "both") completionOptions.push(require_primitives.option("--completion", require_valueparser.string({ metavar: "SHELL" }), {
|
|
88
|
-
description: require_message.message`Generate shell completion script.`,
|
|
89
|
-
hidden: !showSingular
|
|
90
|
-
}));
|
|
91
|
-
if (name === "plural" || name === "both") completionOptions.push(require_primitives.option("--completions", require_valueparser.string({ metavar: "SHELL" }), {
|
|
92
|
-
description: require_message.message`Generate shell completion script.`,
|
|
93
|
-
hidden: !showPlural
|
|
94
|
-
}));
|
|
95
|
-
const completionOption = completionOptions.length === 1 ? completionOptions[0] : require_constructs.longestMatch(completionOptions[0], completionOptions[1]);
|
|
96
|
-
const argsParser = require_modifiers.withDefault(require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` })), []);
|
|
97
|
-
const optionParser = require_constructs.object({
|
|
98
|
-
shell: completionOption,
|
|
99
|
-
args: argsParser
|
|
100
|
-
});
|
|
101
|
-
switch (mode) {
|
|
102
|
-
case "command": return {
|
|
103
|
-
completionCommand,
|
|
104
|
-
completionOption: null
|
|
105
|
-
};
|
|
106
|
-
case "option": return {
|
|
107
|
-
completionCommand: null,
|
|
108
|
-
completionOption: optionParser
|
|
109
|
-
};
|
|
110
|
-
case "both": return {
|
|
111
|
-
completionCommand,
|
|
112
|
-
completionOption: optionParser
|
|
363
|
+
if (commandConfig) {
|
|
364
|
+
const names = commandConfig.names ?? ["completion"];
|
|
365
|
+
const displayName = names[0];
|
|
366
|
+
const completionCommandConfig = {
|
|
367
|
+
brief: require_message.message`Generate shell completion script or provide completions.`,
|
|
368
|
+
description: require_message.message`Generate shell completion script or provide completions.`,
|
|
369
|
+
footer: require_message.message`Examples:${require_message.lineBreak()} Bash: ${require_message.commandLine(`eval "$(${programName} ${displayName} bash)"`)}${require_message.lineBreak()} zsh: ${require_message.commandLine(`eval "$(${programName} ${displayName} zsh)"`)}${require_message.lineBreak()} fish: ${require_message.commandLine(`eval "$(${programName} ${displayName} fish)"`)}${require_message.lineBreak()} PowerShell: ${require_message.commandLine(`${programName} ${displayName} pwsh > ${programName}-completion.ps1; . ./${programName}-completion.ps1`)}${require_message.lineBreak()} Nushell: ${require_message.commandLine(`${programName} ${displayName} nu | save ${programName}-completion.nu; source ./${programName}-completion.nu`)}`
|
|
113
370
|
};
|
|
371
|
+
const commandParsers = [];
|
|
372
|
+
for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], completionInner, {
|
|
373
|
+
...completionCommandConfig,
|
|
374
|
+
hidden: i === 0 ? commandConfig.hidden : true
|
|
375
|
+
}));
|
|
376
|
+
completionCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
|
|
377
|
+
}
|
|
378
|
+
if (optionConfig) {
|
|
379
|
+
const names = optionConfig.names ?? ["--completion"];
|
|
380
|
+
const completionOptions = [];
|
|
381
|
+
for (const name of names) completionOptions.push(require_primitives.option(name, require_valueparser.string({ metavar: "SHELL" }), {
|
|
382
|
+
description: require_message.message`Generate shell completion script.`,
|
|
383
|
+
hidden: optionConfig.hidden
|
|
384
|
+
}));
|
|
385
|
+
const completionOptionParser = completionOptions.length === 1 ? completionOptions[0] : require_constructs.longestMatch(...completionOptions);
|
|
386
|
+
const argsParser = require_modifiers.withDefault(require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` })), []);
|
|
387
|
+
completionOption = require_constructs.object({
|
|
388
|
+
shell: completionOptionParser,
|
|
389
|
+
args: argsParser
|
|
390
|
+
});
|
|
114
391
|
}
|
|
392
|
+
return {
|
|
393
|
+
completionCommand,
|
|
394
|
+
completionOption
|
|
395
|
+
};
|
|
115
396
|
}
|
|
116
|
-
function combineWithHelpVersion(originalParser, helpParsers, versionParsers, completionParsers, groups) {
|
|
397
|
+
function combineWithHelpVersion(originalParser, helpParsers, versionParsers, completionParsers, groups, helpOptionNames, versionOptionNames) {
|
|
117
398
|
const parsers = [];
|
|
399
|
+
const effectiveHelpOptionNames = helpOptionNames ?? ["--help"];
|
|
400
|
+
const effectiveVersionOptionNames = versionOptionNames ?? ["--version"];
|
|
118
401
|
if (helpParsers.helpOption) {
|
|
119
402
|
const lenientHelpParser = {
|
|
120
403
|
$mode: "sync",
|
|
@@ -135,11 +418,11 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
135
418
|
let versionIndex = -1;
|
|
136
419
|
for (let i = 0; i < buffer.length; i++) {
|
|
137
420
|
if (buffer[i] === "--") break;
|
|
138
|
-
if (buffer[i]
|
|
421
|
+
if (effectiveHelpOptionNames.includes(buffer[i])) {
|
|
139
422
|
helpFound = true;
|
|
140
423
|
helpIndex = i;
|
|
141
424
|
}
|
|
142
|
-
if (buffer[i]
|
|
425
|
+
if (effectiveVersionOptionNames.includes(buffer[i])) versionIndex = i;
|
|
143
426
|
}
|
|
144
427
|
if (helpFound && versionIndex > helpIndex) return {
|
|
145
428
|
success: false,
|
|
@@ -158,8 +441,10 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
158
441
|
...context,
|
|
159
442
|
buffer: [],
|
|
160
443
|
state: {
|
|
444
|
+
[metaResultBrand]: true,
|
|
161
445
|
help: true,
|
|
162
446
|
version: false,
|
|
447
|
+
completion: false,
|
|
163
448
|
commands,
|
|
164
449
|
helpFlag: true
|
|
165
450
|
}
|
|
@@ -169,7 +454,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
169
454
|
}
|
|
170
455
|
return {
|
|
171
456
|
success: false,
|
|
172
|
-
error: require_message.message`Flag ${require_message.optionName(
|
|
457
|
+
error: require_message.message`Flag ${require_message.optionName(effectiveHelpOptionNames[0])} not found.`,
|
|
173
458
|
consumed: 0
|
|
174
459
|
};
|
|
175
460
|
},
|
|
@@ -180,16 +465,17 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
180
465
|
};
|
|
181
466
|
},
|
|
182
467
|
*suggest(_context, prefix) {
|
|
183
|
-
if (
|
|
468
|
+
for (const name of effectiveHelpOptionNames) if (name.startsWith(prefix)) yield {
|
|
184
469
|
kind: "literal",
|
|
185
|
-
text:
|
|
470
|
+
text: name
|
|
186
471
|
};
|
|
187
472
|
},
|
|
188
473
|
getDocFragments(state) {
|
|
189
474
|
return helpParsers.helpOption?.getDocFragments(state) ?? { fragments: [] };
|
|
190
475
|
}
|
|
191
476
|
};
|
|
192
|
-
|
|
477
|
+
const wrappedHelp = groups?.helpOptionGroup ? require_constructs.group(groups.helpOptionGroup, lenientHelpParser) : lenientHelpParser;
|
|
478
|
+
parsers.push(wrappedHelp);
|
|
193
479
|
}
|
|
194
480
|
if (versionParsers.versionOption) {
|
|
195
481
|
const lenientVersionParser = {
|
|
@@ -211,11 +497,11 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
211
497
|
let helpIndex = -1;
|
|
212
498
|
for (let i = 0; i < buffer.length; i++) {
|
|
213
499
|
if (buffer[i] === "--") break;
|
|
214
|
-
if (buffer[i]
|
|
500
|
+
if (effectiveVersionOptionNames.includes(buffer[i])) {
|
|
215
501
|
versionFound = true;
|
|
216
502
|
versionIndex = i;
|
|
217
503
|
}
|
|
218
|
-
if (buffer[i]
|
|
504
|
+
if (effectiveHelpOptionNames.includes(buffer[i])) helpIndex = i;
|
|
219
505
|
}
|
|
220
506
|
if (versionFound && helpIndex > versionIndex) return {
|
|
221
507
|
success: false,
|
|
@@ -228,8 +514,10 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
228
514
|
...context,
|
|
229
515
|
buffer: [],
|
|
230
516
|
state: {
|
|
517
|
+
[metaResultBrand]: true,
|
|
231
518
|
help: false,
|
|
232
519
|
version: true,
|
|
520
|
+
completion: false,
|
|
233
521
|
versionFlag: true
|
|
234
522
|
}
|
|
235
523
|
},
|
|
@@ -237,7 +525,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
237
525
|
};
|
|
238
526
|
return {
|
|
239
527
|
success: false,
|
|
240
|
-
error: require_message.message`Flag ${require_message.optionName(
|
|
528
|
+
error: require_message.message`Flag ${require_message.optionName(effectiveVersionOptionNames[0])} not found.`,
|
|
241
529
|
consumed: 0
|
|
242
530
|
};
|
|
243
531
|
},
|
|
@@ -248,47 +536,52 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
248
536
|
};
|
|
249
537
|
},
|
|
250
538
|
*suggest(_context, prefix) {
|
|
251
|
-
if (
|
|
539
|
+
for (const name of effectiveVersionOptionNames) if (name.startsWith(prefix)) yield {
|
|
252
540
|
kind: "literal",
|
|
253
|
-
text:
|
|
541
|
+
text: name
|
|
254
542
|
};
|
|
255
543
|
},
|
|
256
544
|
getDocFragments(state) {
|
|
257
545
|
return versionParsers.versionOption?.getDocFragments(state) ?? { fragments: [] };
|
|
258
546
|
}
|
|
259
547
|
};
|
|
260
|
-
|
|
548
|
+
const wrappedVersion = groups?.versionOptionGroup ? require_constructs.group(groups.versionOptionGroup, lenientVersionParser) : lenientVersionParser;
|
|
549
|
+
parsers.push(wrappedVersion);
|
|
261
550
|
}
|
|
262
551
|
if (versionParsers.versionCommand) {
|
|
263
552
|
const versionParser = require_constructs.object({
|
|
553
|
+
[metaResultBrand]: require_primitives.constant(true),
|
|
264
554
|
help: require_primitives.constant(false),
|
|
265
555
|
version: require_primitives.constant(true),
|
|
266
556
|
completion: require_primitives.constant(false),
|
|
267
557
|
result: versionParsers.versionCommand,
|
|
268
558
|
helpFlag: helpParsers.helpOption ? require_modifiers.optional(helpParsers.helpOption) : require_primitives.constant(false)
|
|
269
559
|
});
|
|
270
|
-
parsers.push(groups?.
|
|
560
|
+
parsers.push(groups?.versionCommandGroup ? require_constructs.group(groups.versionCommandGroup, versionParser) : versionParser);
|
|
271
561
|
}
|
|
272
562
|
if (completionParsers.completionCommand) {
|
|
273
563
|
const completionParser = require_constructs.object({
|
|
564
|
+
[metaResultBrand]: require_primitives.constant(true),
|
|
274
565
|
help: require_primitives.constant(false),
|
|
275
566
|
version: require_primitives.constant(false),
|
|
276
567
|
completion: require_primitives.constant(true),
|
|
277
568
|
completionData: completionParsers.completionCommand,
|
|
278
569
|
helpFlag: helpParsers.helpOption ? require_modifiers.optional(helpParsers.helpOption) : require_primitives.constant(false)
|
|
279
570
|
});
|
|
280
|
-
parsers.push(groups?.
|
|
571
|
+
parsers.push(groups?.completionCommandGroup ? require_constructs.group(groups.completionCommandGroup, completionParser) : completionParser);
|
|
281
572
|
}
|
|
282
573
|
if (helpParsers.helpCommand) {
|
|
283
574
|
const helpParser = require_constructs.object({
|
|
575
|
+
[metaResultBrand]: require_primitives.constant(true),
|
|
284
576
|
help: require_primitives.constant(true),
|
|
285
577
|
version: require_primitives.constant(false),
|
|
286
578
|
completion: require_primitives.constant(false),
|
|
287
579
|
commands: helpParsers.helpCommand
|
|
288
580
|
});
|
|
289
|
-
parsers.push(groups?.
|
|
581
|
+
parsers.push(groups?.helpCommandGroup ? require_constructs.group(groups.helpCommandGroup, helpParser) : helpParser);
|
|
290
582
|
}
|
|
291
583
|
parsers.push(require_constructs.object({
|
|
584
|
+
[metaResultBrand]: require_primitives.constant(true),
|
|
292
585
|
help: require_primitives.constant(false),
|
|
293
586
|
version: require_primitives.constant(false),
|
|
294
587
|
completion: require_primitives.constant(false),
|
|
@@ -316,29 +609,29 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
316
609
|
return combined;
|
|
317
610
|
}
|
|
318
611
|
/**
|
|
319
|
-
* Classifies the parsing result into a discriminated union for cleaner
|
|
612
|
+
* Classifies the parsing result into a discriminated union for cleaner
|
|
613
|
+
* handling.
|
|
320
614
|
*/
|
|
321
|
-
function classifyResult(result, args) {
|
|
615
|
+
function classifyResult(result, args, helpOptionNames, helpCommandNames, versionOptionNames, versionCommandNames, completionCommandNames) {
|
|
322
616
|
if (!result.success) return {
|
|
323
617
|
type: "error",
|
|
324
618
|
error: result.error
|
|
325
619
|
};
|
|
326
620
|
const value$1 = result.value;
|
|
327
|
-
if (
|
|
621
|
+
if (isMetaParseResult(value$1)) {
|
|
328
622
|
const parsedValue = value$1;
|
|
329
|
-
const hasVersionOption = args.includes(
|
|
330
|
-
const hasVersionCommand = args.length > 0 && args[0]
|
|
331
|
-
const
|
|
332
|
-
const
|
|
333
|
-
const
|
|
334
|
-
if (hasVersionOption && hasHelpOption && !hasVersionCommand && !hasHelpCommand) {}
|
|
623
|
+
const hasVersionOption = versionOptionNames.some((n) => args.includes(n));
|
|
624
|
+
const hasVersionCommand = args.length > 0 && versionCommandNames.includes(args[0]);
|
|
625
|
+
const hasCompletionCommand = args.length > 0 && completionCommandNames.includes(args[0]);
|
|
626
|
+
const hasHelpOption = hasCompletionCommand ? helpOptionNames.length > 0 && args.length >= 2 && helpOptionNames.includes(args[1]) : helpOptionNames.some((n) => args.includes(n));
|
|
627
|
+
const hasHelpCommand = args.length > 0 && helpCommandNames.includes(args[0]);
|
|
335
628
|
if (hasVersionCommand && hasHelpOption && parsedValue.helpFlag) return {
|
|
336
629
|
type: "help",
|
|
337
|
-
commands: [
|
|
630
|
+
commands: [args[0]]
|
|
338
631
|
};
|
|
339
632
|
if (hasCompletionCommand && hasHelpOption && parsedValue.helpFlag) return {
|
|
340
633
|
type: "help",
|
|
341
|
-
commands: [
|
|
634
|
+
commands: [args[0]]
|
|
342
635
|
};
|
|
343
636
|
if (parsedValue.help && (hasHelpOption || hasHelpCommand)) {
|
|
344
637
|
let commandContext = [];
|
|
@@ -352,12 +645,12 @@ function classifyResult(result, args) {
|
|
|
352
645
|
if ((hasVersionOption || hasVersionCommand) && (parsedValue.version || parsedValue.versionFlag)) return { type: "version" };
|
|
353
646
|
if (parsedValue.completion && parsedValue.completionData) return {
|
|
354
647
|
type: "completion",
|
|
355
|
-
shell: parsedValue.completionData.shell
|
|
356
|
-
args: parsedValue.completionData.args
|
|
648
|
+
shell: parsedValue.completionData.shell ?? "",
|
|
649
|
+
args: parsedValue.completionData.args ?? []
|
|
357
650
|
};
|
|
358
651
|
return {
|
|
359
652
|
type: "success",
|
|
360
|
-
value: parsedValue.result
|
|
653
|
+
value: "result" in parsedValue ? parsedValue.result : value$1
|
|
361
654
|
};
|
|
362
655
|
}
|
|
363
656
|
return {
|
|
@@ -369,34 +662,23 @@ function classifyResult(result, args) {
|
|
|
369
662
|
* Handles shell completion requests.
|
|
370
663
|
* @since 0.6.0
|
|
371
664
|
*/
|
|
372
|
-
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth,
|
|
665
|
+
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder) {
|
|
373
666
|
const shellName = completionArgs[0] || "";
|
|
374
667
|
const args = completionArgs.slice(1);
|
|
375
|
-
const callOnError = (code) =>
|
|
376
|
-
|
|
377
|
-
return onError(code);
|
|
378
|
-
} catch {
|
|
379
|
-
return onError();
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
const callOnCompletion = (code) => {
|
|
383
|
-
try {
|
|
384
|
-
return onCompletion(code);
|
|
385
|
-
} catch {
|
|
386
|
-
return onCompletion();
|
|
387
|
-
}
|
|
388
|
-
};
|
|
668
|
+
const callOnError = (code) => onError(code);
|
|
669
|
+
const callOnCompletion = (code) => onCompletion(code);
|
|
389
670
|
if (!shellName) {
|
|
390
671
|
stderr("Error: Missing shell name for completion.\n");
|
|
391
672
|
if (completionParser) {
|
|
392
|
-
const
|
|
673
|
+
const displayName = completionCommandDisplayName ?? "completion";
|
|
674
|
+
const doc = require_parser.getDocPage(completionParser, [displayName]);
|
|
393
675
|
if (doc) stderr(require_doc.formatDocPage(programName, doc, {
|
|
394
676
|
colors,
|
|
395
|
-
maxWidth
|
|
677
|
+
maxWidth,
|
|
678
|
+
sectionOrder
|
|
396
679
|
}));
|
|
397
680
|
}
|
|
398
|
-
|
|
399
|
-
return callOnError(1);
|
|
681
|
+
return require_mode_dispatch.dispatchByMode(parser.$mode, () => callOnError(1), () => Promise.resolve(callOnError(1)));
|
|
400
682
|
}
|
|
401
683
|
const shell = availableShells[shellName];
|
|
402
684
|
if (!shell) {
|
|
@@ -409,26 +691,24 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
409
691
|
colors,
|
|
410
692
|
quotes: !colors
|
|
411
693
|
}));
|
|
412
|
-
|
|
413
|
-
return callOnError(1);
|
|
694
|
+
return require_mode_dispatch.dispatchByMode(parser.$mode, () => callOnError(1), () => Promise.resolve(callOnError(1)));
|
|
414
695
|
}
|
|
415
696
|
if (args.length === 0) {
|
|
416
|
-
const
|
|
417
|
-
const completionArg = completionMode === "option" ? usePlural ? "--completions" : "--completion" : usePlural ? "completions" : "completion";
|
|
697
|
+
const completionArg = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
|
|
418
698
|
const script = shell.generateScript(programName, [completionArg, shellName]);
|
|
419
699
|
stdout(script);
|
|
420
|
-
|
|
421
|
-
return callOnCompletion(0);
|
|
700
|
+
return require_mode_dispatch.dispatchByMode(parser.$mode, () => callOnCompletion(0), () => Promise.resolve(callOnCompletion(0)));
|
|
422
701
|
}
|
|
423
|
-
|
|
424
|
-
const
|
|
425
|
-
|
|
702
|
+
return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
|
|
703
|
+
const syncParser = parser;
|
|
704
|
+
const suggestions = require_parser.suggest(syncParser, args);
|
|
705
|
+
for (const chunk of shell.encodeSuggestions(suggestions)) stdout(chunk);
|
|
426
706
|
return callOnCompletion(0);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
707
|
+
}, async () => {
|
|
708
|
+
const suggestions = await require_parser.suggestAsync(parser, args);
|
|
709
|
+
for (const chunk of shell.encodeSuggestions(suggestions)) stdout(chunk);
|
|
710
|
+
return callOnCompletion(0);
|
|
711
|
+
});
|
|
432
712
|
}
|
|
433
713
|
function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsParam) {
|
|
434
714
|
const isProgram = typeof programNameOrArgs !== "string";
|
|
@@ -457,21 +737,28 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
457
737
|
args = argsOrOptions;
|
|
458
738
|
options = optionsParam ?? {};
|
|
459
739
|
}
|
|
460
|
-
const { colors, maxWidth, showDefault, showChoices, aboveError = "usage", onError = () => {
|
|
740
|
+
const { colors, maxWidth, showDefault, showChoices, sectionOrder, aboveError = "usage", onError = () => {
|
|
461
741
|
throw new RunParserError("Failed to parse command line arguments.");
|
|
462
742
|
}, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
|
|
463
|
-
const
|
|
743
|
+
const norm = (c) => c === true ? {} : c;
|
|
744
|
+
const helpCommandConfig = norm(options.help?.command);
|
|
745
|
+
const helpOptionConfig = norm(options.help?.option);
|
|
464
746
|
const onHelp = options.help?.onShow ?? (() => ({}));
|
|
465
|
-
const
|
|
466
|
-
const
|
|
747
|
+
const versionCommandConfig = norm(options.version?.command);
|
|
748
|
+
const versionOptionConfig = norm(options.version?.option);
|
|
467
749
|
const versionValue = options.version?.value ?? "";
|
|
468
750
|
const onVersion = options.version?.onShow ?? (() => ({}));
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
const completionName = options.completion?.name ?? "both";
|
|
472
|
-
const completionHelpVisibility = options.completion?.helpVisibility ?? completionName;
|
|
751
|
+
const completionCommandConfig = norm(options.completion?.command);
|
|
752
|
+
const completionOptionConfig = norm(options.completion?.option);
|
|
473
753
|
const onCompletion = options.completion?.onShow ?? (() => ({}));
|
|
474
|
-
const
|
|
754
|
+
const onCompletionResult = (code) => onCompletion(code);
|
|
755
|
+
const onErrorResult = (code) => onError(code);
|
|
756
|
+
const helpOptionNames = helpOptionConfig?.names ?? ["--help"];
|
|
757
|
+
const helpCommandNames = helpCommandConfig?.names ?? ["help"];
|
|
758
|
+
const versionOptionNames = versionOptionConfig?.names ?? ["--version"];
|
|
759
|
+
const versionCommandNames = versionCommandConfig?.names ?? ["version"];
|
|
760
|
+
const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
|
|
761
|
+
const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
|
|
475
762
|
const defaultShells = {
|
|
476
763
|
bash: require_completion.bash,
|
|
477
764
|
fish: require_completion.fish,
|
|
@@ -483,72 +770,65 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
483
770
|
...defaultShells,
|
|
484
771
|
...options.completion.shells
|
|
485
772
|
} : defaultShells;
|
|
486
|
-
const
|
|
487
|
-
const version = options.version ? versionMode : "none";
|
|
488
|
-
const completion = options.completion ? completionMode : "none";
|
|
489
|
-
const helpParsers = help === "none" ? {
|
|
773
|
+
const helpParsers = options.help ? createHelpParser(helpCommandConfig, helpOptionConfig) : {
|
|
490
774
|
helpCommand: null,
|
|
491
775
|
helpOption: null
|
|
492
|
-
}
|
|
493
|
-
const versionParsers = version
|
|
776
|
+
};
|
|
777
|
+
const versionParsers = options.version ? createVersionParser(versionCommandConfig, versionOptionConfig) : {
|
|
494
778
|
versionCommand: null,
|
|
495
779
|
versionOption: null
|
|
496
|
-
}
|
|
497
|
-
const completionParsers = completion
|
|
780
|
+
};
|
|
781
|
+
const completionParsers = options.completion ? createCompletionParser(programName, availableShells, completionCommandConfig, completionOptionConfig) : {
|
|
498
782
|
completionCommand: null,
|
|
499
783
|
completionOption: null
|
|
500
|
-
}
|
|
784
|
+
};
|
|
501
785
|
if (options.completion) {
|
|
502
|
-
const hasHelpOption = args.includes(
|
|
503
|
-
if (
|
|
504
|
-
if (
|
|
786
|
+
const hasHelpOption = helpOptionConfig ? completionCommandConfig && completionCommandNames.includes(args[0]) ? args.length >= 2 && helpOptionNames.includes(args[1]) : helpOptionNames.some((n) => args.includes(n)) : false;
|
|
787
|
+
if (completionCommandConfig && args.length >= 1 && completionCommandNames.includes(args[0]) && !hasHelpOption) return handleCompletion(args.slice(1), programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], false, sectionOrder);
|
|
788
|
+
if (completionOptionConfig) for (let i = 0; i < args.length; i++) {
|
|
505
789
|
const arg = args[i];
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const shell = arg.slice(arg.indexOf("=") + 1);
|
|
790
|
+
const equalsMatch = completionOptionNames.find((n) => arg.startsWith(n + "="));
|
|
791
|
+
if (equalsMatch) {
|
|
792
|
+
const shell = arg.slice(equalsMatch.length + 1);
|
|
510
793
|
const completionArgs = args.slice(i + 1);
|
|
511
|
-
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr,
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName);
|
|
519
|
-
}
|
|
794
|
+
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
|
|
795
|
+
}
|
|
796
|
+
const exactMatch = completionOptionNames.includes(arg);
|
|
797
|
+
if (exactMatch) {
|
|
798
|
+
const shell = i + 1 < args.length ? args[i + 1] : "";
|
|
799
|
+
const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
|
|
800
|
+
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
|
|
520
801
|
}
|
|
521
802
|
}
|
|
522
803
|
}
|
|
523
|
-
const augmentedParser = help
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
804
|
+
const augmentedParser = !options.help && !options.version && !options.completion ? parser : combineWithHelpVersion(parser, helpParsers, versionParsers, completionParsers, {
|
|
805
|
+
helpCommandGroup: helpCommandConfig?.group,
|
|
806
|
+
helpOptionGroup: helpOptionConfig?.group,
|
|
807
|
+
versionCommandGroup: versionCommandConfig?.group,
|
|
808
|
+
versionOptionGroup: versionOptionConfig?.group,
|
|
809
|
+
completionCommandGroup: completionCommandConfig?.group,
|
|
810
|
+
completionOptionGroup: completionOptionConfig?.group
|
|
811
|
+
}, helpOptionConfig ? [...helpOptionNames] : void 0, versionOptionConfig ? [...versionOptionNames] : void 0);
|
|
528
812
|
const handleResult = (result) => {
|
|
529
|
-
const classified = classifyResult(result, args);
|
|
813
|
+
const classified = classifyResult(result, args, helpOptionConfig ? [...helpOptionNames] : [], helpCommandConfig ? [...helpCommandNames] : [], versionOptionConfig ? [...versionOptionNames] : [], versionCommandConfig ? [...versionCommandNames] : [], completionCommandConfig ? [...completionCommandNames] : []);
|
|
530
814
|
switch (classified.type) {
|
|
531
815
|
case "success": return classified.value;
|
|
532
816
|
case "version":
|
|
533
817
|
stdout(versionValue);
|
|
534
|
-
|
|
535
|
-
return onVersion(0);
|
|
536
|
-
} catch {
|
|
537
|
-
return onVersion();
|
|
538
|
-
}
|
|
818
|
+
return onVersion(0);
|
|
539
819
|
case "completion": throw new RunParserError("Completion should be handled by early return");
|
|
540
820
|
case "help": {
|
|
541
821
|
let helpGeneratorParser;
|
|
542
|
-
const helpAsCommand =
|
|
543
|
-
const versionAsCommand =
|
|
544
|
-
const completionAsCommand =
|
|
545
|
-
const helpAsOption =
|
|
546
|
-
const versionAsOption =
|
|
547
|
-
const completionAsOption =
|
|
822
|
+
const helpAsCommand = helpCommandConfig != null;
|
|
823
|
+
const versionAsCommand = versionCommandConfig != null;
|
|
824
|
+
const completionAsCommand = completionCommandConfig != null;
|
|
825
|
+
const helpAsOption = helpOptionConfig != null;
|
|
826
|
+
const versionAsOption = versionOptionConfig != null;
|
|
827
|
+
const completionAsOption = completionOptionConfig != null;
|
|
548
828
|
const requestedCommand = classified.commands[0];
|
|
549
|
-
if (
|
|
550
|
-
else if (requestedCommand
|
|
551
|
-
else if (requestedCommand
|
|
829
|
+
if (requestedCommand != null && completionCommandNames.includes(requestedCommand) && completionAsCommand && completionParsers.completionCommand) helpGeneratorParser = completionParsers.completionCommand;
|
|
830
|
+
else if (requestedCommand != null && helpCommandNames.includes(requestedCommand) && helpAsCommand && helpParsers.helpCommand) helpGeneratorParser = helpParsers.helpCommand;
|
|
831
|
+
else if (requestedCommand != null && versionCommandNames.includes(requestedCommand) && versionAsCommand && versionParsers.versionCommand) helpGeneratorParser = versionParsers.versionCommand;
|
|
552
832
|
else {
|
|
553
833
|
const commandParsers = [parser];
|
|
554
834
|
const groupedMeta = {};
|
|
@@ -557,15 +837,24 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
557
837
|
if (groupLabel) (groupedMeta[groupLabel] ??= []).push(p);
|
|
558
838
|
else ungroupedMeta.push(p);
|
|
559
839
|
};
|
|
560
|
-
if (helpAsCommand && helpParsers.helpCommand) addMeta(helpParsers.helpCommand,
|
|
561
|
-
if (versionAsCommand && versionParsers.versionCommand) addMeta(versionParsers.versionCommand,
|
|
562
|
-
if (completionAsCommand && completionParsers.completionCommand) addMeta(completionParsers.completionCommand,
|
|
840
|
+
if (helpAsCommand && helpParsers.helpCommand) addMeta(helpParsers.helpCommand, helpCommandConfig?.group);
|
|
841
|
+
if (versionAsCommand && versionParsers.versionCommand) addMeta(versionParsers.versionCommand, versionCommandConfig?.group);
|
|
842
|
+
if (completionAsCommand && completionParsers.completionCommand) addMeta(completionParsers.completionCommand, completionCommandConfig?.group);
|
|
563
843
|
commandParsers.push(...ungroupedMeta);
|
|
564
844
|
for (const [label, parsers] of Object.entries(groupedMeta)) if (parsers.length === 1) commandParsers.push(require_constructs.group(label, parsers[0]));
|
|
565
845
|
else commandParsers.push(require_constructs.group(label, require_constructs.longestMatch(...parsers)));
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
846
|
+
const groupedMetaOptions = {};
|
|
847
|
+
const ungroupedMetaOptions = [];
|
|
848
|
+
const addMetaOption = (p, groupLabel) => {
|
|
849
|
+
if (groupLabel) (groupedMetaOptions[groupLabel] ??= []).push(p);
|
|
850
|
+
else ungroupedMetaOptions.push(p);
|
|
851
|
+
};
|
|
852
|
+
if (helpAsOption && helpParsers.helpOption) addMetaOption(helpParsers.helpOption, helpOptionConfig?.group);
|
|
853
|
+
if (versionAsOption && versionParsers.versionOption) addMetaOption(versionParsers.versionOption, versionOptionConfig?.group);
|
|
854
|
+
if (completionAsOption && completionParsers.completionOption) addMetaOption(completionParsers.completionOption, completionOptionConfig?.group);
|
|
855
|
+
commandParsers.push(...ungroupedMetaOptions);
|
|
856
|
+
for (const [label, optParsers] of Object.entries(groupedMetaOptions)) if (optParsers.length === 1) commandParsers.push(require_constructs.group(label, optParsers[0]));
|
|
857
|
+
else commandParsers.push(require_constructs.group(label, require_constructs.longestMatch(...optParsers)));
|
|
569
858
|
if (commandParsers.length === 1) helpGeneratorParser = commandParsers[0];
|
|
570
859
|
else if (commandParsers.length === 2) helpGeneratorParser = require_constructs.longestMatch(commandParsers[0], commandParsers[1]);
|
|
571
860
|
else helpGeneratorParser = require_constructs.longestMatch(...commandParsers);
|
|
@@ -583,6 +872,31 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
583
872
|
stderr(`Error: ${errorMessage}`);
|
|
584
873
|
return onError(1);
|
|
585
874
|
};
|
|
875
|
+
const displayHelp = (doc) => {
|
|
876
|
+
if (doc != null) {
|
|
877
|
+
const isMetaCommandHelp = requestedCommand != null && completionCommandNames.includes(requestedCommand) || requestedCommand != null && helpCommandNames.includes(requestedCommand) || requestedCommand != null && versionCommandNames.includes(requestedCommand);
|
|
878
|
+
const isSubcommandHelp = classified.commands.length > 0;
|
|
879
|
+
const isTopLevel = !isSubcommandHelp;
|
|
880
|
+
const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
|
|
881
|
+
const augmentedDoc = {
|
|
882
|
+
...doc,
|
|
883
|
+
brief: shouldOverride ? brief ?? doc.brief : doc.brief,
|
|
884
|
+
description: shouldOverride ? description ?? doc.description : doc.description,
|
|
885
|
+
examples: isTopLevel && !isMetaCommandHelp ? examples ?? doc.examples : void 0,
|
|
886
|
+
author: isTopLevel && !isMetaCommandHelp ? author ?? doc.author : void 0,
|
|
887
|
+
bugs: isTopLevel && !isMetaCommandHelp ? bugs ?? doc.bugs : void 0,
|
|
888
|
+
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
889
|
+
};
|
|
890
|
+
stdout(require_doc.formatDocPage(programName, augmentedDoc, {
|
|
891
|
+
colors,
|
|
892
|
+
maxWidth,
|
|
893
|
+
showDefault,
|
|
894
|
+
showChoices,
|
|
895
|
+
sectionOrder
|
|
896
|
+
}));
|
|
897
|
+
}
|
|
898
|
+
return onHelp(0);
|
|
899
|
+
};
|
|
586
900
|
if (classified.commands.length > 0) {
|
|
587
901
|
let validationContext = {
|
|
588
902
|
buffer: [...classified.commands],
|
|
@@ -623,34 +937,6 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
623
937
|
}
|
|
624
938
|
if (validationResult != null) return reportInvalidHelpCommand(validationResult);
|
|
625
939
|
}
|
|
626
|
-
const displayHelp = (doc) => {
|
|
627
|
-
if (doc != null) {
|
|
628
|
-
const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
|
|
629
|
-
const isSubcommandHelp = classified.commands.length > 0;
|
|
630
|
-
const isTopLevel = !isSubcommandHelp;
|
|
631
|
-
const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
|
|
632
|
-
const augmentedDoc = {
|
|
633
|
-
...doc,
|
|
634
|
-
brief: shouldOverride ? brief ?? doc.brief : doc.brief,
|
|
635
|
-
description: shouldOverride ? description ?? doc.description : doc.description,
|
|
636
|
-
examples: isTopLevel && !isMetaCommandHelp ? examples ?? doc.examples : void 0,
|
|
637
|
-
author: isTopLevel && !isMetaCommandHelp ? author ?? doc.author : void 0,
|
|
638
|
-
bugs: isTopLevel && !isMetaCommandHelp ? bugs ?? doc.bugs : void 0,
|
|
639
|
-
footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
|
|
640
|
-
};
|
|
641
|
-
stdout(require_doc.formatDocPage(programName, augmentedDoc, {
|
|
642
|
-
colors,
|
|
643
|
-
maxWidth,
|
|
644
|
-
showDefault,
|
|
645
|
-
showChoices
|
|
646
|
-
}));
|
|
647
|
-
}
|
|
648
|
-
try {
|
|
649
|
-
return onHelp(0);
|
|
650
|
-
} catch {
|
|
651
|
-
return onHelp();
|
|
652
|
-
}
|
|
653
|
-
};
|
|
654
940
|
const docOrPromise = require_parser.getDocPage(helpGeneratorParser, classified.commands);
|
|
655
941
|
if (docOrPromise instanceof Promise) return docOrPromise.then(displayHelp);
|
|
656
942
|
return displayHelp(docOrPromise);
|
|
@@ -699,11 +985,17 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
699
985
|
default: throw new RunParserError("Unexpected parse result type");
|
|
700
986
|
}
|
|
701
987
|
};
|
|
702
|
-
|
|
703
|
-
|
|
988
|
+
const parserMode = parser.$mode;
|
|
989
|
+
return require_mode_dispatch.dispatchByMode(parserMode, () => {
|
|
704
990
|
const result = require_parser.parseSync(augmentedParser, args);
|
|
705
|
-
|
|
706
|
-
|
|
991
|
+
const handled = handleResult(result);
|
|
992
|
+
if (handled instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
993
|
+
return handled;
|
|
994
|
+
}, async () => {
|
|
995
|
+
const result = await require_parser.parseAsync(augmentedParser, args);
|
|
996
|
+
const handled = handleResult(result);
|
|
997
|
+
return handled instanceof Promise ? await handled : handled;
|
|
998
|
+
});
|
|
707
999
|
}
|
|
708
1000
|
/**
|
|
709
1001
|
* Runs a synchronous command-line parser with the given options.
|
|
@@ -772,26 +1064,31 @@ function indentLines(text$1, indent) {
|
|
|
772
1064
|
* @returns `true` if early exit should be performed, `false` otherwise.
|
|
773
1065
|
*/
|
|
774
1066
|
function needsEarlyExit(args, options) {
|
|
1067
|
+
const norm = (c) => c === true ? {} : c;
|
|
775
1068
|
if (options.help) {
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
|
|
1069
|
+
const helpOptionConfig = norm(options.help.option);
|
|
1070
|
+
const helpCommandConfig = norm(options.help.command);
|
|
1071
|
+
const helpOptionNames = helpOptionConfig?.names ?? ["--help"];
|
|
1072
|
+
const helpCommandNames = helpCommandConfig?.names ?? ["help"];
|
|
1073
|
+
if (helpOptionConfig && helpOptionNames.some((n) => args.includes(n))) return true;
|
|
1074
|
+
if (helpCommandConfig && helpCommandNames.includes(args[0])) return true;
|
|
779
1075
|
}
|
|
780
1076
|
if (options.version) {
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
1077
|
+
const versionOptionConfig = norm(options.version.option);
|
|
1078
|
+
const versionCommandConfig = norm(options.version.command);
|
|
1079
|
+
const versionOptionNames = versionOptionConfig?.names ?? ["--version"];
|
|
1080
|
+
const versionCommandNames = versionCommandConfig?.names ?? ["version"];
|
|
1081
|
+
if (versionOptionConfig && versionOptionNames.some((n) => args.includes(n))) return true;
|
|
1082
|
+
if (versionCommandConfig && versionCommandNames.includes(args[0])) return true;
|
|
784
1083
|
}
|
|
785
1084
|
if (options.completion) {
|
|
786
|
-
const
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
if ((completionName === "singular" || completionName === "both") && (arg === "--completion" || arg.startsWith("--completion="))) return true;
|
|
794
|
-
if ((completionName === "plural" || completionName === "both") && (arg === "--completions" || arg.startsWith("--completions="))) return true;
|
|
1085
|
+
const completionCommandConfig = norm(options.completion.command);
|
|
1086
|
+
const completionOptionConfig = norm(options.completion.option);
|
|
1087
|
+
const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
|
|
1088
|
+
const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
|
|
1089
|
+
if (completionCommandConfig && completionCommandNames.includes(args[0])) return true;
|
|
1090
|
+
if (completionOptionConfig) {
|
|
1091
|
+
for (const arg of args) for (const name of completionOptionNames) if (arg === name || arg.startsWith(name + "=")) return true;
|
|
795
1092
|
}
|
|
796
1093
|
}
|
|
797
1094
|
return false;
|
|
@@ -818,23 +1115,22 @@ function mergeAnnotations(annotationsList) {
|
|
|
818
1115
|
* two-phase parsing is needed.
|
|
819
1116
|
*
|
|
820
1117
|
* @param contexts Source contexts to collect annotations from.
|
|
1118
|
+
* @param options Optional context-required options to pass to each context.
|
|
821
1119
|
* @returns Promise with merged annotations and dynamic-context hint.
|
|
822
1120
|
*/
|
|
823
|
-
async function collectPhase1Annotations(contexts) {
|
|
1121
|
+
async function collectPhase1Annotations(contexts, options) {
|
|
824
1122
|
const annotationsList = [];
|
|
825
1123
|
let hasDynamic = false;
|
|
826
1124
|
for (const context of contexts) {
|
|
827
|
-
const result = context.getAnnotations();
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
if (Object.getOwnPropertySymbols(result).length === 0) hasDynamic = true;
|
|
833
|
-
annotationsList.push(result);
|
|
834
|
-
}
|
|
1125
|
+
const result = context.getAnnotations(void 0, options);
|
|
1126
|
+
hasDynamic ||= needsTwoPhaseContext(context, result);
|
|
1127
|
+
const annotations = result instanceof Promise ? await result : result;
|
|
1128
|
+
const internalAnnotations = context.getInternalAnnotations?.(void 0, annotations);
|
|
1129
|
+
annotationsList.push(internalAnnotations == null ? annotations : mergeAnnotations([annotations, internalAnnotations]));
|
|
835
1130
|
}
|
|
836
1131
|
return {
|
|
837
1132
|
annotations: mergeAnnotations(annotationsList),
|
|
1133
|
+
annotationsList,
|
|
838
1134
|
hasDynamic
|
|
839
1135
|
};
|
|
840
1136
|
}
|
|
@@ -843,54 +1139,131 @@ async function collectPhase1Annotations(contexts) {
|
|
|
843
1139
|
*
|
|
844
1140
|
* @param contexts Source contexts to collect annotations from.
|
|
845
1141
|
* @param parsed Optional parsed result from a previous parse pass.
|
|
1142
|
+
* @param options Optional context-required options to pass to each context.
|
|
846
1143
|
* @returns Promise that resolves to merged annotations.
|
|
847
1144
|
*/
|
|
848
|
-
async function collectAnnotations(contexts, parsed) {
|
|
1145
|
+
async function collectAnnotations(contexts, parsed, options) {
|
|
849
1146
|
const annotationsList = [];
|
|
1147
|
+
const preparedParsed = prepareParsedForContexts(parsed);
|
|
850
1148
|
for (const context of contexts) {
|
|
851
|
-
const
|
|
852
|
-
|
|
1149
|
+
const mergedAnnotations = await withPreparedParsedForContext(context, preparedParsed, async (contextParsed) => {
|
|
1150
|
+
const result = context.getAnnotations(contextParsed, options);
|
|
1151
|
+
const annotations = result instanceof Promise ? await result : result;
|
|
1152
|
+
const internalAnnotations = context.getInternalAnnotations?.(contextParsed, annotations);
|
|
1153
|
+
return internalAnnotations == null ? annotations : mergeAnnotations([annotations, internalAnnotations]);
|
|
1154
|
+
});
|
|
1155
|
+
annotationsList.push(mergedAnnotations);
|
|
853
1156
|
}
|
|
854
|
-
return
|
|
1157
|
+
return {
|
|
1158
|
+
annotations: mergeAnnotations(annotationsList),
|
|
1159
|
+
annotationsList
|
|
1160
|
+
};
|
|
855
1161
|
}
|
|
856
1162
|
/**
|
|
857
1163
|
* Collects phase 1 annotations from all contexts synchronously and determines
|
|
858
1164
|
* whether two-phase parsing is needed.
|
|
859
1165
|
*
|
|
860
1166
|
* @param contexts Source contexts to collect annotations from.
|
|
1167
|
+
* @param options Optional context-required options to pass to each context.
|
|
861
1168
|
* @returns Merged annotations with dynamic-context hint.
|
|
862
1169
|
* @throws Error if any context returns a Promise.
|
|
863
1170
|
*/
|
|
864
|
-
function collectPhase1AnnotationsSync(contexts) {
|
|
1171
|
+
function collectPhase1AnnotationsSync(contexts, options) {
|
|
865
1172
|
const annotationsList = [];
|
|
866
1173
|
let hasDynamic = false;
|
|
867
1174
|
for (const context of contexts) {
|
|
868
|
-
const result = context.getAnnotations();
|
|
1175
|
+
const result = context.getAnnotations(void 0, options);
|
|
869
1176
|
if (result instanceof Promise) throw new Error(`Context ${String(context.id)} returned a Promise in sync mode. Use runWith() or runWithAsync() for async contexts.`);
|
|
870
|
-
|
|
871
|
-
|
|
1177
|
+
hasDynamic ||= needsTwoPhaseContext(context, result);
|
|
1178
|
+
const internalAnnotations = context.getInternalAnnotations?.(void 0, result);
|
|
1179
|
+
annotationsList.push(internalAnnotations == null ? result : mergeAnnotations([result, internalAnnotations]));
|
|
872
1180
|
}
|
|
873
1181
|
return {
|
|
874
1182
|
annotations: mergeAnnotations(annotationsList),
|
|
1183
|
+
annotationsList,
|
|
875
1184
|
hasDynamic
|
|
876
1185
|
};
|
|
877
1186
|
}
|
|
878
1187
|
/**
|
|
1188
|
+
* Determines whether a context requires a second parse pass.
|
|
1189
|
+
*
|
|
1190
|
+
* Explicit `mode` declarations take precedence over legacy heuristics so
|
|
1191
|
+
* static contexts are not forced into two-phase parsing when they return
|
|
1192
|
+
* empty annotations or a Promise.
|
|
1193
|
+
*/
|
|
1194
|
+
function needsTwoPhaseContext(context, result) {
|
|
1195
|
+
if (context.mode !== void 0) return context.mode === "dynamic";
|
|
1196
|
+
if (result instanceof Promise) return true;
|
|
1197
|
+
return Object.getOwnPropertySymbols(result).length === 0;
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
879
1200
|
* Collects annotations from all contexts synchronously.
|
|
880
1201
|
*
|
|
881
1202
|
* @param contexts Source contexts to collect annotations from.
|
|
882
1203
|
* @param parsed Optional parsed result from a previous parse pass.
|
|
1204
|
+
* @param options Optional context-required options to pass to each context.
|
|
883
1205
|
* @returns Merged annotations.
|
|
884
1206
|
* @throws Error if any context returns a Promise.
|
|
885
1207
|
*/
|
|
886
|
-
function collectAnnotationsSync(contexts, parsed) {
|
|
1208
|
+
function collectAnnotationsSync(contexts, parsed, options) {
|
|
887
1209
|
const annotationsList = [];
|
|
1210
|
+
const preparedParsed = prepareParsedForContexts(parsed);
|
|
888
1211
|
for (const context of contexts) {
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
1212
|
+
const mergedAnnotations = withPreparedParsedForContext(context, preparedParsed, (contextParsed) => {
|
|
1213
|
+
const result = context.getAnnotations(contextParsed, options);
|
|
1214
|
+
if (result instanceof Promise) throw new Error(`Context ${String(context.id)} returned a Promise in sync mode. Use runWith() or runWithAsync() for async contexts.`);
|
|
1215
|
+
const internalAnnotations = context.getInternalAnnotations?.(contextParsed, result);
|
|
1216
|
+
return internalAnnotations == null ? result : mergeAnnotations([result, internalAnnotations]);
|
|
1217
|
+
});
|
|
1218
|
+
annotationsList.push(mergedAnnotations);
|
|
892
1219
|
}
|
|
893
|
-
return
|
|
1220
|
+
return {
|
|
1221
|
+
annotations: mergeAnnotations(annotationsList),
|
|
1222
|
+
annotationsList
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
function mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList) {
|
|
1226
|
+
const mergedPerContext = [];
|
|
1227
|
+
const length = Math.max(phase1AnnotationsList.length, phase2AnnotationsList.length);
|
|
1228
|
+
for (let i = 0; i < length; i++) mergedPerContext.push(mergeAnnotations([phase2AnnotationsList[i] ?? {}, phase1AnnotationsList[i] ?? {}]));
|
|
1229
|
+
return mergeAnnotations(mergedPerContext);
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Disposes all contexts that implement `AsyncDisposable` or `Disposable`.
|
|
1233
|
+
* Prefers `[Symbol.asyncDispose]` over `[Symbol.dispose]`.
|
|
1234
|
+
*
|
|
1235
|
+
* @param contexts Source contexts to dispose.
|
|
1236
|
+
*/
|
|
1237
|
+
async function disposeContexts(contexts) {
|
|
1238
|
+
const errors = [];
|
|
1239
|
+
for (const context of contexts) try {
|
|
1240
|
+
if (Symbol.asyncDispose in context && typeof context[Symbol.asyncDispose] === "function") await context[Symbol.asyncDispose]();
|
|
1241
|
+
else if (Symbol.dispose in context && typeof context[Symbol.dispose] === "function") context[Symbol.dispose]();
|
|
1242
|
+
} catch (error) {
|
|
1243
|
+
errors.push(error);
|
|
1244
|
+
}
|
|
1245
|
+
if (errors.length === 1) throw errors[0];
|
|
1246
|
+
if (errors.length > 1) throw new AggregateError(errors, "Failed to dispose one or more source contexts.");
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Disposes all contexts that implement `Disposable` synchronously.
|
|
1250
|
+
* Falls back to `[Symbol.asyncDispose]` when it completes synchronously.
|
|
1251
|
+
*
|
|
1252
|
+
* @param contexts Source contexts to dispose.
|
|
1253
|
+
*/
|
|
1254
|
+
function disposeContextsSync(contexts) {
|
|
1255
|
+
const errors = [];
|
|
1256
|
+
for (const context of contexts) try {
|
|
1257
|
+
if (Symbol.dispose in context && typeof context[Symbol.dispose] === "function") context[Symbol.dispose]();
|
|
1258
|
+
else if (Symbol.asyncDispose in context && typeof context[Symbol.asyncDispose] === "function") {
|
|
1259
|
+
const result = context[Symbol.asyncDispose]();
|
|
1260
|
+
if (typeof result === "object" && result !== null && "then" in result && typeof result.then === "function") throw new TypeError(`Context ${String(context.id)} returned a Promise from Symbol.asyncDispose in sync mode. Use runWith() or runWithAsync() for async disposal.`);
|
|
1261
|
+
}
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
errors.push(error);
|
|
1264
|
+
}
|
|
1265
|
+
if (errors.length === 1) throw errors[0];
|
|
1266
|
+
if (errors.length > 1) throw new AggregateError(errors, "Failed to dispose one or more source contexts.");
|
|
894
1267
|
}
|
|
895
1268
|
/**
|
|
896
1269
|
* Runs a parser with multiple source contexts.
|
|
@@ -950,36 +1323,41 @@ async function runWith(parser, programName, contexts, options) {
|
|
|
950
1323
|
if (parser.$mode === "async") return runParser(parser, programName, args, options);
|
|
951
1324
|
return Promise.resolve(runParser(parser, programName, args, options));
|
|
952
1325
|
}
|
|
953
|
-
const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts);
|
|
954
|
-
if (!needsTwoPhase) {
|
|
955
|
-
const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
956
|
-
if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
|
|
957
|
-
return Promise.resolve(runParser(augmentedParser, programName, args, options));
|
|
958
|
-
}
|
|
959
|
-
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
960
|
-
let firstPassResult;
|
|
961
|
-
let firstPassFailed = false;
|
|
962
1326
|
try {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
if (
|
|
966
|
-
const
|
|
967
|
-
if (
|
|
968
|
-
|
|
1327
|
+
const ctxOptions = options?.contextOptions;
|
|
1328
|
+
const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts, ctxOptions);
|
|
1329
|
+
if (!needsTwoPhase) {
|
|
1330
|
+
const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1331
|
+
if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
|
|
1332
|
+
return Promise.resolve(runParser(augmentedParser, programName, args, options));
|
|
969
1333
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1334
|
+
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1335
|
+
let firstPassResult;
|
|
1336
|
+
let firstPassFailed = false;
|
|
1337
|
+
try {
|
|
1338
|
+
if (parser.$mode === "async") firstPassResult = await require_parser.parseAsync(augmentedParser1, args);
|
|
1339
|
+
else firstPassResult = require_parser.parseSync(augmentedParser1, args);
|
|
1340
|
+
if (typeof firstPassResult === "object" && firstPassResult !== null && "success" in firstPassResult) {
|
|
1341
|
+
const result = firstPassResult;
|
|
1342
|
+
if (result.success) firstPassResult = result.value;
|
|
1343
|
+
else firstPassFailed = true;
|
|
1344
|
+
}
|
|
1345
|
+
} catch {
|
|
1346
|
+
firstPassFailed = true;
|
|
1347
|
+
}
|
|
1348
|
+
if (firstPassFailed) {
|
|
1349
|
+
const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1350
|
+
if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
|
|
1351
|
+
return Promise.resolve(runParser(augmentedParser, programName, args, options));
|
|
1352
|
+
}
|
|
1353
|
+
const { annotationsList: phase2AnnotationsList } = await collectAnnotations(contexts, firstPassResult, ctxOptions);
|
|
1354
|
+
const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
|
|
1355
|
+
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|
|
1356
|
+
if (parser.$mode === "async") return runParser(augmentedParser2, programName, args, options);
|
|
1357
|
+
return Promise.resolve(runParser(augmentedParser2, programName, args, options));
|
|
1358
|
+
} finally {
|
|
1359
|
+
await disposeContexts(contexts);
|
|
977
1360
|
}
|
|
978
|
-
const phase2Annotations = await collectAnnotations(contexts, firstPassResult);
|
|
979
|
-
const finalAnnotations = mergeAnnotations([phase1Annotations, phase2Annotations]);
|
|
980
|
-
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|
|
981
|
-
if (parser.$mode === "async") return runParser(augmentedParser2, programName, args, options);
|
|
982
|
-
return Promise.resolve(runParser(augmentedParser2, programName, args, options));
|
|
983
1361
|
}
|
|
984
1362
|
/**
|
|
985
1363
|
* Runs a synchronous parser with multiple source contexts.
|
|
@@ -995,31 +1373,37 @@ async function runWith(parser, programName, contexts, options) {
|
|
|
995
1373
|
* @param contexts Source contexts to use (priority: earlier overrides later).
|
|
996
1374
|
* @param options Run options including args, help, version, etc.
|
|
997
1375
|
* @returns The parsed result.
|
|
998
|
-
* @throws Error if any context returns a Promise
|
|
1376
|
+
* @throws Error if any context returns a Promise or if a context's
|
|
1377
|
+
* `[Symbol.asyncDispose]` returns a Promise.
|
|
999
1378
|
* @since 0.10.0
|
|
1000
1379
|
*/
|
|
1001
1380
|
function runWithSync(parser, programName, contexts, options) {
|
|
1002
1381
|
const args = options?.args ?? [];
|
|
1003
1382
|
if (needsEarlyExit(args, options)) return runParser(parser, programName, args, options);
|
|
1004
1383
|
if (contexts.length === 0) return runParser(parser, programName, args, options);
|
|
1005
|
-
const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts);
|
|
1006
|
-
if (!needsTwoPhase) {
|
|
1007
|
-
const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1008
|
-
return runParser(augmentedParser, programName, args, options);
|
|
1009
|
-
}
|
|
1010
|
-
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1011
|
-
let firstPassResult;
|
|
1012
1384
|
try {
|
|
1013
|
-
const
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1385
|
+
const ctxOptions = options?.contextOptions;
|
|
1386
|
+
const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts, ctxOptions);
|
|
1387
|
+
if (!needsTwoPhase) {
|
|
1388
|
+
const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1389
|
+
return runParser(augmentedParser, programName, args, options);
|
|
1390
|
+
}
|
|
1391
|
+
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1392
|
+
let firstPassResult;
|
|
1393
|
+
try {
|
|
1394
|
+
const result = require_parser.parseSync(augmentedParser1, args);
|
|
1395
|
+
if (result.success) firstPassResult = result.value;
|
|
1396
|
+
else return runParser(augmentedParser1, programName, args, options);
|
|
1397
|
+
} catch {
|
|
1398
|
+
return runParser(augmentedParser1, programName, args, options);
|
|
1399
|
+
}
|
|
1400
|
+
const { annotationsList: phase2AnnotationsList } = collectAnnotationsSync(contexts, firstPassResult, ctxOptions);
|
|
1401
|
+
const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
|
|
1402
|
+
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|
|
1403
|
+
return runParser(augmentedParser2, programName, args, options);
|
|
1404
|
+
} finally {
|
|
1405
|
+
disposeContextsSync(contexts);
|
|
1018
1406
|
}
|
|
1019
|
-
const phase2Annotations = collectAnnotationsSync(contexts, firstPassResult);
|
|
1020
|
-
const finalAnnotations = mergeAnnotations([phase1Annotations, phase2Annotations]);
|
|
1021
|
-
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|
|
1022
|
-
return runParser(augmentedParser2, programName, args, options);
|
|
1023
1407
|
}
|
|
1024
1408
|
/**
|
|
1025
1409
|
* Runs any parser asynchronously with multiple source contexts.
|
|
@@ -1048,11 +1432,7 @@ function runWithAsync(parser, programName, contexts, options) {
|
|
|
1048
1432
|
* @returns A new parser with annotations in its initial state.
|
|
1049
1433
|
*/
|
|
1050
1434
|
function injectAnnotationsIntoParser(parser, annotations) {
|
|
1051
|
-
|
|
1052
|
-
const newInitialState = {
|
|
1053
|
-
...parser.initialState,
|
|
1054
|
-
[require_annotations.annotationKey]: annotations
|
|
1055
|
-
};
|
|
1435
|
+
const newInitialState = require_annotations.injectAnnotations(parser.initialState, annotations);
|
|
1056
1436
|
return {
|
|
1057
1437
|
...parser,
|
|
1058
1438
|
initialState: newInitialState
|