args-tokens 0.22.6 → 0.23.1
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 +44 -6
- package/lib/index.d.ts +6 -3
- package/lib/index.js +6 -3
- package/lib/parser.d.ts +97 -1
- package/lib/parser.js +197 -1
- package/lib/resolver.d.ts +559 -2
- package/lib/resolver.js +286 -3
- package/lib/{utils-1LQrGCWG.js → utils-CxvkckUD.js} +1 -1
- package/lib/utils.js +1 -1
- package/package.json +26 -25
- package/lib/parser-DEYiqyo1.d.ts +0 -98
- package/lib/parser-M-ayhS1h.js +0 -199
- package/lib/resolver-7JOAwfSr.d.ts +0 -474
- package/lib/resolver-DBvNkaE7.js +0 -262
package/lib/resolver.js
CHANGED
|
@@ -1,5 +1,288 @@
|
|
|
1
|
-
import "./parser
|
|
2
|
-
import "./utils-
|
|
3
|
-
import { ArgResolveError, resolveArgs } from "./resolver-DBvNkaE7.js";
|
|
1
|
+
import { hasLongOptionPrefix, isShortOption } from "./parser.js";
|
|
2
|
+
import { t as kebabnize } from "./utils-CxvkckUD.js";
|
|
4
3
|
|
|
4
|
+
//#region src/resolver.ts
|
|
5
|
+
/**
|
|
6
|
+
* Entry point of argument options resolver.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
12
|
+
* @license MIT
|
|
13
|
+
*/
|
|
14
|
+
const SKIP_POSITIONAL_DEFAULT = -1;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve command line arguments.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
|
|
19
|
+
*
|
|
20
|
+
* @param args - An arguments that contains {@link ArgSchema | arguments schema}.
|
|
21
|
+
* @param tokens - An array of {@link ArgToken | tokens}.
|
|
22
|
+
* @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
|
|
23
|
+
* @returns An object that contains the values of the arguments, positional arguments, rest arguments, {@link AggregateError | validation errors}, and explicit provision status.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // passed tokens: --port 3000
|
|
28
|
+
*
|
|
29
|
+
* const { values, explicit } = resolveArgs({
|
|
30
|
+
* port: {
|
|
31
|
+
* type: 'number',
|
|
32
|
+
* default: 8080
|
|
33
|
+
* },
|
|
34
|
+
* host: {
|
|
35
|
+
* type: 'string',
|
|
36
|
+
* default: 'localhost'
|
|
37
|
+
* }
|
|
38
|
+
* }, parsedTokens)
|
|
39
|
+
*
|
|
40
|
+
* values.port // 3000
|
|
41
|
+
* values.host // 'localhost'
|
|
42
|
+
*
|
|
43
|
+
* explicit.port // true (explicitly provided)
|
|
44
|
+
* explicit.host // false (not provided, fallback to default)
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKIP_POSITIONAL_DEFAULT, toKebab = false } = {}) {
|
|
48
|
+
const skipPositionalIndex = typeof skipPositional === "number" ? Math.max(skipPositional, SKIP_POSITIONAL_DEFAULT) : SKIP_POSITIONAL_DEFAULT;
|
|
49
|
+
const rest = [];
|
|
50
|
+
const optionTokens = [];
|
|
51
|
+
const positionalTokens = [];
|
|
52
|
+
let currentLongOption;
|
|
53
|
+
let currentShortOption;
|
|
54
|
+
const expandableShortOptions = [];
|
|
55
|
+
function toShortValue() {
|
|
56
|
+
if (expandableShortOptions.length === 0) return;
|
|
57
|
+
else {
|
|
58
|
+
const value = expandableShortOptions.map((token) => token.name).join("");
|
|
59
|
+
expandableShortOptions.length = 0;
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function applyLongOptionValue(value = void 0) {
|
|
64
|
+
if (currentLongOption) {
|
|
65
|
+
currentLongOption.value = value;
|
|
66
|
+
optionTokens.push({ ...currentLongOption });
|
|
67
|
+
currentLongOption = void 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function applyShortOptionValue(value = void 0) {
|
|
71
|
+
if (currentShortOption) {
|
|
72
|
+
currentShortOption.value = value || toShortValue();
|
|
73
|
+
optionTokens.push({ ...currentShortOption });
|
|
74
|
+
currentShortOption = void 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* analyze phase to resolve value
|
|
79
|
+
* separate tokens into positionals, long and short options, after that resolve values
|
|
80
|
+
*/
|
|
81
|
+
const schemas = Object.values(args);
|
|
82
|
+
let terminated = false;
|
|
83
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
84
|
+
const token = tokens[i];
|
|
85
|
+
if (token.kind === "positional") {
|
|
86
|
+
if (terminated && token.value) {
|
|
87
|
+
rest.push(token.value);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (currentShortOption) {
|
|
91
|
+
if (schemas.find((schema) => schema.short === currentShortOption.name && schema.type === "boolean")) positionalTokens.push({ ...token });
|
|
92
|
+
} else if (currentLongOption) {
|
|
93
|
+
if (args[currentLongOption.name]?.type === "boolean") positionalTokens.push({ ...token });
|
|
94
|
+
} else positionalTokens.push({ ...token });
|
|
95
|
+
applyLongOptionValue(token.value);
|
|
96
|
+
applyShortOptionValue(token.value);
|
|
97
|
+
} else if (token.kind === "option") if (token.rawName) {
|
|
98
|
+
if (hasLongOptionPrefix(token.rawName)) {
|
|
99
|
+
applyLongOptionValue();
|
|
100
|
+
if (token.inlineValue) optionTokens.push({ ...token });
|
|
101
|
+
else currentLongOption = { ...token };
|
|
102
|
+
applyShortOptionValue();
|
|
103
|
+
} else if (isShortOption(token.rawName)) if (currentShortOption) {
|
|
104
|
+
if (currentShortOption.index === token.index) if (shortGrouping) {
|
|
105
|
+
currentShortOption.value = token.value;
|
|
106
|
+
optionTokens.push({ ...currentShortOption });
|
|
107
|
+
currentShortOption = { ...token };
|
|
108
|
+
} else expandableShortOptions.push({ ...token });
|
|
109
|
+
else {
|
|
110
|
+
currentShortOption.value = toShortValue();
|
|
111
|
+
optionTokens.push({ ...currentShortOption });
|
|
112
|
+
currentShortOption = { ...token };
|
|
113
|
+
}
|
|
114
|
+
applyLongOptionValue();
|
|
115
|
+
} else {
|
|
116
|
+
currentShortOption = { ...token };
|
|
117
|
+
applyLongOptionValue();
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
if (currentShortOption && currentShortOption.index == token.index && token.inlineValue) {
|
|
121
|
+
currentShortOption.value = token.value;
|
|
122
|
+
optionTokens.push({ ...currentShortOption });
|
|
123
|
+
currentShortOption = void 0;
|
|
124
|
+
}
|
|
125
|
+
applyLongOptionValue();
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
if (token.kind === "option-terminator") terminated = true;
|
|
129
|
+
applyLongOptionValue();
|
|
130
|
+
applyShortOptionValue();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* check if the last long or short option is not resolved
|
|
135
|
+
*/
|
|
136
|
+
applyLongOptionValue();
|
|
137
|
+
applyShortOptionValue();
|
|
138
|
+
/**
|
|
139
|
+
* resolve values
|
|
140
|
+
*/
|
|
141
|
+
const values = Object.create(null);
|
|
142
|
+
const errors = [];
|
|
143
|
+
const explicit = Object.create(null);
|
|
144
|
+
const actualInputNames = /* @__PURE__ */ new Map();
|
|
145
|
+
function checkTokenName(option, schema, token) {
|
|
146
|
+
return token.name === (schema.type === "boolean" ? schema.negatable && token.name?.startsWith("no-") ? `no-${option}` : option : option);
|
|
147
|
+
}
|
|
148
|
+
const positionalItemCount = tokens.filter((token) => token.kind === "positional").length;
|
|
149
|
+
function getPositionalSkipIndex() {
|
|
150
|
+
return Math.min(skipPositionalIndex, positionalItemCount);
|
|
151
|
+
}
|
|
152
|
+
let positionalsCount = 0;
|
|
153
|
+
for (const [rawArg, schema] of Object.entries(args)) {
|
|
154
|
+
const arg = toKebab || schema.toKebab ? kebabnize(rawArg) : rawArg;
|
|
155
|
+
explicit[rawArg] = false;
|
|
156
|
+
if (schema.type === "positional") {
|
|
157
|
+
if (skipPositionalIndex > SKIP_POSITIONAL_DEFAULT) while (positionalsCount <= getPositionalSkipIndex()) positionalsCount++;
|
|
158
|
+
if (schema.multiple) {
|
|
159
|
+
const remainingPositionals = positionalTokens.slice(positionalsCount);
|
|
160
|
+
if (remainingPositionals.length > 0) {
|
|
161
|
+
values[rawArg] = remainingPositionals.map((p) => p.value);
|
|
162
|
+
positionalsCount += remainingPositionals.length;
|
|
163
|
+
explicit[rawArg] = true;
|
|
164
|
+
} else if (schema.required) errors.push(createRequireError(arg, schema));
|
|
165
|
+
} else {
|
|
166
|
+
const positional = positionalTokens[positionalsCount];
|
|
167
|
+
if (positional != null) {
|
|
168
|
+
values[rawArg] = positional.value;
|
|
169
|
+
explicit[rawArg] = true;
|
|
170
|
+
} else errors.push(createRequireError(arg, schema));
|
|
171
|
+
positionalsCount++;
|
|
172
|
+
}
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (schema.required) {
|
|
176
|
+
if (!optionTokens.find((token) => {
|
|
177
|
+
return schema.short && token.name === schema.short || token.rawName && hasLongOptionPrefix(token.rawName) && token.name === arg;
|
|
178
|
+
})) {
|
|
179
|
+
errors.push(createRequireError(arg, schema));
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
for (let i = 0; i < optionTokens.length; i++) {
|
|
184
|
+
const token = optionTokens[i];
|
|
185
|
+
if (checkTokenName(arg, schema, token) && token.rawName != void 0 && hasLongOptionPrefix(token.rawName) || schema.short === token.name && token.rawName != void 0 && isShortOption(token.rawName)) {
|
|
186
|
+
const invalid = validateRequire(token, arg, schema);
|
|
187
|
+
if (invalid) {
|
|
188
|
+
errors.push(invalid);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
explicit[rawArg] = true;
|
|
192
|
+
const actualInputName = isShortOption(token.rawName) ? `-${token.name}` : `--${arg}`;
|
|
193
|
+
actualInputNames.set(rawArg, actualInputName);
|
|
194
|
+
if (schema.type === "boolean") token.value = void 0;
|
|
195
|
+
const [parsedValue, error] = parse(token, arg, schema);
|
|
196
|
+
if (error) errors.push(error);
|
|
197
|
+
else if (schema.multiple) {
|
|
198
|
+
values[rawArg] ||= [];
|
|
199
|
+
values[rawArg].push(parsedValue);
|
|
200
|
+
} else values[rawArg] = parsedValue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (values[rawArg] == null && schema.default != null) values[rawArg] = schema.default;
|
|
204
|
+
}
|
|
205
|
+
const conflictErrors = checkConflicts(args, explicit, toKebab, actualInputNames);
|
|
206
|
+
errors.push(...conflictErrors);
|
|
207
|
+
return {
|
|
208
|
+
values,
|
|
209
|
+
positionals: positionalTokens.map((token) => token.value),
|
|
210
|
+
rest,
|
|
211
|
+
error: errors.length > 0 ? new AggregateError(errors) : void 0,
|
|
212
|
+
explicit
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function parse(token, option, schema) {
|
|
216
|
+
switch (schema.type) {
|
|
217
|
+
case "string": return typeof token.value === "string" ? [token.value || schema.default, void 0] : [void 0, createTypeError(option, schema)];
|
|
218
|
+
case "boolean": return token.value ? [token.value || schema.default, void 0] : [!(schema.negatable && token.name.startsWith("no-")), void 0];
|
|
219
|
+
case "number":
|
|
220
|
+
if (!isNumeric(token.value)) return [void 0, createTypeError(option, schema)];
|
|
221
|
+
return token.value ? [+token.value, void 0] : [+(schema.default || ""), void 0];
|
|
222
|
+
case "enum":
|
|
223
|
+
if (schema.choices && !schema.choices.includes(token.value)) return [void 0, new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be chosen from '${schema.type}' [${schema.choices.map((c) => JSON.stringify(c)).join(", ")}] values`, option, "type", schema)];
|
|
224
|
+
return [token.value || schema.default, void 0];
|
|
225
|
+
case "custom":
|
|
226
|
+
if (typeof schema.parse !== "function") throw new TypeError(`argument '${option}' should have a 'parse' function`);
|
|
227
|
+
try {
|
|
228
|
+
return [schema.parse(token.value || String(schema.default || "")), void 0];
|
|
229
|
+
} catch (error) {
|
|
230
|
+
return [void 0, error];
|
|
231
|
+
}
|
|
232
|
+
default: throw new Error(`Unsupported argument type '${schema.type}' for option '${option}'`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function createRequireError(option, schema) {
|
|
236
|
+
return new ArgResolveError(schema.type === "positional" ? `Positional argument '${option}' is required` : `Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}is required`, option, "required", schema);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* An error that occurs when resolving arguments.
|
|
240
|
+
* This error is thrown when the argument is not valid.
|
|
241
|
+
*/
|
|
242
|
+
var ArgResolveError = class extends Error {
|
|
243
|
+
name;
|
|
244
|
+
schema;
|
|
245
|
+
type;
|
|
246
|
+
/**
|
|
247
|
+
* Create an `ArgResolveError` instance.
|
|
248
|
+
*
|
|
249
|
+
* @param message - the error message
|
|
250
|
+
* @param name - the name of the argument
|
|
251
|
+
* @param type - the type of the error, either 'type' or 'required'
|
|
252
|
+
* @param schema - the argument schema that caused the error
|
|
253
|
+
*/
|
|
254
|
+
constructor(message, name, type, schema) {
|
|
255
|
+
super(message);
|
|
256
|
+
this.name = name;
|
|
257
|
+
this.type = type;
|
|
258
|
+
this.schema = schema;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
function validateRequire(token, option, schema) {
|
|
262
|
+
if (schema.required && schema.type !== "boolean" && !token.value) return createRequireError(option, schema);
|
|
263
|
+
}
|
|
264
|
+
function isNumeric(str) {
|
|
265
|
+
return str.trim() !== "" && !isNaN(str);
|
|
266
|
+
}
|
|
267
|
+
function createTypeError(option, schema) {
|
|
268
|
+
return new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be '${schema.type}'`, option, "type", schema);
|
|
269
|
+
}
|
|
270
|
+
function checkConflicts(args, explicit, toKebab, actualInputNames) {
|
|
271
|
+
for (const rawArg in args) {
|
|
272
|
+
const schema = args[rawArg];
|
|
273
|
+
if (!explicit[rawArg]) continue;
|
|
274
|
+
if (!schema.conflicts) continue;
|
|
275
|
+
const conflicts = Array.isArray(schema.conflicts) ? schema.conflicts : [schema.conflicts];
|
|
276
|
+
for (let i = 0; i < conflicts.length; i++) {
|
|
277
|
+
const conflictingArg = conflicts[i];
|
|
278
|
+
if (!explicit[conflictingArg]) continue;
|
|
279
|
+
const arg = toKebab || schema.toKebab ? kebabnize(rawArg) : rawArg;
|
|
280
|
+
const conflictingArgKebab = toKebab || args[conflictingArg]?.toKebab ? kebabnize(conflictingArg) : conflictingArg;
|
|
281
|
+
return [new ArgResolveError(`Optional argument '${actualInputNames.get(rawArg) || `--${arg}`}' conflicts with '${actualInputNames.get(conflictingArg) || `--${conflictingArgKebab}`}'`, rawArg, "conflict", schema)];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
//#endregion
|
|
5
288
|
export { ArgResolveError, resolveArgs };
|
package/lib/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "args-tokens",
|
|
3
3
|
"description": "parseArgs tokens compatibility and more high-performance parser",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kazuya kawaguchi",
|
|
7
7
|
"email": "kawakazu80@gmail.com"
|
|
@@ -71,35 +71,36 @@
|
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@eslint/markdown": "^
|
|
75
|
-
"@kazupon/eslint-config": "^0.
|
|
76
|
-
"@kazupon/prettier-config": "^0.
|
|
77
|
-
"@types/node": "^
|
|
78
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
79
|
-
"@vitest/eslint-plugin": "^1.
|
|
80
|
-
"bumpp": "^10.
|
|
81
|
-
"deno": "^2.
|
|
82
|
-
"eslint": "^9.
|
|
74
|
+
"@eslint/markdown": "^7.5.1",
|
|
75
|
+
"@kazupon/eslint-config": "^0.44.0",
|
|
76
|
+
"@kazupon/prettier-config": "^0.2.0",
|
|
77
|
+
"@types/node": "^24.10.9",
|
|
78
|
+
"@typescript/native-preview": "7.0.0-dev.20260131.1",
|
|
79
|
+
"@vitest/eslint-plugin": "^1.6.6",
|
|
80
|
+
"bumpp": "^10.4.0",
|
|
81
|
+
"deno": "^2.6.7",
|
|
82
|
+
"eslint": "^9.39.2",
|
|
83
83
|
"eslint-config-prettier": "^10.1.8",
|
|
84
|
-
"eslint-plugin-jsdoc": "^52.0.
|
|
85
|
-
"eslint-plugin-jsonc": "^2.
|
|
84
|
+
"eslint-plugin-jsdoc": "^52.0.4",
|
|
85
|
+
"eslint-plugin-jsonc": "^2.21.0",
|
|
86
|
+
"eslint-plugin-markdown-preferences": "^0.10.0",
|
|
86
87
|
"eslint-plugin-promise": "^7.2.1",
|
|
87
|
-
"eslint-plugin-regexp": "^2.
|
|
88
|
+
"eslint-plugin-regexp": "^2.10.0",
|
|
88
89
|
"eslint-plugin-unicorn": "^60.0.0",
|
|
89
|
-
"eslint-plugin-yml": "^1.
|
|
90
|
+
"eslint-plugin-yml": "^1.19.1",
|
|
90
91
|
"gh-changelogen": "^0.2.8",
|
|
91
|
-
"jsr": "^0.
|
|
92
|
-
"jsr-exports-lint": "^0.4.
|
|
93
|
-
"knip": "^5.
|
|
94
|
-
"lint-staged": "^16.
|
|
92
|
+
"jsr": "^0.14.2",
|
|
93
|
+
"jsr-exports-lint": "^0.4.2",
|
|
94
|
+
"knip": "^5.82.1",
|
|
95
|
+
"lint-staged": "^16.2.7",
|
|
95
96
|
"mitata": "^1.0.34",
|
|
96
|
-
"pkg-pr-new": "^0.0.
|
|
97
|
-
"prettier": "^3.
|
|
98
|
-
"tsdown": "^0.
|
|
99
|
-
"typescript": "^5.9.
|
|
100
|
-
"typescript-eslint": "^8.
|
|
101
|
-
"vitest": "^
|
|
102
|
-
"zod": "^4.
|
|
97
|
+
"pkg-pr-new": "^0.0.62",
|
|
98
|
+
"prettier": "^3.8.1",
|
|
99
|
+
"tsdown": "^0.20.1",
|
|
100
|
+
"typescript": "^5.9.3",
|
|
101
|
+
"typescript-eslint": "^8.54.0",
|
|
102
|
+
"vitest": "^4.0.18",
|
|
103
|
+
"zod": "^4.3.6"
|
|
103
104
|
},
|
|
104
105
|
"prettier": "@kazupon/prettier-config",
|
|
105
106
|
"lint-staged": {
|
package/lib/parser-DEYiqyo1.d.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
//#region src/parser.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Entry point of argument parser.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* forked from `nodejs/node` (`pkgjs/parseargs`)
|
|
9
|
-
* repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
|
|
10
|
-
* code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
|
|
11
|
-
*
|
|
12
|
-
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
13
|
-
* @license MIT
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Argument token Kind.
|
|
17
|
-
*
|
|
18
|
-
* - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
|
|
19
|
-
* - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
|
|
20
|
-
* - `positional`: positional token
|
|
21
|
-
*/
|
|
22
|
-
type ArgTokenKind = 'option' | 'option-terminator' | 'positional';
|
|
23
|
-
/**
|
|
24
|
-
* Argument token.
|
|
25
|
-
*/
|
|
26
|
-
interface ArgToken {
|
|
27
|
-
/**
|
|
28
|
-
* Argument token kind.
|
|
29
|
-
*/
|
|
30
|
-
kind: ArgTokenKind;
|
|
31
|
-
/**
|
|
32
|
-
* Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1.
|
|
33
|
-
*/
|
|
34
|
-
index: number;
|
|
35
|
-
/**
|
|
36
|
-
* Option name, e.g. `--foo` => `foo`, `-x` => `x`.
|
|
37
|
-
*/
|
|
38
|
-
name?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`.
|
|
41
|
-
*/
|
|
42
|
-
rawName?: string;
|
|
43
|
-
/**
|
|
44
|
-
* Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
|
|
45
|
-
* If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
|
|
46
|
-
*/
|
|
47
|
-
value?: string;
|
|
48
|
-
/**
|
|
49
|
-
* Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
|
|
50
|
-
*/
|
|
51
|
-
inlineValue?: boolean;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Parser Options.
|
|
55
|
-
*/
|
|
56
|
-
interface ParserOptions {
|
|
57
|
-
/**
|
|
58
|
-
* [Node.js parseArgs](https://nodejs.org/api/util.html#parseargs-tokens) tokens compatible mode.
|
|
59
|
-
*
|
|
60
|
-
* @default false
|
|
61
|
-
*/
|
|
62
|
-
allowCompatible?: boolean;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Parse command line arguments.
|
|
66
|
-
*
|
|
67
|
-
* @param args - command line arguments
|
|
68
|
-
* @param options - parse options, about details see {@link ParserOptions}
|
|
69
|
-
* @returns Argument tokens.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```js
|
|
73
|
-
* import { parseArgs } from 'args-tokens' // for Node.js and Bun
|
|
74
|
-
* // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
|
|
75
|
-
*
|
|
76
|
-
* const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
|
|
77
|
-
* // do something with using tokens
|
|
78
|
-
* // ...
|
|
79
|
-
* console.log('tokens:', tokens)
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
declare function parseArgs(args: string[], options?: ParserOptions): ArgToken[];
|
|
83
|
-
/**
|
|
84
|
-
* Check if `arg` is a short option (e.g. `-f`).
|
|
85
|
-
*
|
|
86
|
-
* @param arg - An argument to check
|
|
87
|
-
* @returns Whether `arg` is a short option.
|
|
88
|
-
*/
|
|
89
|
-
declare function isShortOption(arg: string): boolean;
|
|
90
|
-
/**
|
|
91
|
-
* Check if `arg` is a long option prefix (e.g. `--`).
|
|
92
|
-
*
|
|
93
|
-
* @param arg - An argument to check
|
|
94
|
-
* @returns Whether `arg` is a long option prefix.
|
|
95
|
-
*/
|
|
96
|
-
declare function hasLongOptionPrefix(arg: string): boolean;
|
|
97
|
-
//#endregion
|
|
98
|
-
export { ArgToken, ParserOptions, hasLongOptionPrefix as hasLongOptionPrefix$1, isShortOption as isShortOption$1, parseArgs as parseArgs$1 };
|
package/lib/parser-M-ayhS1h.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
//#region src/parser.ts
|
|
2
|
-
const HYPHEN_CHAR = "-";
|
|
3
|
-
const HYPHEN_CODE = HYPHEN_CHAR.codePointAt(0);
|
|
4
|
-
const EQUAL_CHAR = "=";
|
|
5
|
-
const EQUAL_CODE = EQUAL_CHAR.codePointAt(0);
|
|
6
|
-
const TERMINATOR = "--";
|
|
7
|
-
const SHORT_OPTION_PREFIX = HYPHEN_CHAR;
|
|
8
|
-
const LONG_OPTION_PREFIX = "--";
|
|
9
|
-
/**
|
|
10
|
-
* Parse command line arguments.
|
|
11
|
-
*
|
|
12
|
-
* @param args - command line arguments
|
|
13
|
-
* @param options - parse options, about details see {@link ParserOptions}
|
|
14
|
-
* @returns Argument tokens.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```js
|
|
18
|
-
* import { parseArgs } from 'args-tokens' // for Node.js and Bun
|
|
19
|
-
* // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
|
|
20
|
-
*
|
|
21
|
-
* const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
|
|
22
|
-
* // do something with using tokens
|
|
23
|
-
* // ...
|
|
24
|
-
* console.log('tokens:', tokens)
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
function parseArgs(args, options = {}) {
|
|
28
|
-
const { allowCompatible = false } = options;
|
|
29
|
-
const tokens = [];
|
|
30
|
-
const remainings = [...args];
|
|
31
|
-
let index = -1;
|
|
32
|
-
let groupCount = 0;
|
|
33
|
-
let hasShortValueSeparator = false;
|
|
34
|
-
while (remainings.length > 0) {
|
|
35
|
-
const arg = remainings.shift();
|
|
36
|
-
if (arg == void 0) break;
|
|
37
|
-
const nextArg = remainings[0];
|
|
38
|
-
if (groupCount > 0) groupCount--;
|
|
39
|
-
else index++;
|
|
40
|
-
if (arg === TERMINATOR) {
|
|
41
|
-
tokens.push({
|
|
42
|
-
kind: "option-terminator",
|
|
43
|
-
index
|
|
44
|
-
});
|
|
45
|
-
const mapped = remainings.map((arg$1) => {
|
|
46
|
-
return {
|
|
47
|
-
kind: "positional",
|
|
48
|
-
index: ++index,
|
|
49
|
-
value: arg$1
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
tokens.push(...mapped);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
if (isShortOption(arg)) {
|
|
56
|
-
const shortOption = arg.charAt(1);
|
|
57
|
-
let value;
|
|
58
|
-
let inlineValue;
|
|
59
|
-
if (groupCount) {
|
|
60
|
-
tokens.push({
|
|
61
|
-
kind: "option",
|
|
62
|
-
name: shortOption,
|
|
63
|
-
rawName: arg,
|
|
64
|
-
index,
|
|
65
|
-
value,
|
|
66
|
-
inlineValue
|
|
67
|
-
});
|
|
68
|
-
if (groupCount === 1 && hasOptionValue(nextArg)) {
|
|
69
|
-
value = remainings.shift();
|
|
70
|
-
if (hasShortValueSeparator) {
|
|
71
|
-
inlineValue = true;
|
|
72
|
-
hasShortValueSeparator = false;
|
|
73
|
-
}
|
|
74
|
-
tokens.push({
|
|
75
|
-
kind: "option",
|
|
76
|
-
index,
|
|
77
|
-
value,
|
|
78
|
-
inlineValue
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
} else tokens.push({
|
|
82
|
-
kind: "option",
|
|
83
|
-
name: shortOption,
|
|
84
|
-
rawName: arg,
|
|
85
|
-
index,
|
|
86
|
-
value,
|
|
87
|
-
inlineValue
|
|
88
|
-
});
|
|
89
|
-
if (value != null) ++index;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (isShortOptionGroup(arg)) {
|
|
93
|
-
const expanded = [];
|
|
94
|
-
let shortValue = "";
|
|
95
|
-
for (let i = 1; i < arg.length; i++) {
|
|
96
|
-
const shortableOption = arg.charAt(i);
|
|
97
|
-
if (hasShortValueSeparator) shortValue += shortableOption;
|
|
98
|
-
else if (!allowCompatible && shortableOption.codePointAt(0) === EQUAL_CODE) hasShortValueSeparator = true;
|
|
99
|
-
else expanded.push(`${SHORT_OPTION_PREFIX}${shortableOption}`);
|
|
100
|
-
}
|
|
101
|
-
if (shortValue) expanded.push(shortValue);
|
|
102
|
-
remainings.unshift(...expanded);
|
|
103
|
-
groupCount = expanded.length;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
if (isLongOption(arg)) {
|
|
107
|
-
const longOption = arg.slice(2);
|
|
108
|
-
tokens.push({
|
|
109
|
-
kind: "option",
|
|
110
|
-
name: longOption,
|
|
111
|
-
rawName: arg,
|
|
112
|
-
index,
|
|
113
|
-
value: void 0,
|
|
114
|
-
inlineValue: void 0
|
|
115
|
-
});
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
if (isLongOptionAndValue(arg)) {
|
|
119
|
-
const equalIndex = arg.indexOf(EQUAL_CHAR);
|
|
120
|
-
const longOption = arg.slice(2, equalIndex);
|
|
121
|
-
const value = arg.slice(equalIndex + 1);
|
|
122
|
-
tokens.push({
|
|
123
|
-
kind: "option",
|
|
124
|
-
name: longOption,
|
|
125
|
-
rawName: `${LONG_OPTION_PREFIX}${longOption}`,
|
|
126
|
-
index,
|
|
127
|
-
value,
|
|
128
|
-
inlineValue: true
|
|
129
|
-
});
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
tokens.push({
|
|
133
|
-
kind: "positional",
|
|
134
|
-
index,
|
|
135
|
-
value: arg
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return tokens;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Check if `arg` is a short option (e.g. `-f`).
|
|
142
|
-
*
|
|
143
|
-
* @param arg - An argument to check
|
|
144
|
-
* @returns Whether `arg` is a short option.
|
|
145
|
-
*/
|
|
146
|
-
function isShortOption(arg) {
|
|
147
|
-
return arg.length === 2 && arg.codePointAt(0) === HYPHEN_CODE && arg.codePointAt(1) !== HYPHEN_CODE;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Check if `arg` is a short option group (e.g. `-abc`).
|
|
151
|
-
*
|
|
152
|
-
* @param arg - An argument to check
|
|
153
|
-
* @returns Whether `arg` is a short option group.
|
|
154
|
-
*/
|
|
155
|
-
function isShortOptionGroup(arg) {
|
|
156
|
-
if (arg.length <= 2) return false;
|
|
157
|
-
if (arg.codePointAt(0) !== HYPHEN_CODE) return false;
|
|
158
|
-
if (arg.codePointAt(1) === HYPHEN_CODE) return false;
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Check if `arg` is a long option (e.g. `--foo`).
|
|
163
|
-
*
|
|
164
|
-
* @param arg - An argument to check
|
|
165
|
-
* @returns Whether `arg` is a long option.
|
|
166
|
-
*/
|
|
167
|
-
function isLongOption(arg) {
|
|
168
|
-
return hasLongOptionPrefix(arg) && !arg.includes(EQUAL_CHAR, 3);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Check if `arg` is a long option with value (e.g. `--foo=bar`).
|
|
172
|
-
*
|
|
173
|
-
* @param arg - An argument to check
|
|
174
|
-
* @returns Whether `arg` is a long option.
|
|
175
|
-
*/
|
|
176
|
-
function isLongOptionAndValue(arg) {
|
|
177
|
-
return hasLongOptionPrefix(arg) && arg.includes(EQUAL_CHAR, 3);
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Check if `arg` is a long option prefix (e.g. `--`).
|
|
181
|
-
*
|
|
182
|
-
* @param arg - An argument to check
|
|
183
|
-
* @returns Whether `arg` is a long option prefix.
|
|
184
|
-
*/
|
|
185
|
-
function hasLongOptionPrefix(arg) {
|
|
186
|
-
return arg.length > 2 && ~arg.indexOf(LONG_OPTION_PREFIX);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Check if a `value` is an option value.
|
|
190
|
-
*
|
|
191
|
-
* @param value - A value to check
|
|
192
|
-
* @returns Whether a `value` is an option value.
|
|
193
|
-
*/
|
|
194
|
-
function hasOptionValue(value) {
|
|
195
|
-
return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
//#endregion
|
|
199
|
-
export { hasLongOptionPrefix, isShortOption, parseArgs };
|