@eeue56/baner
Version:
Flag parsing library in Typescript
947 lines (819 loc) • 25.2 kB
text/typescript
import { Ok } from "@eeue56/ts-core/build/main/lib/result";
import { Err } from "@eeue56/ts-core/build/main/lib/result";
import * as assert from "assert";
import {
shortFlag,
parse,
longFlag,
parser,
list,
string,
number,
boolean,
bothFlag,
empty,
variableList,
allErrors,
oneOf,
allMissing,
} from "./baner";
export function testShortFlag() {
const emptyAParser = parser([ shortFlag("a", "some help text", empty()) ]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(emptyAParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(emptyAParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "-a" ],
});
const listWithMultipleFlags: string[] = [ "-a", "-b", "-c" ];
assert.deepStrictEqual(parse(emptyAParser, listWithMultipleFlags), {
flags: {
a: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "-a", "-b", "-c" ],
});
const listWithMultiplebothFlags: string[] = [
"--yes",
"-c",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(parse(emptyAParser, listWithMultiplebothFlags), {
flags: {
a: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes", "-c", "-a", "--no", "-b" ],
});
}
export function testShortFlagWithSingleArgument() {
const singleArgParser = parser([
shortFlag("a", "some help text", list([ string() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "-a" ],
});
const listWithSingleFlagWithArgument: string[] = [ "-a", "hello" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ "hello" ]),
},
},
args: [ "-a", "hello" ],
}
);
const listWithMultipleFlags: string[] = [ "-a", "hello", "-b", "-c" ];
assert.deepStrictEqual(parse(singleArgParser, listWithMultipleFlags), {
flags: {
a: {
isPresent: true,
arguments: Ok([ "hello" ]),
},
},
args: [ "-a", "hello", "-b", "-c" ],
});
const listWithMultipleFlagsWithoutArgument: string[] = [ "-a", "-b", "-c" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithMultipleFlagsWithoutArgument),
{
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "-a", "-b", "-c" ],
}
);
const listWithMultiplebothFlags: string[] = [
"--yes",
"-c",
"-a",
"hello",
"--no",
"-b",
];
assert.deepStrictEqual(parse(singleArgParser, listWithMultiplebothFlags), {
flags: {
a: {
isPresent: true,
arguments: Ok([ "hello" ]),
},
},
args: [ "--yes", "-c", "-a", "hello", "--no", "-b" ],
});
}
export function testLongFlag() {
const emptyYesParser = parser([
longFlag("yes", "some help text", empty()),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(emptyYesParser, emptyList), {
flags: {
yes: {
isPresent: false,
arguments: Err("Long flag --yes not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "--yes" ];
assert.deepStrictEqual(parse(emptyYesParser, listWithSingleFlag), {
flags: {
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes" ],
});
const listWithMultipleFlags: string[] = [ "--yes", "-b", "-c" ];
assert.deepStrictEqual(parse(emptyYesParser, listWithMultipleFlags), {
flags: {
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes", "-b", "-c" ],
});
const listWithMultiplebothFlags: string[] = [
"-c",
"--yes",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(parse(emptyYesParser, listWithMultiplebothFlags), {
flags: {
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "-c", "--yes", "-a", "--no", "-b" ],
});
}
export function testLongFlagWithSingleArgument() {
const singleArgParser = parser([
longFlag("yes", "some help text", list([ string() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
yes: {
isPresent: false,
arguments: Err("Long flag --yes not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "--yes" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "--yes" ],
});
const listWithMultipleFlags: string[] = [ "--yes", "-b", "-c" ];
assert.deepStrictEqual(parse(singleArgParser, listWithMultipleFlags), {
flags: {
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "--yes", "-b", "-c" ],
});
const listWithMultiplebothFlags: string[] = [
"-c",
"--yes",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(parse(singleArgParser, listWithMultiplebothFlags), {
flags: {
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "-c", "--yes", "-a", "--no", "-b" ],
});
const listWithMultiplebothFlagsAndAnArg: string[] = [
"-c",
"--yes",
"hello",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(
parse(singleArgParser, listWithMultiplebothFlagsAndAnArg),
{
flags: {
yes: {
isPresent: true,
arguments: Ok([ "hello" ]),
},
},
args: [ "-c", "--yes", "hello", "-a", "--no", "-b" ],
}
);
}
export function testBothFlag() {
const emptyYesParser = parser([
bothFlag("y", "yes", "some help text", empty()),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(emptyYesParser, emptyList), {
flags: {
"y/yes": {
isPresent: false,
arguments: Err("Mixed flag -y/--yes not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "--yes" ];
assert.deepStrictEqual(parse(emptyYesParser, listWithSingleFlag), {
flags: {
"y/yes": {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes" ],
});
const listWithMultipleFlags: string[] = [ "--yes", "-b", "-c" ];
assert.deepStrictEqual(parse(emptyYesParser, listWithMultipleFlags), {
flags: {
"y/yes": {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes", "-b", "-c" ],
});
const listWithMultiplebothFlags: string[] = [
"-c",
"--yes",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(parse(emptyYesParser, listWithMultiplebothFlags), {
flags: {
"y/yes": {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "-c", "--yes", "-a", "--no", "-b" ],
});
const listWithMultiplebothFlagsAndShortFlag: string[] = [
"-c",
"-y",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(
parse(emptyYesParser, listWithMultiplebothFlagsAndShortFlag),
{
flags: {
"y/yes": {
isPresent: true,
arguments: Ok(null),
},
},
args: listWithMultiplebothFlagsAndShortFlag,
}
);
}
export function testMultipleEmptyArguments() {
const emptyAOrYesParser = parser([
shortFlag("a", "some help text", empty()),
longFlag("yes", "some help text", empty()),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(emptyAOrYesParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: false,
arguments: Err("Long flag --yes not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "--yes" ];
assert.deepStrictEqual(parse(emptyAOrYesParser, listWithSingleFlag), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: [ "--yes" ],
});
const listWithMultipleFlags: string[] = [ "--yes", "-b", "-c" ];
assert.deepStrictEqual(parse(emptyAOrYesParser, listWithMultipleFlags), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: listWithMultipleFlags,
});
const listWithMultiplebothFlags: string[] = [
"-c",
"--yes",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(
parse(emptyAOrYesParser, listWithMultiplebothFlags),
{
flags: {
a: {
isPresent: true,
arguments: Ok(null),
},
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: listWithMultiplebothFlags,
}
);
const listWithMultiplebothFlagsInDifferentOrder: string[] = [
"-c",
"-a",
"--no",
"--yes",
"-b",
];
assert.deepStrictEqual(
parse(emptyAOrYesParser, listWithMultiplebothFlagsInDifferentOrder),
{
flags: {
a: {
isPresent: true,
arguments: Ok(null),
},
yes: {
isPresent: true,
arguments: Ok(null),
},
},
args: listWithMultiplebothFlagsInDifferentOrder,
}
);
}
export function testMultipleSingleArguments() {
const emptyAOrYesParser = parser([
shortFlag("a", "some help text", list([ string() ])),
longFlag("yes", "some help text", list([ string() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(emptyAOrYesParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: false,
arguments: Err("Long flag --yes not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "--yes" ];
assert.deepStrictEqual(parse(emptyAOrYesParser, listWithSingleFlag), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: [ "--yes" ],
});
const listWithMultipleFlags: string[] = [ "--yes", "-b", "-c" ];
assert.deepStrictEqual(parse(emptyAOrYesParser, listWithMultipleFlags), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: listWithMultipleFlags,
});
const listWithMultiplebothFlags: string[] = [
"-c",
"--yes",
"-a",
"--no",
"-b",
];
assert.deepStrictEqual(
parse(emptyAOrYesParser, listWithMultiplebothFlags),
{
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a string. at index 0"
),
},
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: listWithMultiplebothFlags,
}
);
const listWithMultiplebothFlagsInDifferentOrder: string[] = [
"-c",
"-a",
"--no",
"--yes",
"-b",
];
assert.deepStrictEqual(
parse(emptyAOrYesParser, listWithMultiplebothFlagsInDifferentOrder),
{
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a string. at index 0"
),
},
yes: {
isPresent: true,
arguments: Err(
"Error parsing --yes due to: Not enough arguments. Expected a string. at index 0"
),
},
},
args: listWithMultiplebothFlagsInDifferentOrder,
}
);
}
export function testShortFlagWithSingleNumberArgument() {
const singleArgParser = parser([
shortFlag("a", "some help text", list([ number() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a number. at index 0"
),
},
},
args: [ "-a" ],
});
const listWithSingleFlagWithArgument: string[] = [ "-a", "hello" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithArgument),
{
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not a number argument"
),
},
},
args: listWithSingleFlagWithArgument,
}
);
const listWithSingleFlagWithNumberArgument: string[] = [ "-a", "5.5" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithNumberArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ 5.5 ]),
},
},
args: listWithSingleFlagWithNumberArgument,
}
);
const listWithSingleFlagWithIntArgument: string[] = [ "-a", "5" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithIntArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ 5 ]),
},
},
args: listWithSingleFlagWithIntArgument,
}
);
const listWithSingleFlagWithZeroArgument: string[] = [ "-a", "0" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithZeroArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ 0 ]),
},
},
args: listWithSingleFlagWithZeroArgument,
}
);
const listWithSingleFlagWithNegativeArgument: string[] = [ "-a", "-5.5" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithNegativeArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ -5.5 ]),
},
},
args: listWithSingleFlagWithNegativeArgument,
}
);
}
export function testShortFlagWithSingleBooleanArgument() {
const singleArgParser = parser([
shortFlag("a", "some help text", list([ boolean() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a boolean. at index 0"
),
},
},
args: [ "-a" ],
});
const listWithSingleFlagWithArgument: string[] = [ "-a", "hello" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithArgument),
{
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not a boolean argument"
),
},
},
args: listWithSingleFlagWithArgument,
}
);
const listWithSingleFlagWithTrueArgument: string[] = [ "-a", "true" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithTrueArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ true ]),
},
},
args: listWithSingleFlagWithTrueArgument,
}
);
const listWithSingleFlagWithFalseArgument: string[] = [ "-a", "false" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithFalseArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ false ]),
},
},
args: listWithSingleFlagWithFalseArgument,
}
);
}
export function testShortFlagWithMultipleArguments() {
const singleArgParser = parser([
shortFlag("a", "some help text", list([ boolean(), string() ])),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Err(
"Error parsing -a due to: Not enough arguments. Expected a boolean. at index 0"
),
},
},
args: [ "-a" ],
});
const listWithSingleFlagWithArgument: string[] = [ "-a", "true", "hello" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ true, "hello" ]),
},
},
args: listWithSingleFlagWithArgument,
}
);
}
export function testShortFlagWithVariableArguments() {
const singleArgParser = parser([
shortFlag("a", "some help text", variableList(string())),
]);
const emptyList: string[] = [ ];
assert.deepStrictEqual(parse(singleArgParser, emptyList), {
flags: {
a: {
isPresent: false,
arguments: Err("Short flag -a not found"),
},
},
args: [ ],
});
const listWithSingleFlag: string[] = [ "-a" ];
assert.deepStrictEqual(parse(singleArgParser, listWithSingleFlag), {
flags: {
a: {
isPresent: true,
arguments: Ok([ ]),
},
},
args: [ "-a" ],
});
const listWithSingleFlagWithArgument: string[] = [ "-a", "true", "hello" ];
assert.deepStrictEqual(
parse(singleArgParser, listWithSingleFlagWithArgument),
{
flags: {
a: {
isPresent: true,
arguments: Ok([ "true", "hello" ]),
},
},
args: listWithSingleFlagWithArgument,
}
);
}
export function testAllErrors() {
const someParser = parser([
shortFlag("a", "some help text", list([ number() ])),
shortFlag("b", "B", number()),
shortFlag("c", "C", oneOf([ "ban", "can" ])),
]);
let parsed = parse(someParser, [ "-a", "-b", "-c" ]);
assert.deepStrictEqual(allErrors(parsed), [
"Error parsing -a due to: Not enough arguments. Expected a number. at index 0",
"Error parsing -b due to: Not enough arguments. Expected a number.",
"Error parsing -c due to: Not enough arguments. Expected one of: ban | can.",
]);
parsed = parse(someParser, [ "-a", "1", "-b", "-c" ]);
assert.deepStrictEqual(allErrors(parsed), [
"Error parsing -b due to: Not enough arguments. Expected a number.",
"Error parsing -c due to: Not enough arguments. Expected one of: ban | can.",
]);
}
export function testAllMissing() {
const someParser = parser([
shortFlag("a", "some help text", list([ number() ])),
shortFlag("b", "B", number()),
shortFlag("c", "C", oneOf([ "ban", "can" ])),
]);
let parsed = parse(someParser, [ ]);
assert.deepStrictEqual(allMissing(parsed, [ ]), [ "a", "b", "c" ]);
parsed = parse(someParser, [ "-a", "1", "-c" ]);
assert.deepStrictEqual(allMissing(parsed, [ ]), [ "b" ]);
parsed = parse(someParser, [ "-a", "1" ]);
assert.deepStrictEqual(allMissing(parsed, [ "c" ]), [ "b" ]);
}