@optique/core 1.1.1 → 1.1.3
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 +124 -41
- package/dist/constructs.js +124 -41
- package/dist/primitives.cjs +14 -9
- package/dist/primitives.js +14 -9
- package/package.json +2 -2
package/dist/constructs.cjs
CHANGED
|
@@ -581,6 +581,35 @@ function createExclusiveState(parentState, index, parser, result) {
|
|
|
581
581
|
return require_internal_annotations.annotateFreshArray(parentState, [index, annotatedResult]);
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
|
+
* Detects a branch result that handled only the global options terminator.
|
|
585
|
+
* Such a result advances the shared parser context, but does not identify
|
|
586
|
+
* which exclusive branch matched.
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function isOptionsTerminatorOnlyResult(context, result) {
|
|
590
|
+
return !context.optionsTerminated && context.buffer[0] === "--" && result.success && result.next.optionsTerminated && result.consumed.length === 1 && result.consumed[0] === "--";
|
|
591
|
+
}
|
|
592
|
+
function isUnselectedBooleanOptionState(state) {
|
|
593
|
+
return state != null && typeof state === "object" && "success" in state && state.success === true && "value" in state && state.value === false;
|
|
594
|
+
}
|
|
595
|
+
function preserveExclusiveStateAfterOptionsTerminator(context, result) {
|
|
596
|
+
const mergedExec = require_execution_context.mergeChildExec(context.exec, result.next.exec);
|
|
597
|
+
return {
|
|
598
|
+
success: true,
|
|
599
|
+
next: {
|
|
600
|
+
...context,
|
|
601
|
+
buffer: result.next.buffer,
|
|
602
|
+
optionsTerminated: true,
|
|
603
|
+
state: context.state,
|
|
604
|
+
...mergedExec != null ? {
|
|
605
|
+
exec: mergedExec,
|
|
606
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
607
|
+
} : {}
|
|
608
|
+
},
|
|
609
|
+
consumed: result.consumed
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
584
613
|
* Creates a complete() method shared by or() and longestMatch().
|
|
585
614
|
* @internal
|
|
586
615
|
*/
|
|
@@ -818,9 +847,15 @@ function or(...args) {
|
|
|
818
847
|
let zeroConsumedBranch = null;
|
|
819
848
|
let zeroConsumedCount = 0;
|
|
820
849
|
let provisionalConsuming = null;
|
|
850
|
+
let optionsTerminatorResult = null;
|
|
821
851
|
let provisionalAmbiguous = false;
|
|
822
852
|
for (const [parser, i] of orderedParsers) {
|
|
823
853
|
const result = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
854
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
855
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
856
|
+
optionsTerminatorResult ??= result;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
824
859
|
if (result.success && result.consumed.length > 0) {
|
|
825
860
|
if (result.provisional) {
|
|
826
861
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1001,6 +1036,7 @@ function or(...args) {
|
|
|
1001
1036
|
}
|
|
1002
1037
|
}
|
|
1003
1038
|
}
|
|
1039
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1004
1040
|
return {
|
|
1005
1041
|
...error,
|
|
1006
1042
|
success: false
|
|
@@ -1014,10 +1050,16 @@ function or(...args) {
|
|
|
1014
1050
|
let zeroConsumedBranch = null;
|
|
1015
1051
|
let zeroConsumedCount = 0;
|
|
1016
1052
|
let provisionalConsuming = null;
|
|
1053
|
+
let optionsTerminatorResult = null;
|
|
1017
1054
|
let provisionalAmbiguous = false;
|
|
1018
1055
|
for (const [parser, i] of orderedParsers) {
|
|
1019
1056
|
const resultOrPromise = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
1020
1057
|
const result = await resultOrPromise;
|
|
1058
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1059
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
1060
|
+
optionsTerminatorResult ??= result;
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1021
1063
|
if (result.success && result.consumed.length > 0) {
|
|
1022
1064
|
if (result.provisional) {
|
|
1023
1065
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1200,6 +1242,7 @@ function or(...args) {
|
|
|
1200
1242
|
}
|
|
1201
1243
|
}
|
|
1202
1244
|
}
|
|
1245
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1203
1246
|
return {
|
|
1204
1247
|
...error,
|
|
1205
1248
|
success: false
|
|
@@ -1301,82 +1344,122 @@ function createLongestMatch(...args) {
|
|
|
1301
1344
|
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
1302
1345
|
})()
|
|
1303
1346
|
});
|
|
1304
|
-
const
|
|
1347
|
+
const commitLongestMatch = (context, match, optionsTerminatorResult) => {
|
|
1348
|
+
const selectedResult = optionsTerminatorResult == null ? match.result : {
|
|
1349
|
+
...match.result,
|
|
1350
|
+
next: {
|
|
1351
|
+
...match.result.next,
|
|
1352
|
+
buffer: optionsTerminatorResult.next.buffer,
|
|
1353
|
+
optionsTerminated: true
|
|
1354
|
+
},
|
|
1355
|
+
consumed: [...optionsTerminatorResult.consumed, ...match.result.consumed]
|
|
1356
|
+
};
|
|
1357
|
+
const parser = parsers[match.index];
|
|
1358
|
+
const mergedExec = require_execution_context.mergeChildExec(context.exec, selectedResult.next.exec);
|
|
1359
|
+
return {
|
|
1360
|
+
success: true,
|
|
1361
|
+
next: {
|
|
1362
|
+
...context,
|
|
1363
|
+
buffer: selectedResult.next.buffer,
|
|
1364
|
+
optionsTerminated: selectedResult.next.optionsTerminated,
|
|
1365
|
+
state: createExclusiveState(context.state, match.index, parser, selectedResult),
|
|
1366
|
+
...mergedExec != null ? {
|
|
1367
|
+
exec: mergedExec,
|
|
1368
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1369
|
+
} : {}
|
|
1370
|
+
},
|
|
1371
|
+
consumed: selectedResult.consumed
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
const resolveLongestMatchOptionsTerminator = (context, bestMatch, optionsTerminatorMatches) => {
|
|
1375
|
+
if (optionsTerminatorMatches.length < 1) return null;
|
|
1376
|
+
if (bestMatch != null && bestMatch.consumed > 0) return null;
|
|
1377
|
+
const activeState = normalizeExclusiveState(context.state);
|
|
1378
|
+
if (activeState != null && activeState[1].success && activeState[1].consumed.length > 0) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1379
|
+
let selected = bestMatch == null ? null : {
|
|
1380
|
+
match: bestMatch,
|
|
1381
|
+
fromTerminator: false
|
|
1382
|
+
};
|
|
1383
|
+
for (const match of optionsTerminatorMatches) {
|
|
1384
|
+
if (!match.selectedAfterTerminator && (extractRequiredUsage(parsers[match.index].usage).length > 0 || isUnselectedBooleanOptionState(match.result.next.state))) continue;
|
|
1385
|
+
const selectedIsProvisional = selected != null && !!selected.match.result.provisional;
|
|
1386
|
+
const matchIsProvisional = !!match.result.provisional;
|
|
1387
|
+
if (selected == null || selectedIsProvisional && !matchIsProvisional || selectedIsProvisional === matchIsProvisional && match.index < selected.match.index) selected = {
|
|
1388
|
+
match,
|
|
1389
|
+
fromTerminator: true
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (selected != null) return commitLongestMatch(context, selected.match, selected.fromTerminator ? void 0 : optionsTerminatorMatches[0].result);
|
|
1393
|
+
return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1394
|
+
};
|
|
1395
|
+
const parseSyncBranches = (context) => {
|
|
1305
1396
|
let bestMatch = null;
|
|
1397
|
+
const optionsTerminatorMatches = [];
|
|
1306
1398
|
let error = getInitialError(context);
|
|
1307
1399
|
const activeState = normalizeExclusiveState(context.state);
|
|
1308
1400
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1309
1401
|
const parser = syncParsers[i];
|
|
1310
|
-
const
|
|
1402
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1403
|
+
const result = parser.parse(childContext);
|
|
1404
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1405
|
+
optionsTerminatorMatches.push({
|
|
1406
|
+
index: i,
|
|
1407
|
+
result,
|
|
1408
|
+
consumed: 1,
|
|
1409
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1410
|
+
});
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1311
1413
|
if (result.success) {
|
|
1312
1414
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1313
1415
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1314
1416
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1315
1417
|
index: i,
|
|
1316
|
-
parser,
|
|
1317
1418
|
result,
|
|
1318
1419
|
consumed
|
|
1319
1420
|
};
|
|
1320
1421
|
} else if (error.consumed < result.consumed) error = result;
|
|
1321
1422
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
success: true,
|
|
1326
|
-
next: {
|
|
1327
|
-
...context,
|
|
1328
|
-
buffer: bestMatch.result.next.buffer,
|
|
1329
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1330
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1331
|
-
...mergedExec != null ? {
|
|
1332
|
-
exec: mergedExec,
|
|
1333
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1334
|
-
} : {}
|
|
1335
|
-
},
|
|
1336
|
-
consumed: bestMatch.result.consumed
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1423
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1424
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1425
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1339
1426
|
return {
|
|
1340
1427
|
...error,
|
|
1341
1428
|
success: false
|
|
1342
1429
|
};
|
|
1343
1430
|
};
|
|
1344
|
-
const
|
|
1431
|
+
const parseAsyncBranches = async (context) => {
|
|
1345
1432
|
let bestMatch = null;
|
|
1433
|
+
const optionsTerminatorMatches = [];
|
|
1346
1434
|
let error = getInitialError(context);
|
|
1347
1435
|
const activeState = normalizeExclusiveState(context.state);
|
|
1348
1436
|
for (let i = 0; i < parsers.length; i++) {
|
|
1349
1437
|
const parser = parsers[i];
|
|
1350
|
-
const
|
|
1438
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1439
|
+
const resultOrPromise = parser.parse(childContext);
|
|
1351
1440
|
const result = await resultOrPromise;
|
|
1441
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1442
|
+
optionsTerminatorMatches.push({
|
|
1443
|
+
index: i,
|
|
1444
|
+
result,
|
|
1445
|
+
consumed: 1,
|
|
1446
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1447
|
+
});
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1352
1450
|
if (result.success) {
|
|
1353
1451
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1354
1452
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1355
1453
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1356
1454
|
index: i,
|
|
1357
|
-
parser,
|
|
1358
1455
|
result,
|
|
1359
1456
|
consumed
|
|
1360
1457
|
};
|
|
1361
1458
|
} else if (error.consumed < result.consumed) error = result;
|
|
1362
1459
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
success: true,
|
|
1367
|
-
next: {
|
|
1368
|
-
...context,
|
|
1369
|
-
buffer: bestMatch.result.next.buffer,
|
|
1370
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1371
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1372
|
-
...mergedExec != null ? {
|
|
1373
|
-
exec: mergedExec,
|
|
1374
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1375
|
-
} : {}
|
|
1376
|
-
},
|
|
1377
|
-
consumed: bestMatch.result.consumed
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1460
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1461
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1462
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1380
1463
|
return {
|
|
1381
1464
|
...error,
|
|
1382
1465
|
success: false
|
|
@@ -1399,7 +1482,7 @@ function createLongestMatch(...args) {
|
|
|
1399
1482
|
return extractExclusivePhase2Seed(parsers, state, exec, combinedMode);
|
|
1400
1483
|
},
|
|
1401
1484
|
parse(context) {
|
|
1402
|
-
return require_mode_dispatch.dispatchByMode(combinedMode, () =>
|
|
1485
|
+
return require_mode_dispatch.dispatchByMode(combinedMode, () => parseSyncBranches(context), () => parseAsyncBranches(context));
|
|
1403
1486
|
},
|
|
1404
1487
|
getSuggestRuntimeNodes(state, path) {
|
|
1405
1488
|
return getExclusiveSuggestRuntimeNodes(parsers, state, path);
|
package/dist/constructs.js
CHANGED
|
@@ -581,6 +581,35 @@ function createExclusiveState(parentState, index, parser, result) {
|
|
|
581
581
|
return annotateFreshArray(parentState, [index, annotatedResult]);
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
|
+
* Detects a branch result that handled only the global options terminator.
|
|
585
|
+
* Such a result advances the shared parser context, but does not identify
|
|
586
|
+
* which exclusive branch matched.
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function isOptionsTerminatorOnlyResult(context, result) {
|
|
590
|
+
return !context.optionsTerminated && context.buffer[0] === "--" && result.success && result.next.optionsTerminated && result.consumed.length === 1 && result.consumed[0] === "--";
|
|
591
|
+
}
|
|
592
|
+
function isUnselectedBooleanOptionState(state) {
|
|
593
|
+
return state != null && typeof state === "object" && "success" in state && state.success === true && "value" in state && state.value === false;
|
|
594
|
+
}
|
|
595
|
+
function preserveExclusiveStateAfterOptionsTerminator(context, result) {
|
|
596
|
+
const mergedExec = mergeChildExec(context.exec, result.next.exec);
|
|
597
|
+
return {
|
|
598
|
+
success: true,
|
|
599
|
+
next: {
|
|
600
|
+
...context,
|
|
601
|
+
buffer: result.next.buffer,
|
|
602
|
+
optionsTerminated: true,
|
|
603
|
+
state: context.state,
|
|
604
|
+
...mergedExec != null ? {
|
|
605
|
+
exec: mergedExec,
|
|
606
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
607
|
+
} : {}
|
|
608
|
+
},
|
|
609
|
+
consumed: result.consumed
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
584
613
|
* Creates a complete() method shared by or() and longestMatch().
|
|
585
614
|
* @internal
|
|
586
615
|
*/
|
|
@@ -818,9 +847,15 @@ function or(...args) {
|
|
|
818
847
|
let zeroConsumedBranch = null;
|
|
819
848
|
let zeroConsumedCount = 0;
|
|
820
849
|
let provisionalConsuming = null;
|
|
850
|
+
let optionsTerminatorResult = null;
|
|
821
851
|
let provisionalAmbiguous = false;
|
|
822
852
|
for (const [parser, i] of orderedParsers) {
|
|
823
853
|
const result = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
854
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
855
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
856
|
+
optionsTerminatorResult ??= result;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
824
859
|
if (result.success && result.consumed.length > 0) {
|
|
825
860
|
if (result.provisional) {
|
|
826
861
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1001,6 +1036,7 @@ function or(...args) {
|
|
|
1001
1036
|
}
|
|
1002
1037
|
}
|
|
1003
1038
|
}
|
|
1039
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1004
1040
|
return {
|
|
1005
1041
|
...error,
|
|
1006
1042
|
success: false
|
|
@@ -1014,10 +1050,16 @@ function or(...args) {
|
|
|
1014
1050
|
let zeroConsumedBranch = null;
|
|
1015
1051
|
let zeroConsumedCount = 0;
|
|
1016
1052
|
let provisionalConsuming = null;
|
|
1053
|
+
let optionsTerminatorResult = null;
|
|
1017
1054
|
let provisionalAmbiguous = false;
|
|
1018
1055
|
for (const [parser, i] of orderedParsers) {
|
|
1019
1056
|
const resultOrPromise = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
1020
1057
|
const result = await resultOrPromise;
|
|
1058
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1059
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
1060
|
+
optionsTerminatorResult ??= result;
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1021
1063
|
if (result.success && result.consumed.length > 0) {
|
|
1022
1064
|
if (result.provisional) {
|
|
1023
1065
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1200,6 +1242,7 @@ function or(...args) {
|
|
|
1200
1242
|
}
|
|
1201
1243
|
}
|
|
1202
1244
|
}
|
|
1245
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1203
1246
|
return {
|
|
1204
1247
|
...error,
|
|
1205
1248
|
success: false
|
|
@@ -1301,82 +1344,122 @@ function createLongestMatch(...args) {
|
|
|
1301
1344
|
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
1302
1345
|
})()
|
|
1303
1346
|
});
|
|
1304
|
-
const
|
|
1347
|
+
const commitLongestMatch = (context, match, optionsTerminatorResult) => {
|
|
1348
|
+
const selectedResult = optionsTerminatorResult == null ? match.result : {
|
|
1349
|
+
...match.result,
|
|
1350
|
+
next: {
|
|
1351
|
+
...match.result.next,
|
|
1352
|
+
buffer: optionsTerminatorResult.next.buffer,
|
|
1353
|
+
optionsTerminated: true
|
|
1354
|
+
},
|
|
1355
|
+
consumed: [...optionsTerminatorResult.consumed, ...match.result.consumed]
|
|
1356
|
+
};
|
|
1357
|
+
const parser = parsers[match.index];
|
|
1358
|
+
const mergedExec = mergeChildExec(context.exec, selectedResult.next.exec);
|
|
1359
|
+
return {
|
|
1360
|
+
success: true,
|
|
1361
|
+
next: {
|
|
1362
|
+
...context,
|
|
1363
|
+
buffer: selectedResult.next.buffer,
|
|
1364
|
+
optionsTerminated: selectedResult.next.optionsTerminated,
|
|
1365
|
+
state: createExclusiveState(context.state, match.index, parser, selectedResult),
|
|
1366
|
+
...mergedExec != null ? {
|
|
1367
|
+
exec: mergedExec,
|
|
1368
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1369
|
+
} : {}
|
|
1370
|
+
},
|
|
1371
|
+
consumed: selectedResult.consumed
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
const resolveLongestMatchOptionsTerminator = (context, bestMatch, optionsTerminatorMatches) => {
|
|
1375
|
+
if (optionsTerminatorMatches.length < 1) return null;
|
|
1376
|
+
if (bestMatch != null && bestMatch.consumed > 0) return null;
|
|
1377
|
+
const activeState = normalizeExclusiveState(context.state);
|
|
1378
|
+
if (activeState != null && activeState[1].success && activeState[1].consumed.length > 0) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1379
|
+
let selected = bestMatch == null ? null : {
|
|
1380
|
+
match: bestMatch,
|
|
1381
|
+
fromTerminator: false
|
|
1382
|
+
};
|
|
1383
|
+
for (const match of optionsTerminatorMatches) {
|
|
1384
|
+
if (!match.selectedAfterTerminator && (extractRequiredUsage(parsers[match.index].usage).length > 0 || isUnselectedBooleanOptionState(match.result.next.state))) continue;
|
|
1385
|
+
const selectedIsProvisional = selected != null && !!selected.match.result.provisional;
|
|
1386
|
+
const matchIsProvisional = !!match.result.provisional;
|
|
1387
|
+
if (selected == null || selectedIsProvisional && !matchIsProvisional || selectedIsProvisional === matchIsProvisional && match.index < selected.match.index) selected = {
|
|
1388
|
+
match,
|
|
1389
|
+
fromTerminator: true
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (selected != null) return commitLongestMatch(context, selected.match, selected.fromTerminator ? void 0 : optionsTerminatorMatches[0].result);
|
|
1393
|
+
return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1394
|
+
};
|
|
1395
|
+
const parseSyncBranches = (context) => {
|
|
1305
1396
|
let bestMatch = null;
|
|
1397
|
+
const optionsTerminatorMatches = [];
|
|
1306
1398
|
let error = getInitialError(context);
|
|
1307
1399
|
const activeState = normalizeExclusiveState(context.state);
|
|
1308
1400
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1309
1401
|
const parser = syncParsers[i];
|
|
1310
|
-
const
|
|
1402
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1403
|
+
const result = parser.parse(childContext);
|
|
1404
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1405
|
+
optionsTerminatorMatches.push({
|
|
1406
|
+
index: i,
|
|
1407
|
+
result,
|
|
1408
|
+
consumed: 1,
|
|
1409
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1410
|
+
});
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1311
1413
|
if (result.success) {
|
|
1312
1414
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1313
1415
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1314
1416
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1315
1417
|
index: i,
|
|
1316
|
-
parser,
|
|
1317
1418
|
result,
|
|
1318
1419
|
consumed
|
|
1319
1420
|
};
|
|
1320
1421
|
} else if (error.consumed < result.consumed) error = result;
|
|
1321
1422
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
success: true,
|
|
1326
|
-
next: {
|
|
1327
|
-
...context,
|
|
1328
|
-
buffer: bestMatch.result.next.buffer,
|
|
1329
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1330
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1331
|
-
...mergedExec != null ? {
|
|
1332
|
-
exec: mergedExec,
|
|
1333
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1334
|
-
} : {}
|
|
1335
|
-
},
|
|
1336
|
-
consumed: bestMatch.result.consumed
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1423
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1424
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1425
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1339
1426
|
return {
|
|
1340
1427
|
...error,
|
|
1341
1428
|
success: false
|
|
1342
1429
|
};
|
|
1343
1430
|
};
|
|
1344
|
-
const
|
|
1431
|
+
const parseAsyncBranches = async (context) => {
|
|
1345
1432
|
let bestMatch = null;
|
|
1433
|
+
const optionsTerminatorMatches = [];
|
|
1346
1434
|
let error = getInitialError(context);
|
|
1347
1435
|
const activeState = normalizeExclusiveState(context.state);
|
|
1348
1436
|
for (let i = 0; i < parsers.length; i++) {
|
|
1349
1437
|
const parser = parsers[i];
|
|
1350
|
-
const
|
|
1438
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1439
|
+
const resultOrPromise = parser.parse(childContext);
|
|
1351
1440
|
const result = await resultOrPromise;
|
|
1441
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1442
|
+
optionsTerminatorMatches.push({
|
|
1443
|
+
index: i,
|
|
1444
|
+
result,
|
|
1445
|
+
consumed: 1,
|
|
1446
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1447
|
+
});
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1352
1450
|
if (result.success) {
|
|
1353
1451
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1354
1452
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1355
1453
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1356
1454
|
index: i,
|
|
1357
|
-
parser,
|
|
1358
1455
|
result,
|
|
1359
1456
|
consumed
|
|
1360
1457
|
};
|
|
1361
1458
|
} else if (error.consumed < result.consumed) error = result;
|
|
1362
1459
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
success: true,
|
|
1367
|
-
next: {
|
|
1368
|
-
...context,
|
|
1369
|
-
buffer: bestMatch.result.next.buffer,
|
|
1370
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1371
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1372
|
-
...mergedExec != null ? {
|
|
1373
|
-
exec: mergedExec,
|
|
1374
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1375
|
-
} : {}
|
|
1376
|
-
},
|
|
1377
|
-
consumed: bestMatch.result.consumed
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1460
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1461
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1462
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1380
1463
|
return {
|
|
1381
1464
|
...error,
|
|
1382
1465
|
success: false
|
|
@@ -1399,7 +1482,7 @@ function createLongestMatch(...args) {
|
|
|
1399
1482
|
return extractExclusivePhase2Seed(parsers, state, exec, combinedMode);
|
|
1400
1483
|
},
|
|
1401
1484
|
parse(context) {
|
|
1402
|
-
return dispatchByMode(combinedMode, () =>
|
|
1485
|
+
return dispatchByMode(combinedMode, () => parseSyncBranches(context), () => parseAsyncBranches(context));
|
|
1403
1486
|
},
|
|
1404
1487
|
getSuggestRuntimeNodes(state, path) {
|
|
1405
1488
|
return getExclusiveSuggestRuntimeNodes(parsers, state, path);
|
package/dist/primitives.cjs
CHANGED
|
@@ -247,7 +247,7 @@ function* getSuggestionsWithDependency(valueParser, prefix, dependencyRegistry,
|
|
|
247
247
|
* Internal sync helper for option suggest functionality.
|
|
248
248
|
* @internal
|
|
249
249
|
*/
|
|
250
|
-
function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix) {
|
|
250
|
+
function* suggestOptionSync(optionNames$1, valueParser, hidden, description, context, prefix) {
|
|
251
251
|
if (hidden) return;
|
|
252
252
|
const equalsIndex = prefix.indexOf("=");
|
|
253
253
|
if (equalsIndex >= 0) {
|
|
@@ -275,7 +275,8 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
275
275
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
276
276
|
yield {
|
|
277
277
|
kind: "literal",
|
|
278
|
-
text: optionName$1
|
|
278
|
+
text: optionName$1,
|
|
279
|
+
...description && { description }
|
|
279
280
|
};
|
|
280
281
|
}
|
|
281
282
|
}
|
|
@@ -331,7 +332,7 @@ async function* getSuggestionsWithDependencyAsync(valueParser, prefix, dependenc
|
|
|
331
332
|
* Internal async helper for option suggest functionality.
|
|
332
333
|
* @internal
|
|
333
334
|
*/
|
|
334
|
-
async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context, prefix) {
|
|
335
|
+
async function* suggestOptionAsync(optionNames$1, valueParser, hidden, description, context, prefix) {
|
|
335
336
|
if (hidden) return;
|
|
336
337
|
const equalsIndex = prefix.indexOf("=");
|
|
337
338
|
if (equalsIndex >= 0) {
|
|
@@ -359,7 +360,8 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
359
360
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
360
361
|
yield {
|
|
361
362
|
kind: "literal",
|
|
362
|
-
text: optionName$1
|
|
363
|
+
text: optionName$1,
|
|
364
|
+
...description && { description }
|
|
363
365
|
};
|
|
364
366
|
}
|
|
365
367
|
}
|
|
@@ -628,8 +630,8 @@ function option(...args) {
|
|
|
628
630
|
return require_mode_dispatch.dispatchByMode(mode, completeSync, completeAsync);
|
|
629
631
|
},
|
|
630
632
|
suggest(context, prefix) {
|
|
631
|
-
if (isAsync) return suggestOptionAsync(optionNames$1, valueParser, require_usage.isSuggestionHidden(options.hidden), context, prefix);
|
|
632
|
-
return suggestOptionSync(optionNames$1, valueParser, require_usage.isSuggestionHidden(options.hidden), context, prefix);
|
|
633
|
+
if (isAsync) return suggestOptionAsync(optionNames$1, valueParser, require_usage.isSuggestionHidden(options.hidden), options.description, context, prefix);
|
|
634
|
+
return suggestOptionSync(optionNames$1, valueParser, require_usage.isSuggestionHidden(options.hidden), options.description, context, prefix);
|
|
633
635
|
},
|
|
634
636
|
getDocFragments(_state, defaultValue) {
|
|
635
637
|
if (require_usage.isDocHidden(options.hidden)) return {
|
|
@@ -910,7 +912,8 @@ function flag(...args) {
|
|
|
910
912
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
911
913
|
suggestions.push({
|
|
912
914
|
kind: "literal",
|
|
913
|
-
text: optionName$1
|
|
915
|
+
text: optionName$1,
|
|
916
|
+
...options.description && { description: options.description }
|
|
914
917
|
});
|
|
915
918
|
}
|
|
916
919
|
}
|
|
@@ -1427,10 +1430,11 @@ function* suggestCommandSync(context, prefix, name, aliases, parser, options) {
|
|
|
1427
1430
|
if (require_usage.isSuggestionHidden(options.hidden)) return;
|
|
1428
1431
|
const state = normalizeCommandState(context.state);
|
|
1429
1432
|
if (state === void 0) {
|
|
1433
|
+
const description = options.brief ?? options.description;
|
|
1430
1434
|
for (const commandName of [name, ...aliases]) if (commandName.startsWith(prefix)) yield {
|
|
1431
1435
|
kind: "literal",
|
|
1432
1436
|
text: commandName,
|
|
1433
|
-
...
|
|
1437
|
+
...description && { description }
|
|
1434
1438
|
};
|
|
1435
1439
|
} else if (state[0] === "matched") yield* parser.suggest(require_execution_context.withChildContext(context, name, getCommandChildState(context.state, parser.initialState, parser), parser.usage), prefix);
|
|
1436
1440
|
else if (state[0] === "parsing") yield* parser.suggest(require_execution_context.withChildContext(context, name, getCommandChildState(context.state, state[1], parser), parser.usage), prefix);
|
|
@@ -1439,10 +1443,11 @@ async function* suggestCommandAsync(context, prefix, name, aliases, parser, opti
|
|
|
1439
1443
|
if (require_usage.isSuggestionHidden(options.hidden)) return;
|
|
1440
1444
|
const state = normalizeCommandState(context.state);
|
|
1441
1445
|
if (state === void 0) {
|
|
1446
|
+
const description = options.brief ?? options.description;
|
|
1442
1447
|
for (const commandName of [name, ...aliases]) if (commandName.startsWith(prefix)) yield {
|
|
1443
1448
|
kind: "literal",
|
|
1444
1449
|
text: commandName,
|
|
1445
|
-
...
|
|
1450
|
+
...description && { description }
|
|
1446
1451
|
};
|
|
1447
1452
|
} else if (state[0] === "matched") {
|
|
1448
1453
|
const suggestions = parser.suggest(require_execution_context.withChildContext(context, name, getCommandChildState(context.state, parser.initialState, parser), parser.usage), prefix);
|
package/dist/primitives.js
CHANGED
|
@@ -247,7 +247,7 @@ function* getSuggestionsWithDependency(valueParser, prefix, dependencyRegistry,
|
|
|
247
247
|
* Internal sync helper for option suggest functionality.
|
|
248
248
|
* @internal
|
|
249
249
|
*/
|
|
250
|
-
function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix) {
|
|
250
|
+
function* suggestOptionSync(optionNames$1, valueParser, hidden, description, context, prefix) {
|
|
251
251
|
if (hidden) return;
|
|
252
252
|
const equalsIndex = prefix.indexOf("=");
|
|
253
253
|
if (equalsIndex >= 0) {
|
|
@@ -275,7 +275,8 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
275
275
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
276
276
|
yield {
|
|
277
277
|
kind: "literal",
|
|
278
|
-
text: optionName$1
|
|
278
|
+
text: optionName$1,
|
|
279
|
+
...description && { description }
|
|
279
280
|
};
|
|
280
281
|
}
|
|
281
282
|
}
|
|
@@ -331,7 +332,7 @@ async function* getSuggestionsWithDependencyAsync(valueParser, prefix, dependenc
|
|
|
331
332
|
* Internal async helper for option suggest functionality.
|
|
332
333
|
* @internal
|
|
333
334
|
*/
|
|
334
|
-
async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context, prefix) {
|
|
335
|
+
async function* suggestOptionAsync(optionNames$1, valueParser, hidden, description, context, prefix) {
|
|
335
336
|
if (hidden) return;
|
|
336
337
|
const equalsIndex = prefix.indexOf("=");
|
|
337
338
|
if (equalsIndex >= 0) {
|
|
@@ -359,7 +360,8 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
359
360
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
360
361
|
yield {
|
|
361
362
|
kind: "literal",
|
|
362
|
-
text: optionName$1
|
|
363
|
+
text: optionName$1,
|
|
364
|
+
...description && { description }
|
|
363
365
|
};
|
|
364
366
|
}
|
|
365
367
|
}
|
|
@@ -628,8 +630,8 @@ function option(...args) {
|
|
|
628
630
|
return dispatchByMode(mode, completeSync, completeAsync);
|
|
629
631
|
},
|
|
630
632
|
suggest(context, prefix) {
|
|
631
|
-
if (isAsync) return suggestOptionAsync(optionNames$1, valueParser, isSuggestionHidden(options.hidden), context, prefix);
|
|
632
|
-
return suggestOptionSync(optionNames$1, valueParser, isSuggestionHidden(options.hidden), context, prefix);
|
|
633
|
+
if (isAsync) return suggestOptionAsync(optionNames$1, valueParser, isSuggestionHidden(options.hidden), options.description, context, prefix);
|
|
634
|
+
return suggestOptionSync(optionNames$1, valueParser, isSuggestionHidden(options.hidden), options.description, context, prefix);
|
|
633
635
|
},
|
|
634
636
|
getDocFragments(_state, defaultValue) {
|
|
635
637
|
if (isDocHidden(options.hidden)) return {
|
|
@@ -910,7 +912,8 @@ function flag(...args) {
|
|
|
910
912
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
911
913
|
suggestions.push({
|
|
912
914
|
kind: "literal",
|
|
913
|
-
text: optionName$1
|
|
915
|
+
text: optionName$1,
|
|
916
|
+
...options.description && { description: options.description }
|
|
914
917
|
});
|
|
915
918
|
}
|
|
916
919
|
}
|
|
@@ -1427,10 +1430,11 @@ function* suggestCommandSync(context, prefix, name, aliases, parser, options) {
|
|
|
1427
1430
|
if (isSuggestionHidden(options.hidden)) return;
|
|
1428
1431
|
const state = normalizeCommandState(context.state);
|
|
1429
1432
|
if (state === void 0) {
|
|
1433
|
+
const description = options.brief ?? options.description;
|
|
1430
1434
|
for (const commandName of [name, ...aliases]) if (commandName.startsWith(prefix)) yield {
|
|
1431
1435
|
kind: "literal",
|
|
1432
1436
|
text: commandName,
|
|
1433
|
-
...
|
|
1437
|
+
...description && { description }
|
|
1434
1438
|
};
|
|
1435
1439
|
} else if (state[0] === "matched") yield* parser.suggest(withChildContext(context, name, getCommandChildState(context.state, parser.initialState, parser), parser.usage), prefix);
|
|
1436
1440
|
else if (state[0] === "parsing") yield* parser.suggest(withChildContext(context, name, getCommandChildState(context.state, state[1], parser), parser.usage), prefix);
|
|
@@ -1439,10 +1443,11 @@ async function* suggestCommandAsync(context, prefix, name, aliases, parser, opti
|
|
|
1439
1443
|
if (isSuggestionHidden(options.hidden)) return;
|
|
1440
1444
|
const state = normalizeCommandState(context.state);
|
|
1441
1445
|
if (state === void 0) {
|
|
1446
|
+
const description = options.brief ?? options.description;
|
|
1442
1447
|
for (const commandName of [name, ...aliases]) if (commandName.startsWith(prefix)) yield {
|
|
1443
1448
|
kind: "literal",
|
|
1444
1449
|
text: commandName,
|
|
1445
|
-
...
|
|
1450
|
+
...description && { description }
|
|
1446
1451
|
};
|
|
1447
1452
|
} else if (state[0] === "matched") {
|
|
1448
1453
|
const suggestions = parser.suggest(withChildContext(context, name, getCommandChildState(context.state, parser.initialState, parser), parser.usage), prefix);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Type-safe combinatorial command-line interface parser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
"fast-check": "^4.7.0",
|
|
201
201
|
"tsdown": "^0.13.0",
|
|
202
202
|
"typescript": "^5.8.3",
|
|
203
|
-
"@optique/env": "1.1.
|
|
203
|
+
"@optique/env": "1.1.3"
|
|
204
204
|
},
|
|
205
205
|
"scripts": {
|
|
206
206
|
"build": "tsdown",
|