argvex
Version:
Lightweight and unopinionated CLI argument parser — just a parsing tool, not a framework
115 lines (114 loc) • 4.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArgvexError = void 0;
class ArgvexError extends Error {
constructor(argument) {
super(`Argument "${argument}" is unrecognized or misplaced.`);
}
}
exports.ArgvexError = ArgvexError;
const longflag = (name, value, definition) => {
const values = [];
let arity = definition?.arity ?? Infinity;
if (value != null) {
values.push(value);
arity = 1;
}
return { definition: { name, ...definition, arity }, values };
};
const shortflag = (alias, aliases, definition) => {
const values = [];
let arity = definition?.arity ?? Infinity;
if (aliases.indexOf(alias) != aliases.length - 1) {
arity = 0;
}
return { definition: { name: alias, ...definition, arity }, values };
};
const inlineflag = (index, aliases, definition) => {
if (definition == null) {
return null;
}
if (definition.arity == 0) {
return null;
}
if (aliases[index + 1] == null) {
return null;
}
return { definition, values: [aliases.substring(index + 1)] };
};
const argvex = (options) => {
const { command, argv = command?.split(" ").filter(arg => !!arg) ?? process.argv.slice(2), schema = [], strict = false, additive = false } = options;
const definitions = new Map();
for (const { name, alias, arity = Infinity } of schema) {
const definition = { name, alias, arity };
definitions.set(name, definition);
if (alias != null) {
definitions.set(alias, definition);
}
}
let current = null;
const _ = [];
const flags = {};
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];
if (arg == "--") {
_.push(...argv.slice(i + 1));
break;
}
if (arg.startsWith('--')) {
const [name, value] = arg.substring(2).split("=");
if (name.length == 0) {
throw new ArgvexError(arg);
}
if (strict && !definitions.has(name)) {
throw new ArgvexError(arg);
}
const { definition, values } = longflag(name, value, definitions.get(name));
definitions.set(name, definition);
if (additive && flags[name] != null) {
values.unshift(...flags[name]);
}
current = { definition, values };
flags[name] = values;
continue;
}
if (arg.startsWith('-')) {
const aliases = arg.substring(1);
if (aliases.length == 0) {
throw new ArgvexError(arg);
}
for (let j = 0; j < aliases.length; j++) {
const alias = aliases[j];
if (strict && !definitions.has(alias)) {
throw new ArgvexError(`-${alias}`);
}
const inliner = inlineflag(j, aliases, definitions.get(alias));
if (inliner != null) {
const { definition, values } = inliner;
definitions.set(alias, definition);
if (additive && flags[definition.name] != null) {
values.unshift(...flags[definition.name]);
}
current = { definition, values };
flags[definition.name] = values;
break;
}
const { definition, values } = shortflag(alias, aliases, definitions.get(alias));
definitions.set(alias, definition);
if (additive && flags[definition.name] != null) {
values.unshift(...flags[definition.name]);
}
current = { definition, values };
flags[definition.name] = values;
}
continue;
}
if (current == null || current.values.length >= current.definition.arity) {
_.push(arg);
continue;
}
current?.values.push(arg);
}
return { _, ...flags };
};
exports.default = argvex;