@optique/core 0.3.0-dev.40 → 0.3.0-dev.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/facade.cjs +32 -6
- package/dist/facade.js +33 -7
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/parser.cjs +81 -0
- package/dist/parser.d.cts +79 -1
- package/dist/parser.d.ts +79 -1
- package/dist/parser.js +81 -1
- package/package.json +1 -1
package/dist/facade.cjs
CHANGED
|
@@ -38,22 +38,48 @@ function run(parser, programName, args, options = {}) {
|
|
|
38
38
|
let { colors, maxWidth, help = "none", onHelp = () => {}, aboveError = "usage", onError = () => {
|
|
39
39
|
throw new RunError("Failed to parse command line arguments.");
|
|
40
40
|
}, stderr = console.error, stdout = console.log } = options;
|
|
41
|
+
const contextualHelpParser = require_parser.object({
|
|
42
|
+
help: require_parser.constant(true),
|
|
43
|
+
commands: require_parser.multiple(require_parser.argument(require_valueparser.string({ metavar: "COMMAND" }))),
|
|
44
|
+
__help: require_parser.flag("--help")
|
|
45
|
+
});
|
|
41
46
|
const helpCommand = require_parser.command("help", require_parser.multiple(require_parser.argument(require_valueparser.string({ metavar: "COMMAND" }))), { description: require_message.message`Show help information.` });
|
|
42
47
|
const helpOption = require_parser.option("--help", { description: require_message.message`Show help information.` });
|
|
43
|
-
const augmentedParser = help === "none" ? require_parser.object({
|
|
48
|
+
const augmentedParser = help === "none" ? parser : help === "command" ? require_parser.longestMatch(require_parser.object({
|
|
49
|
+
help: require_parser.constant(true),
|
|
50
|
+
commands: helpCommand
|
|
51
|
+
}), require_parser.object({
|
|
44
52
|
help: require_parser.constant(false),
|
|
45
53
|
result: parser
|
|
46
|
-
}) : require_parser.
|
|
54
|
+
})) : help === "option" ? require_parser.longestMatch(require_parser.object({
|
|
55
|
+
help: require_parser.constant(false),
|
|
56
|
+
result: parser
|
|
57
|
+
}), contextualHelpParser, require_parser.merge(require_parser.object({
|
|
58
|
+
help: require_parser.constant(true),
|
|
59
|
+
commands: require_parser.constant([])
|
|
60
|
+
}), helpOption)) : require_parser.longestMatch(require_parser.object({
|
|
47
61
|
help: require_parser.constant(false),
|
|
48
62
|
result: parser
|
|
49
63
|
}), require_parser.object({
|
|
50
64
|
help: require_parser.constant(true),
|
|
51
|
-
|
|
52
|
-
})
|
|
65
|
+
commands: helpCommand
|
|
66
|
+
}), contextualHelpParser, require_parser.merge(require_parser.object({
|
|
67
|
+
help: require_parser.constant(true),
|
|
68
|
+
commands: require_parser.constant([])
|
|
69
|
+
}), helpOption));
|
|
53
70
|
const result = require_parser.parse(augmentedParser, args);
|
|
54
71
|
if (result.success) {
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
const value = result.value;
|
|
73
|
+
if (help === "none") return value;
|
|
74
|
+
if (typeof value === "object" && value != null && "help" in value) {
|
|
75
|
+
const helpValue$1 = value;
|
|
76
|
+
if (!helpValue$1.help) return helpValue$1.result;
|
|
77
|
+
} else return value;
|
|
78
|
+
let commandContext = [];
|
|
79
|
+
const helpValue = value;
|
|
80
|
+
if (Array.isArray(helpValue.commands)) commandContext = helpValue.commands;
|
|
81
|
+
else if (typeof helpValue.commands === "object" && helpValue.commands != null && "length" in helpValue.commands) commandContext = helpValue.commands;
|
|
82
|
+
const doc = require_parser.getDocPage(commandContext.length < 1 ? augmentedParser : parser, commandContext);
|
|
57
83
|
if (doc != null) stdout(require_doc.formatDocPage(programName, doc, {
|
|
58
84
|
colors,
|
|
59
85
|
maxWidth
|
package/dist/facade.js
CHANGED
|
@@ -2,7 +2,7 @@ import { formatMessage, message } from "./message.js";
|
|
|
2
2
|
import { formatUsage } from "./usage.js";
|
|
3
3
|
import { formatDocPage } from "./doc.js";
|
|
4
4
|
import { string } from "./valueparser.js";
|
|
5
|
-
import { argument, command, constant, getDocPage, multiple, object, option,
|
|
5
|
+
import { argument, command, constant, flag, getDocPage, longestMatch, merge, multiple, object, option, parse } from "./parser.js";
|
|
6
6
|
|
|
7
7
|
//#region src/facade.ts
|
|
8
8
|
/**
|
|
@@ -38,22 +38,48 @@ function run(parser, programName, args, options = {}) {
|
|
|
38
38
|
let { colors, maxWidth, help = "none", onHelp = () => {}, aboveError = "usage", onError = () => {
|
|
39
39
|
throw new RunError("Failed to parse command line arguments.");
|
|
40
40
|
}, stderr = console.error, stdout = console.log } = options;
|
|
41
|
+
const contextualHelpParser = object({
|
|
42
|
+
help: constant(true),
|
|
43
|
+
commands: multiple(argument(string({ metavar: "COMMAND" }))),
|
|
44
|
+
__help: flag("--help")
|
|
45
|
+
});
|
|
41
46
|
const helpCommand = command("help", multiple(argument(string({ metavar: "COMMAND" }))), { description: message`Show help information.` });
|
|
42
47
|
const helpOption = option("--help", { description: message`Show help information.` });
|
|
43
|
-
const augmentedParser = help === "none" ? object({
|
|
48
|
+
const augmentedParser = help === "none" ? parser : help === "command" ? longestMatch(object({
|
|
49
|
+
help: constant(true),
|
|
50
|
+
commands: helpCommand
|
|
51
|
+
}), object({
|
|
44
52
|
help: constant(false),
|
|
45
53
|
result: parser
|
|
46
|
-
}) :
|
|
54
|
+
})) : help === "option" ? longestMatch(object({
|
|
55
|
+
help: constant(false),
|
|
56
|
+
result: parser
|
|
57
|
+
}), contextualHelpParser, merge(object({
|
|
58
|
+
help: constant(true),
|
|
59
|
+
commands: constant([])
|
|
60
|
+
}), helpOption)) : longestMatch(object({
|
|
47
61
|
help: constant(false),
|
|
48
62
|
result: parser
|
|
49
63
|
}), object({
|
|
50
64
|
help: constant(true),
|
|
51
|
-
|
|
52
|
-
})
|
|
65
|
+
commands: helpCommand
|
|
66
|
+
}), contextualHelpParser, merge(object({
|
|
67
|
+
help: constant(true),
|
|
68
|
+
commands: constant([])
|
|
69
|
+
}), helpOption));
|
|
53
70
|
const result = parse(augmentedParser, args);
|
|
54
71
|
if (result.success) {
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
const value = result.value;
|
|
73
|
+
if (help === "none") return value;
|
|
74
|
+
if (typeof value === "object" && value != null && "help" in value) {
|
|
75
|
+
const helpValue$1 = value;
|
|
76
|
+
if (!helpValue$1.help) return helpValue$1.result;
|
|
77
|
+
} else return value;
|
|
78
|
+
let commandContext = [];
|
|
79
|
+
const helpValue = value;
|
|
80
|
+
if (Array.isArray(helpValue.commands)) commandContext = helpValue.commands;
|
|
81
|
+
else if (typeof helpValue.commands === "object" && helpValue.commands != null && "length" in helpValue.commands) commandContext = helpValue.commands;
|
|
82
|
+
const doc = getDocPage(commandContext.length < 1 ? augmentedParser : parser, commandContext);
|
|
57
83
|
if (doc != null) stdout(formatDocPage(programName, doc, {
|
|
58
84
|
colors,
|
|
59
85
|
maxWidth
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ exports.getDocPage = require_parser.getDocPage;
|
|
|
21
21
|
exports.integer = require_valueparser.integer;
|
|
22
22
|
exports.isValueParser = require_valueparser.isValueParser;
|
|
23
23
|
exports.locale = require_valueparser.locale;
|
|
24
|
+
exports.longestMatch = require_parser.longestMatch;
|
|
24
25
|
exports.map = require_parser.map;
|
|
25
26
|
exports.merge = require_parser.merge;
|
|
26
27
|
exports.message = require_message.message;
|
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,6 @@ import { Message, MessageFormatOptions, MessageTerm, formatMessage, message, met
|
|
|
2
2
|
import { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, formatUsage, formatUsageTerm, normalizeUsage } from "./usage.cjs";
|
|
3
3
|
import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, formatDocPage } from "./doc.cjs";
|
|
4
4
|
import { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, float, integer, isValueParser, locale, string, url, uuid } from "./valueparser.cjs";
|
|
5
|
-
import { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.cjs";
|
|
5
|
+
import { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.cjs";
|
|
6
6
|
import { RunError, RunOptions, run } from "./facade.cjs";
|
|
7
|
-
export { ArgumentOptions, ChoiceOptions, CommandOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, Message, MessageFormatOptions, MessageTerm, MultipleOptions, OptionName, OptionOptions, Parser, ParserContext, ParserResult, Result, RunError, RunOptions, StringOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
|
7
|
+
export { ArgumentOptions, ChoiceOptions, CommandOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, Message, MessageFormatOptions, MessageTerm, MultipleOptions, OptionName, OptionOptions, Parser, ParserContext, ParserResult, Result, RunError, RunOptions, StringOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { Message, MessageFormatOptions, MessageTerm, formatMessage, message, met
|
|
|
2
2
|
import { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, formatUsage, formatUsageTerm, normalizeUsage } from "./usage.js";
|
|
3
3
|
import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, formatDocPage } from "./doc.js";
|
|
4
4
|
import { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, float, integer, isValueParser, locale, string, url, uuid } from "./valueparser.js";
|
|
5
|
-
import { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.js";
|
|
5
|
+
import { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.js";
|
|
6
6
|
import { RunError, RunOptions, run } from "./facade.js";
|
|
7
|
-
export { ArgumentOptions, ChoiceOptions, CommandOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, Message, MessageFormatOptions, MessageTerm, MultipleOptions, OptionName, OptionOptions, Parser, ParserContext, ParserResult, Result, RunError, RunOptions, StringOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
|
7
|
+
export { ArgumentOptions, ChoiceOptions, CommandOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, Message, MessageFormatOptions, MessageTerm, MultipleOptions, OptionName, OptionOptions, Parser, ParserContext, ParserResult, Result, RunError, RunOptions, StringOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { formatMessage, message, metavar, optionName, optionNames, text, value,
|
|
|
2
2
|
import { formatUsage, formatUsageTerm, normalizeUsage } from "./usage.js";
|
|
3
3
|
import { formatDocPage } from "./doc.js";
|
|
4
4
|
import { choice, float, integer, isValueParser, locale, string, url, uuid } from "./valueparser.js";
|
|
5
|
-
import { argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.js";
|
|
5
|
+
import { argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault } from "./parser.js";
|
|
6
6
|
import { RunError, run } from "./facade.js";
|
|
7
7
|
|
|
8
|
-
export { RunError, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
|
8
|
+
export { RunError, argument, choice, command, concat, constant, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, object, option, optionName, optionNames, optional, or, parse, run, string, text, tuple, url, uuid, value, values, withDefault };
|
package/dist/parser.cjs
CHANGED
|
@@ -1031,6 +1031,86 @@ function or(...parsers) {
|
|
|
1031
1031
|
}
|
|
1032
1032
|
};
|
|
1033
1033
|
}
|
|
1034
|
+
function longestMatch(...parsers) {
|
|
1035
|
+
return {
|
|
1036
|
+
$valueType: [],
|
|
1037
|
+
$stateType: [],
|
|
1038
|
+
priority: Math.max(...parsers.map((p) => p.priority)),
|
|
1039
|
+
usage: [{
|
|
1040
|
+
type: "exclusive",
|
|
1041
|
+
terms: parsers.map((p) => p.usage)
|
|
1042
|
+
}],
|
|
1043
|
+
initialState: void 0,
|
|
1044
|
+
complete(state) {
|
|
1045
|
+
if (state == null) return {
|
|
1046
|
+
success: false,
|
|
1047
|
+
error: require_message.message`No parser matched.`
|
|
1048
|
+
};
|
|
1049
|
+
const [i, result] = state;
|
|
1050
|
+
if (result.success) return parsers[i].complete(result.next.state);
|
|
1051
|
+
return {
|
|
1052
|
+
success: false,
|
|
1053
|
+
error: result.error
|
|
1054
|
+
};
|
|
1055
|
+
},
|
|
1056
|
+
parse(context) {
|
|
1057
|
+
let bestMatch = null;
|
|
1058
|
+
let error = {
|
|
1059
|
+
consumed: 0,
|
|
1060
|
+
error: context.buffer.length < 1 ? require_message.message`No parser matched.` : require_message.message`Unexpected option or subcommand: ${require_message.optionName(context.buffer[0])}.`
|
|
1061
|
+
};
|
|
1062
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1063
|
+
const parser = parsers[i];
|
|
1064
|
+
const result = parser.parse({
|
|
1065
|
+
...context,
|
|
1066
|
+
state: context.state == null || context.state[0] !== i || !context.state[1].success ? parser.initialState : context.state[1].next.state
|
|
1067
|
+
});
|
|
1068
|
+
if (result.success) {
|
|
1069
|
+
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1070
|
+
if (bestMatch === null || consumed > bestMatch.consumed) bestMatch = {
|
|
1071
|
+
index: i,
|
|
1072
|
+
result,
|
|
1073
|
+
consumed
|
|
1074
|
+
};
|
|
1075
|
+
} else if (error.consumed < result.consumed) error = result;
|
|
1076
|
+
}
|
|
1077
|
+
if (bestMatch && bestMatch.result.success) return {
|
|
1078
|
+
success: true,
|
|
1079
|
+
next: {
|
|
1080
|
+
...context,
|
|
1081
|
+
buffer: bestMatch.result.next.buffer,
|
|
1082
|
+
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1083
|
+
state: [bestMatch.index, bestMatch.result]
|
|
1084
|
+
},
|
|
1085
|
+
consumed: bestMatch.result.consumed
|
|
1086
|
+
};
|
|
1087
|
+
return {
|
|
1088
|
+
...error,
|
|
1089
|
+
success: false
|
|
1090
|
+
};
|
|
1091
|
+
},
|
|
1092
|
+
getDocFragments(state, _defaultValue) {
|
|
1093
|
+
let description;
|
|
1094
|
+
let fragments;
|
|
1095
|
+
if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
1096
|
+
else {
|
|
1097
|
+
const [i, result] = state.state;
|
|
1098
|
+
if (result.success) {
|
|
1099
|
+
const docResult = parsers[i].getDocFragments({
|
|
1100
|
+
kind: "available",
|
|
1101
|
+
state: result.next.state
|
|
1102
|
+
});
|
|
1103
|
+
description = docResult.description;
|
|
1104
|
+
fragments = docResult.fragments;
|
|
1105
|
+
} else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
1106
|
+
}
|
|
1107
|
+
return {
|
|
1108
|
+
description,
|
|
1109
|
+
fragments
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1034
1114
|
function merge(...parsers) {
|
|
1035
1115
|
parsers = parsers.toSorted((a, b) => b.priority - a.priority);
|
|
1036
1116
|
const initialState = {};
|
|
@@ -1483,6 +1563,7 @@ exports.concat = concat;
|
|
|
1483
1563
|
exports.constant = constant;
|
|
1484
1564
|
exports.flag = flag;
|
|
1485
1565
|
exports.getDocPage = getDocPage;
|
|
1566
|
+
exports.longestMatch = longestMatch;
|
|
1486
1567
|
exports.map = map;
|
|
1487
1568
|
exports.merge = merge;
|
|
1488
1569
|
exports.multiple = multiple;
|
package/dist/parser.d.cts
CHANGED
|
@@ -648,6 +648,84 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TStateA, TStateB, TState
|
|
|
648
648
|
* in order, returning the result of the first successful parser.
|
|
649
649
|
*/
|
|
650
650
|
declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TStateC, TStateD, TStateE, TStateF, TStateG, TStateH, TStateI, TStateJ>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>, f: Parser<TF, TStateF>, g: Parser<TG, TStateG>, h: Parser<TH, TStateH>, i: Parser<TI, TStateI>, j: Parser<TJ, TStateJ>): Parser<TA | TB | TC | TD | TE | TF | TG | TH | TI | TJ, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>] | [5, ParserResult<TStateF>] | [6, ParserResult<TStateG>] | [7, ParserResult<TStateH>] | [8, ParserResult<TStateI>] | [9, ParserResult<TStateJ>]>;
|
|
651
|
+
/**
|
|
652
|
+
* Creates a parser that combines two mutually exclusive parsers into one,
|
|
653
|
+
* selecting the parser that consumes the most tokens.
|
|
654
|
+
* The resulting parser will try both parsers and return the result
|
|
655
|
+
* of the parser that consumed more input tokens.
|
|
656
|
+
* @template TA The type of the value returned by the first parser.
|
|
657
|
+
* @template TB The type of the value returned by the second parser.
|
|
658
|
+
* @template TStateA The type of the state used by the first parser.
|
|
659
|
+
* @template TStateB The type of the state used by the second parser.
|
|
660
|
+
* @param a The first {@link Parser} to try.
|
|
661
|
+
* @param b The second {@link Parser} to try.
|
|
662
|
+
* @returns A {@link Parser} that tries to parse using both parsers
|
|
663
|
+
* and returns the result of the parser that consumed more tokens.
|
|
664
|
+
*/
|
|
665
|
+
declare function longestMatch<TA, TB, TStateA, TStateB>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>): Parser<TA | TB, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>]>;
|
|
666
|
+
/**
|
|
667
|
+
* Creates a parser that combines three mutually exclusive parsers into one,
|
|
668
|
+
* selecting the parser that consumes the most tokens.
|
|
669
|
+
* The resulting parser will try all parsers and return the result
|
|
670
|
+
* of the parser that consumed the most input tokens.
|
|
671
|
+
* @template TA The type of the value returned by the first parser.
|
|
672
|
+
* @template TB The type of the value returned by the second parser.
|
|
673
|
+
* @template TC The type of the value returned by the third parser.
|
|
674
|
+
* @template TStateA The type of the state used by the first parser.
|
|
675
|
+
* @template TStateB The type of the state used by the second parser.
|
|
676
|
+
* @template TStateC The type of the state used by the third parser.
|
|
677
|
+
* @param a The first {@link Parser} to try.
|
|
678
|
+
* @param b The second {@link Parser} to try.
|
|
679
|
+
* @param c The third {@link Parser} to try.
|
|
680
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
681
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
682
|
+
*/
|
|
683
|
+
declare function longestMatch<TA, TB, TC, TStateA, TStateB, TStateC>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>): Parser<TA | TB | TC, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>]>;
|
|
684
|
+
/**
|
|
685
|
+
* Creates a parser that combines four mutually exclusive parsers into one,
|
|
686
|
+
* selecting the parser that consumes the most tokens.
|
|
687
|
+
* The resulting parser will try all parsers and return the result
|
|
688
|
+
* of the parser that consumed the most input tokens.
|
|
689
|
+
* @template TA The type of the value returned by the first parser.
|
|
690
|
+
* @template TB The type of the value returned by the second parser.
|
|
691
|
+
* @template TC The type of the value returned by the third parser.
|
|
692
|
+
* @template TD The type of the value returned by the fourth parser.
|
|
693
|
+
* @template TStateA The type of the state used by the first parser.
|
|
694
|
+
* @template TStateB The type of the state used by the second parser.
|
|
695
|
+
* @template TStateC The type of the state used by the third parser.
|
|
696
|
+
* @template TStateD The type of the state used by the fourth parser.
|
|
697
|
+
* @param a The first {@link Parser} to try.
|
|
698
|
+
* @param b The second {@link Parser} to try.
|
|
699
|
+
* @param c The third {@link Parser} to try.
|
|
700
|
+
* @param d The fourth {@link Parser} to try.
|
|
701
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
702
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
703
|
+
*/
|
|
704
|
+
declare function longestMatch<TA, TB, TC, TD, TStateA, TStateB, TStateC, TStateD>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>): Parser<TA | TB | TC | TD, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>]>;
|
|
705
|
+
/**
|
|
706
|
+
* Creates a parser that combines five mutually exclusive parsers into one,
|
|
707
|
+
* selecting the parser that consumes the most tokens.
|
|
708
|
+
* The resulting parser will try all parsers and return the result
|
|
709
|
+
* of the parser that consumed the most input tokens.
|
|
710
|
+
* @template TA The type of the value returned by the first parser.
|
|
711
|
+
* @template TB The type of the value returned by the second parser.
|
|
712
|
+
* @template TC The type of the value returned by the third parser.
|
|
713
|
+
* @template TD The type of the value returned by the fourth parser.
|
|
714
|
+
* @template TE The type of the value returned by the fifth parser.
|
|
715
|
+
* @template TStateA The type of the state used by the first parser.
|
|
716
|
+
* @template TStateB The type of the state used by the second parser.
|
|
717
|
+
* @template TStateC The type of the state used by the third parser.
|
|
718
|
+
* @template TStateD The type of the state used by the fourth parser.
|
|
719
|
+
* @template TStateE The type of the state used by the fifth parser.
|
|
720
|
+
* @param a The first {@link Parser} to try.
|
|
721
|
+
* @param b The second {@link Parser} to try.
|
|
722
|
+
* @param c The third {@link Parser} to try.
|
|
723
|
+
* @param d The fourth {@link Parser} to try.
|
|
724
|
+
* @param e The fifth {@link Parser} to try.
|
|
725
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
726
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
727
|
+
*/
|
|
728
|
+
declare function longestMatch<TA, TB, TC, TD, TE, TStateA, TStateB, TStateC, TStateD, TStateE>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>): Parser<TA | TB | TC | TD | TE, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>]>;
|
|
651
729
|
/**
|
|
652
730
|
* Helper type to check if all members of a union are object-like.
|
|
653
731
|
* This allows merge() to work with parsers like withDefault() that produce union types.
|
|
@@ -936,4 +1014,4 @@ declare function parse<T>(parser: Parser<T, unknown>, args: readonly string[]):
|
|
|
936
1014
|
*/
|
|
937
1015
|
declare function getDocPage(parser: Parser<unknown, unknown>, args?: readonly string[]): DocPage | undefined;
|
|
938
1016
|
//#endregion
|
|
939
|
-
export { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|
|
1017
|
+
export { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|
package/dist/parser.d.ts
CHANGED
|
@@ -648,6 +648,84 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TStateA, TStateB, TState
|
|
|
648
648
|
* in order, returning the result of the first successful parser.
|
|
649
649
|
*/
|
|
650
650
|
declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TStateC, TStateD, TStateE, TStateF, TStateG, TStateH, TStateI, TStateJ>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>, f: Parser<TF, TStateF>, g: Parser<TG, TStateG>, h: Parser<TH, TStateH>, i: Parser<TI, TStateI>, j: Parser<TJ, TStateJ>): Parser<TA | TB | TC | TD | TE | TF | TG | TH | TI | TJ, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>] | [5, ParserResult<TStateF>] | [6, ParserResult<TStateG>] | [7, ParserResult<TStateH>] | [8, ParserResult<TStateI>] | [9, ParserResult<TStateJ>]>;
|
|
651
|
+
/**
|
|
652
|
+
* Creates a parser that combines two mutually exclusive parsers into one,
|
|
653
|
+
* selecting the parser that consumes the most tokens.
|
|
654
|
+
* The resulting parser will try both parsers and return the result
|
|
655
|
+
* of the parser that consumed more input tokens.
|
|
656
|
+
* @template TA The type of the value returned by the first parser.
|
|
657
|
+
* @template TB The type of the value returned by the second parser.
|
|
658
|
+
* @template TStateA The type of the state used by the first parser.
|
|
659
|
+
* @template TStateB The type of the state used by the second parser.
|
|
660
|
+
* @param a The first {@link Parser} to try.
|
|
661
|
+
* @param b The second {@link Parser} to try.
|
|
662
|
+
* @returns A {@link Parser} that tries to parse using both parsers
|
|
663
|
+
* and returns the result of the parser that consumed more tokens.
|
|
664
|
+
*/
|
|
665
|
+
declare function longestMatch<TA, TB, TStateA, TStateB>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>): Parser<TA | TB, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>]>;
|
|
666
|
+
/**
|
|
667
|
+
* Creates a parser that combines three mutually exclusive parsers into one,
|
|
668
|
+
* selecting the parser that consumes the most tokens.
|
|
669
|
+
* The resulting parser will try all parsers and return the result
|
|
670
|
+
* of the parser that consumed the most input tokens.
|
|
671
|
+
* @template TA The type of the value returned by the first parser.
|
|
672
|
+
* @template TB The type of the value returned by the second parser.
|
|
673
|
+
* @template TC The type of the value returned by the third parser.
|
|
674
|
+
* @template TStateA The type of the state used by the first parser.
|
|
675
|
+
* @template TStateB The type of the state used by the second parser.
|
|
676
|
+
* @template TStateC The type of the state used by the third parser.
|
|
677
|
+
* @param a The first {@link Parser} to try.
|
|
678
|
+
* @param b The second {@link Parser} to try.
|
|
679
|
+
* @param c The third {@link Parser} to try.
|
|
680
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
681
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
682
|
+
*/
|
|
683
|
+
declare function longestMatch<TA, TB, TC, TStateA, TStateB, TStateC>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>): Parser<TA | TB | TC, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>]>;
|
|
684
|
+
/**
|
|
685
|
+
* Creates a parser that combines four mutually exclusive parsers into one,
|
|
686
|
+
* selecting the parser that consumes the most tokens.
|
|
687
|
+
* The resulting parser will try all parsers and return the result
|
|
688
|
+
* of the parser that consumed the most input tokens.
|
|
689
|
+
* @template TA The type of the value returned by the first parser.
|
|
690
|
+
* @template TB The type of the value returned by the second parser.
|
|
691
|
+
* @template TC The type of the value returned by the third parser.
|
|
692
|
+
* @template TD The type of the value returned by the fourth parser.
|
|
693
|
+
* @template TStateA The type of the state used by the first parser.
|
|
694
|
+
* @template TStateB The type of the state used by the second parser.
|
|
695
|
+
* @template TStateC The type of the state used by the third parser.
|
|
696
|
+
* @template TStateD The type of the state used by the fourth parser.
|
|
697
|
+
* @param a The first {@link Parser} to try.
|
|
698
|
+
* @param b The second {@link Parser} to try.
|
|
699
|
+
* @param c The third {@link Parser} to try.
|
|
700
|
+
* @param d The fourth {@link Parser} to try.
|
|
701
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
702
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
703
|
+
*/
|
|
704
|
+
declare function longestMatch<TA, TB, TC, TD, TStateA, TStateB, TStateC, TStateD>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>): Parser<TA | TB | TC | TD, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>]>;
|
|
705
|
+
/**
|
|
706
|
+
* Creates a parser that combines five mutually exclusive parsers into one,
|
|
707
|
+
* selecting the parser that consumes the most tokens.
|
|
708
|
+
* The resulting parser will try all parsers and return the result
|
|
709
|
+
* of the parser that consumed the most input tokens.
|
|
710
|
+
* @template TA The type of the value returned by the first parser.
|
|
711
|
+
* @template TB The type of the value returned by the second parser.
|
|
712
|
+
* @template TC The type of the value returned by the third parser.
|
|
713
|
+
* @template TD The type of the value returned by the fourth parser.
|
|
714
|
+
* @template TE The type of the value returned by the fifth parser.
|
|
715
|
+
* @template TStateA The type of the state used by the first parser.
|
|
716
|
+
* @template TStateB The type of the state used by the second parser.
|
|
717
|
+
* @template TStateC The type of the state used by the third parser.
|
|
718
|
+
* @template TStateD The type of the state used by the fourth parser.
|
|
719
|
+
* @template TStateE The type of the state used by the fifth parser.
|
|
720
|
+
* @param a The first {@link Parser} to try.
|
|
721
|
+
* @param b The second {@link Parser} to try.
|
|
722
|
+
* @param c The third {@link Parser} to try.
|
|
723
|
+
* @param d The fourth {@link Parser} to try.
|
|
724
|
+
* @param e The fifth {@link Parser} to try.
|
|
725
|
+
* @returns A {@link Parser} that tries to parse using all parsers
|
|
726
|
+
* and returns the result of the parser that consumed the most tokens.
|
|
727
|
+
*/
|
|
728
|
+
declare function longestMatch<TA, TB, TC, TD, TE, TStateA, TStateB, TStateC, TStateD, TStateE>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>): Parser<TA | TB | TC | TD | TE, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>]>;
|
|
651
729
|
/**
|
|
652
730
|
* Helper type to check if all members of a union are object-like.
|
|
653
731
|
* This allows merge() to work with parsers like withDefault() that produce union types.
|
|
@@ -936,4 +1014,4 @@ declare function parse<T>(parser: Parser<T, unknown>, args: readonly string[]):
|
|
|
936
1014
|
*/
|
|
937
1015
|
declare function getDocPage(parser: Parser<unknown, unknown>, args?: readonly string[]): DocPage | undefined;
|
|
938
1016
|
//#endregion
|
|
939
|
-
export { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|
|
1017
|
+
export { ArgumentOptions, CommandOptions, DocState, FlagOptions, InferValue, MultipleOptions, OptionOptions, Parser, ParserContext, ParserResult, Result, argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|
package/dist/parser.js
CHANGED
|
@@ -1031,6 +1031,86 @@ function or(...parsers) {
|
|
|
1031
1031
|
}
|
|
1032
1032
|
};
|
|
1033
1033
|
}
|
|
1034
|
+
function longestMatch(...parsers) {
|
|
1035
|
+
return {
|
|
1036
|
+
$valueType: [],
|
|
1037
|
+
$stateType: [],
|
|
1038
|
+
priority: Math.max(...parsers.map((p) => p.priority)),
|
|
1039
|
+
usage: [{
|
|
1040
|
+
type: "exclusive",
|
|
1041
|
+
terms: parsers.map((p) => p.usage)
|
|
1042
|
+
}],
|
|
1043
|
+
initialState: void 0,
|
|
1044
|
+
complete(state) {
|
|
1045
|
+
if (state == null) return {
|
|
1046
|
+
success: false,
|
|
1047
|
+
error: message`No parser matched.`
|
|
1048
|
+
};
|
|
1049
|
+
const [i, result] = state;
|
|
1050
|
+
if (result.success) return parsers[i].complete(result.next.state);
|
|
1051
|
+
return {
|
|
1052
|
+
success: false,
|
|
1053
|
+
error: result.error
|
|
1054
|
+
};
|
|
1055
|
+
},
|
|
1056
|
+
parse(context) {
|
|
1057
|
+
let bestMatch = null;
|
|
1058
|
+
let error = {
|
|
1059
|
+
consumed: 0,
|
|
1060
|
+
error: context.buffer.length < 1 ? message`No parser matched.` : message`Unexpected option or subcommand: ${optionName(context.buffer[0])}.`
|
|
1061
|
+
};
|
|
1062
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1063
|
+
const parser = parsers[i];
|
|
1064
|
+
const result = parser.parse({
|
|
1065
|
+
...context,
|
|
1066
|
+
state: context.state == null || context.state[0] !== i || !context.state[1].success ? parser.initialState : context.state[1].next.state
|
|
1067
|
+
});
|
|
1068
|
+
if (result.success) {
|
|
1069
|
+
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1070
|
+
if (bestMatch === null || consumed > bestMatch.consumed) bestMatch = {
|
|
1071
|
+
index: i,
|
|
1072
|
+
result,
|
|
1073
|
+
consumed
|
|
1074
|
+
};
|
|
1075
|
+
} else if (error.consumed < result.consumed) error = result;
|
|
1076
|
+
}
|
|
1077
|
+
if (bestMatch && bestMatch.result.success) return {
|
|
1078
|
+
success: true,
|
|
1079
|
+
next: {
|
|
1080
|
+
...context,
|
|
1081
|
+
buffer: bestMatch.result.next.buffer,
|
|
1082
|
+
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1083
|
+
state: [bestMatch.index, bestMatch.result]
|
|
1084
|
+
},
|
|
1085
|
+
consumed: bestMatch.result.consumed
|
|
1086
|
+
};
|
|
1087
|
+
return {
|
|
1088
|
+
...error,
|
|
1089
|
+
success: false
|
|
1090
|
+
};
|
|
1091
|
+
},
|
|
1092
|
+
getDocFragments(state, _defaultValue) {
|
|
1093
|
+
let description;
|
|
1094
|
+
let fragments;
|
|
1095
|
+
if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
1096
|
+
else {
|
|
1097
|
+
const [i, result] = state.state;
|
|
1098
|
+
if (result.success) {
|
|
1099
|
+
const docResult = parsers[i].getDocFragments({
|
|
1100
|
+
kind: "available",
|
|
1101
|
+
state: result.next.state
|
|
1102
|
+
});
|
|
1103
|
+
description = docResult.description;
|
|
1104
|
+
fragments = docResult.fragments;
|
|
1105
|
+
} else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
|
|
1106
|
+
}
|
|
1107
|
+
return {
|
|
1108
|
+
description,
|
|
1109
|
+
fragments
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1034
1114
|
function merge(...parsers) {
|
|
1035
1115
|
parsers = parsers.toSorted((a, b) => b.priority - a.priority);
|
|
1036
1116
|
const initialState = {};
|
|
@@ -1477,4 +1557,4 @@ function getDocPage(parser, args = []) {
|
|
|
1477
1557
|
}
|
|
1478
1558
|
|
|
1479
1559
|
//#endregion
|
|
1480
|
-
export { argument, command, concat, constant, flag, getDocPage, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|
|
1560
|
+
export { argument, command, concat, constant, flag, getDocPage, longestMatch, map, merge, multiple, object, option, optional, or, parse, tuple, withDefault };
|