@eeue56/baner
Version:
Flag parsing library in Typescript
466 lines (462 loc) • 11.7 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/baner.ts
var baner_exports = {};
__export(baner_exports, {
Err: () => Err,
Ok: () => Ok,
allErrors: () => allErrors,
allMissing: () => allMissing,
allValues: () => allValues,
boolean: () => boolean,
bothFlag: () => bothFlag,
empty: () => empty,
help: () => help,
list: () => list,
longFlag: () => longFlag,
number: () => number,
oneOf: () => oneOf,
parse: () => parse,
parser: () => parser,
shortFlag: () => shortFlag,
string: () => string,
variableList: () => variableList
});
module.exports = __toCommonJS(baner_exports);
// src/types.ts
function Ok(value) {
return { kind: "Ok", value };
}
function Err(error) {
return { kind: "Err", error };
}
function string() {
return {
kind: "StringArgument"
};
}
function number() {
return {
kind: "NumberArgument"
};
}
function boolean() {
return {
kind: "BooleanArgument"
};
}
function empty() {
return {
kind: "BooleanArgument"
};
}
function list(flagArgumentParsers) {
return {
kind: "ListArgument",
items: flagArgumentParsers
};
}
function VariableListArgument(item) {
return {
kind: "VariableListArgument",
item
};
}
function variableList(flagArgumentParser) {
return VariableListArgument(flagArgumentParser);
}
function oneOf(items) {
return {
kind: "OneOfArgument",
items
};
}
function shortFlag(name, help2, parser2) {
return { kind: "Short", name, help: help2, parser: parser2 };
}
function longFlag(name, help2, parser2) {
return { kind: "Long", name, parser: parser2, help: help2 };
}
function bothFlag(shortName, longName, help2, parser2) {
return { kind: "Both", shortName, longName, help: help2, parser: parser2 };
}
// src/baner.ts
function parser(...flags) {
const collectedFlags = {};
for (const flag of flags) {
switch (flag.kind) {
case "Short": {
collectedFlags[flag.name] = flag;
break;
}
case "Long": {
collectedFlags[flag.name] = flag;
break;
}
case "Both": {
collectedFlags[flag.longName] = flag;
break;
}
}
}
return { flags: collectedFlags };
}
function isFlag(string2) {
const isNumber = isNaN(parseFloat(string2));
if (isNumber) {
return string2.startsWith("-");
}
return false;
}
function runString(parseable) {
if (parseable.length === 0 || isFlag(parseable[0]))
return Err("Not enough arguments. Expected a string.");
return Ok(parseable[0]);
}
function runNumber(parseable) {
if (parseable.length === 0 || isFlag(parseable[0]))
return Err("Not enough arguments. Expected a number.");
const parsed = parseFloat(parseable[0]);
if (isNaN(parsed)) return Err("Not a number argument");
return Ok(parsed);
}
function runBoolean(parseable) {
if (parseable.length === 0 || isFlag(parseable[0])) {
return Ok(true);
}
const parsed = parseable[0] === "true" || parseable[0] === "false";
if (!parsed) return Err("Not a boolean argument");
return Ok(parseable[0] === "true");
}
function runList(flagArguments, parseable) {
const results = [];
for (var i = 0; i < flagArguments.length; i++) {
const argument = flagArguments[i];
const res = runArgument(argument, parseable.slice(i));
if (res.kind === "Err") {
if (i >= parseable.length || isFlag(parseable[i])) {
return Err(`${res.error} at index ${i}`);
}
return res;
} else {
results.push(res.value);
}
}
return Ok(results);
}
function runOneOf(items, parseable) {
if (parseable.length === 0 || isFlag(parseable[0]))
return Err(
`Not enough arguments. Expected one of: ${items.join(" | ")}.`
);
for (var i = 0; i < items.length; i++) {
const item = items[i];
if (item === parseable[0]) return Ok(item);
}
return Err(`Didn't match any of: ${items.join(" | ")}`);
}
function runVariableList(flagArgument, parseable) {
const results = [];
for (var i = 0; i < parseable.length; i++) {
if (isFlag(parseable[i])) break;
const res = runArgument(flagArgument, parseable.slice(i));
if (res.kind === "Err") return res;
results.push(res.value);
}
return Ok(results);
}
function runArgument(argument, parseable) {
switch (argument.kind) {
case "StringArgument": {
return runString(parseable);
}
case "NumberArgument": {
return runNumber(parseable);
}
case "BooleanArgument": {
return runBoolean(parseable);
}
case "ListArgument": {
return runList(argument.items, parseable);
}
case "VariableListArgument": {
return runVariableList(
argument.item,
parseable
);
}
case "OneOfArgument": {
return runOneOf(argument.items, parseable);
}
}
}
function runShortFlag(flag, parseable) {
const flagName = flag.name;
const innerParser = flag.parser;
if (parseable.length === 0) {
return {
isPresent: false,
arguments: Err(`Short flag -${flagName} not found`),
flag
};
}
for (var i = 0; i < parseable.length; i++) {
const value = parseable[i];
if (value === `-${flagName}`) {
let res = runArgument(innerParser, parseable.slice(i + 1));
if (res.kind === "Err") {
res = Err(`Error parsing -${flagName} due to: ${res.error}`);
}
return {
isPresent: true,
arguments: res,
flag
};
}
}
return {
isPresent: false,
arguments: Err(`Short flag -${flagName} not found`),
flag
};
}
function runLongFlag(flag, parseable) {
const flagName = flag.name;
const innerParser = flag.parser;
if (parseable.length === 0) {
return {
isPresent: false,
arguments: Err(`Long flag --${flagName} not found`),
flag
};
}
for (var i = 0; i < parseable.length; i++) {
const value = parseable[i];
if (value === `--${flagName}`) {
let res = runArgument(innerParser, parseable.slice(i + 1));
if (res.kind === "Err") {
res = Err(`Error parsing --${flagName} due to: ${res.error}`);
}
return {
isPresent: true,
arguments: res,
flag
};
}
}
return {
isPresent: false,
arguments: Err(`Long flag --${flagName} not found`),
flag
};
}
function runBothFlag(flag, parseable) {
const shortFlagName = flag.shortName;
const longFlagName = flag.longName;
const innerParser = flag.parser;
const combinedFlagName = `-${shortFlagName}/--${longFlagName}`;
if (parseable.length === 0) {
return {
isPresent: false,
arguments: Err(`Mixed flag ${combinedFlagName} not found`),
flag
};
}
for (var i = 0; i < parseable.length; i++) {
const value = parseable[i];
if (value === `-${shortFlagName}` || value === `--${longFlagName}`) {
let res = runArgument(innerParser, parseable.slice(i + 1));
if (res.kind === "Err") {
res = Err(
`Error parsing ${combinedFlagName} due to: ${res.error}`
);
}
return {
isPresent: true,
arguments: res,
flag
};
}
}
return {
isPresent: false,
arguments: Err(`Mixed flag ${combinedFlagName} not found`),
flag
};
}
function runParser(programParser, parseable) {
const emptyRecord = {
args: parseable,
flags: {}
};
for (const flag of Object.values(programParser.flags)) {
let res;
switch (flag.kind) {
case "Short": {
res = runShortFlag(flag, parseable);
break;
}
case "Long": {
res = runLongFlag(flag, parseable);
break;
}
case "Both": {
res = runBothFlag(flag, parseable);
}
}
let name;
switch (flag.kind) {
case "Short": {
name = flag.name;
break;
}
case "Long": {
name = flag.name;
break;
}
case "Both": {
name = flag.longName;
break;
}
}
emptyRecord.flags[name] = {
isPresent: res.isPresent,
arguments: res.arguments,
flag
};
}
return emptyRecord;
}
function helpFlagArgumentParser(parser2) {
switch (parser2.kind) {
case "BooleanArgument":
return "boolean";
case "NumberArgument":
return "number";
case "StringArgument":
return "string";
case "ListArgument":
return "[" + parser2.items.map(helpFlagArgumentParser).join(" ") + "]";
case "VariableListArgument":
return "[" + helpFlagArgumentParser(parser2.item) + "...]";
case "OneOfArgument":
return parser2.items.join(" | ");
}
}
function help(flagParser) {
const output = [];
for (const flag of Object.values(flagParser.flags)) {
switch (flag.kind) {
case "Short": {
output.push(
` -${flag.name} ${helpFlagArgumentParser(
flag.parser
)}: ${flag.help}`
);
break;
}
case "Long": {
output.push(
` --${flag.name} ${helpFlagArgumentParser(
flag.parser
)}: ${flag.help}`
);
break;
}
case "Both": {
output.push(
` -${flag.shortName}, --${flag.longName} ${helpFlagArgumentParser(flag.parser)}: ${flag.help}`
);
break;
}
}
}
return output.join("\n");
}
function allErrors(program) {
const errors = [];
for (const key of Object.keys(program.flags)) {
const value = program.flags[key];
if (!value.isPresent) continue;
const argument = value.arguments;
if (argument.kind === "Err") {
errors.push(argument.error);
}
}
return errors;
}
function allMissing(program, ignore) {
const errors = [];
for (const key of Object.keys(program.flags)) {
if (ignore.indexOf(key) > -1) continue;
if (!program.flags[key].isPresent) errors.push(key);
}
return errors;
}
function allValues(program) {
const values = {};
for (const key of Object.keys(program.flags)) {
if (!program.flags[key].isPresent) continue;
const argument = program.flags[key].arguments;
if (argument.kind === "Ok") {
values[key] = argument.value;
} else {
values[key] = void 0;
}
}
return values;
}
function parse(flagParser, args) {
const parseable = [];
for (const arg of args) {
if (arg.indexOf("=") > -1) {
parseable.push(arg.split("=")[0]);
arg.split("=")[1].split(",").forEach((splitArg) => {
parseable.push(splitArg);
});
} else {
arg.split(",").forEach((splitArg) => {
parseable.push(splitArg);
});
}
}
const res = runParser(flagParser, parseable);
return res;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Err,
Ok,
allErrors,
allMissing,
allValues,
boolean,
bothFlag,
empty,
help,
list,
longFlag,
number,
oneOf,
parse,
parser,
shortFlag,
string,
variableList
});