Skip to content

Commit

Permalink
Refactor CLI parsing, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sondr3 committed Jan 5, 2022
1 parent 5862fbe commit bbc74f7
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 23 deletions.
61 changes: 61 additions & 0 deletions lib/cli.test.ts
@@ -0,0 +1,61 @@
import { strict as assert } from "node:assert";

import { defaultOptions, parseOptions } from "./cli.js";
import { test } from "./index.js";

test("CLI without options", () => {
const options = parseOptions([], defaultOptions);

assert(!options.quiet);
assert(!options.help);
assert(!options.version);

assert.equal(options.dir, ".");
assert.equal(options.filter, undefined);
});

test("CLI with options, no dir", () => {
const options = parseOptions(["-q"], { ...defaultOptions });

assert(options.quiet);
assert(!options.help);
assert(!options.version);

assert.equal(options.dir, ".");
assert.equal(options.filter, undefined);
});

test("CLI with dir", () => {
const options = parseOptions(["dir"], { ...defaultOptions });
assert.equal(options.dir, "dir");
});

test("CLI with filter", () => {
const options = parseOptions(["-f", "filter"], { ...defaultOptions });
assert.equal(typeof options.filter, "function");
});

test("CLI with options and dir", () => {
const options = parseOptions(["-q", "dist/", "-f", "filter"], { ...defaultOptions });

assert(options.quiet);
assert(!options.help);
assert(!options.version);

assert.equal(options.dir, "dist/");
assert.equal(typeof options.filter, "function");
});

test("CLI with version stops parsing", () => {
const options = parseOptions(["--version", "-q"], { ...defaultOptions });

assert(!options.quiet);
assert(options.version);
});

test("CLI with help short circuits", () => {
const options = parseOptions(["--help", "-v"], { ...defaultOptions });

assert(options.help);
assert(!options.version);
});
65 changes: 42 additions & 23 deletions lib/cli.ts
Expand Up @@ -8,7 +8,7 @@ interface CliOptions {
filter?: (name: string) => boolean;
}

const defaultOptions: CliOptions = {
export const defaultOptions: CliOptions = {
dir: ".",
help: false,
version: false,
Expand Down Expand Up @@ -44,32 +44,51 @@ const printVersionHelp = (version: boolean, help: boolean) => {
}
};

export const parseCli = (argv: Array<string>): CliOptions => {
const args = argv.slice(2);
const options: CliOptions = defaultOptions;

if (args.length > 0) {
options.dir = args[0];
}

options.help = args.includes("-h") || args.includes("--help");
options.version = args.includes("-v") || args.includes("--version");
options.quiet = args.includes("-q") || args.includes("--quiet");
export const parseOptions = (args: Array<string>, options: CliOptions): CliOptions => {
if (args.length === 0) return options;

if (args.includes("-f") || args.includes("--filter")) {
const index = args.findIndex((arg) => arg === "-f" || arg === "--filter");
if (index + 1 >= args.length) {
throw new Error("Missing filter string");
}
if (args[0].startsWith("-")) {
switch (args[0]) {
case "-q":
case "--quiet":
options.quiet = true;
return parseOptions(args.slice(1), options);
case "-v":
case "--version":
options.version = true;
return options;
case "-h":
case "--help":
options.help = true;
return options;
case "-f":
case "--filter": {
const index = args.findIndex((arg) => arg === "-f" || arg === "--filter");
if (index + 1 >= args.length) {
throw new Error("Missing filter string");
}

const filter = args[index + 1];
if (filter.startsWith("/") && filter.endsWith("/")) {
const regex = new RegExp(filter.slice(1, filter.length - 1));
options.filter = (name: string) => regex.test(name);
} else {
options.filter = (name: string) => filter.includes(name);
const filter = args[index + 1];
if (filter.startsWith("/") && filter.endsWith("/")) {
const regex = new RegExp(filter.slice(1, filter.length - 1));
options.filter = (name: string) => regex.test(name);
} else {
options.filter = (name: string) => filter.includes(name);
}
return parseOptions(args.slice(2), options);
}
default:
return options;
}
} else {
options.dir = args[0];
return parseOptions(args.slice(1), options);
}
};

export const parseCli = (argv: Array<string>): CliOptions => {
const args = argv.slice(2);
const options = parseOptions(args, defaultOptions);

if (options.version || options.help) {
printVersionHelp(options.version, options.help);
Expand Down

0 comments on commit bbc74f7

Please sign in to comment.