aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2020-03-24 21:53:09 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2020-03-25 06:41:00 +0900
commit2e1356b4c67206e1eda82d842fe4280452a048ff (patch)
treea1a5da44e5bbd0bf6d28e559dbc7fc090a64b571
parent348051972ea816e506e483cb363bfea1e1474d23 (diff)
Add command-line parser on console scripts
-rw-r--r--src/console/commandline/CommandLineParser.ts38
-rw-r--r--src/console/commandline/CommandParser.ts52
-rw-r--r--src/shared/Command.ts15
-rw-r--r--test/console/commandline/CommandLineParser.test.ts29
-rw-r--r--test/console/commandline/CommandParser.test.ts15
5 files changed, 149 insertions, 0 deletions
diff --git a/src/console/commandline/CommandLineParser.ts b/src/console/commandline/CommandLineParser.ts
new file mode 100644
index 0000000..a166f49
--- /dev/null
+++ b/src/console/commandline/CommandLineParser.ts
@@ -0,0 +1,38 @@
+import CommandParser from "./CommandParser";
+import { Command } from "../../shared/Command";
+
+export type CommandLine = {
+ readonly command: Command,
+ readonly args: string
+}
+
+export enum InputPhase {
+ OnCommand,
+ OnArgs,
+}
+
+export default class CommandLineParser {
+ private commandParser: CommandParser = new CommandParser();
+
+ inputPhase(line: string): InputPhase {
+ line = line.trimLeft();
+ if (line.length == 0) {
+ return InputPhase.OnCommand
+ }
+ const command = line.split(/\s+/, 1)[0];
+ if (line.length == command.length) {
+ return InputPhase.OnCommand
+ }
+ return InputPhase.OnArgs;
+ }
+
+ parse(line: string): CommandLine {
+ const trimLeft = line.trimLeft();
+ const command = trimLeft.split(/\s+/, 1)[0];
+ const args = trimLeft.slice(command.length).trimLeft();
+ return {
+ command: this.commandParser.parse(command),
+ args: args,
+ }
+ }
+}
diff --git a/src/console/commandline/CommandParser.ts b/src/console/commandline/CommandParser.ts
new file mode 100644
index 0000000..5228c77
--- /dev/null
+++ b/src/console/commandline/CommandParser.ts
@@ -0,0 +1,52 @@
+import { Command } from "../../shared/Command";
+
+export class UnknownCommandError extends Error {
+ constructor(value: string) {
+ super(`unknown command '${value}'`);
+ }
+}
+
+export default class CommandParser {
+ parse(value: string): Command {
+ switch (value) {
+ case 'o':
+ case 'open':
+ return Command.Open;
+ case 't':
+ case 'tabopen':
+ return Command.TabOpen;
+ case 'w':
+ case 'winopen':
+ return Command.WindowOpen;
+ case 'b':
+ case 'buffer':
+ return Command.Buffer;
+ case 'bd':
+ case 'bdel':
+ case 'bdelete':
+ return Command.BufferDelete;
+ case 'bd!':
+ case 'bdel!':
+ case 'bdelete!':
+ return Command.BufferDeleteForce;
+ case 'bdeletes':
+ return Command.BuffersDelete;
+ case 'bdeletes!':
+ return Command.BuffersDeleteForce;
+ case 'addbookmark':
+ return Command.AddBookmark;
+ case 'q':
+ case 'quit':
+ return Command.Quit;
+ case 'qa':
+ case 'quitall':
+ return Command.QuitAll;
+ case 'set':
+ return Command.Set;
+ case 'h':
+ case 'help':
+ return Command.Help;
+ }
+ throw new UnknownCommandError(value);
+ }
+}
diff --git a/src/shared/Command.ts b/src/shared/Command.ts
new file mode 100644
index 0000000..e492f4a
--- /dev/null
+++ b/src/shared/Command.ts
@@ -0,0 +1,15 @@
+export enum Command {
+ Open = "open",
+ TabOpen = "tabopen",
+ WindowOpen = "winopen",
+ Buffer = "buffer",
+ BufferDelete = "bdelete",
+ BufferDeleteForce = "bdelete!",
+ BuffersDelete = "bdeletes",
+ BuffersDeleteForce = "bdeletes!",
+ AddBookmark = "addbookmark",
+ Quit = "quit",
+ QuitAll = "quitall",
+ Set = "set",
+ Help = "help",
+}
diff --git a/test/console/commandline/CommandLineParser.test.ts b/test/console/commandline/CommandLineParser.test.ts
new file mode 100644
index 0000000..6aec682
--- /dev/null
+++ b/test/console/commandline/CommandLineParser.test.ts
@@ -0,0 +1,29 @@
+import CommandLineParser, {InputPhase} from "../../../src/console/commandline/CommandLineParser";
+import { Command } from "../../../src/shared/Command";
+import { expect } from "chai";
+
+describe("CommandLineParser", () => {
+ describe("#inputPhase", () => {
+ it("returns parsed command-line", () => {
+ const sut = new CommandLineParser();
+ expect(sut.inputPhase("")).to.equal(InputPhase.OnCommand);
+ expect(sut.inputPhase("op")).to.equal(InputPhase.OnCommand);
+ expect(sut.inputPhase("open ")).to.equal(InputPhase.OnArgs);
+ expect(sut.inputPhase("open apple")).to.equal(InputPhase.OnArgs)
+ });
+ });
+ describe("#parse", () => {
+ it("returns parsed command-line", () => {
+ const sut = new CommandLineParser();
+ expect(sut.parse("open google apple")).to.deep.equal({
+ command: Command.Open,
+ args: "google apple",
+ });
+
+ expect(sut.parse("qa")).to.deep.equal({
+ command: Command.QuitAll,
+ args: "",
+ });
+ })
+ })
+});
diff --git a/test/console/commandline/CommandParser.test.ts b/test/console/commandline/CommandParser.test.ts
new file mode 100644
index 0000000..4ad78fd
--- /dev/null
+++ b/test/console/commandline/CommandParser.test.ts
@@ -0,0 +1,15 @@
+import CommandParser, { UnknownCommandError } from "../../../src/console/commandline/CommandParser";
+import { Command } from "../../../src/shared/Command";
+import { expect } from "chai"
+
+describe("CommandParser", () => {
+ describe("#parse", () => {
+ it("returns matched command with the string", () => {
+ const sut = new CommandParser();
+ expect(sut.parse("open")).to.equal(Command.Open);
+ expect(sut.parse("w")).to.equal(Command.WindowOpen);
+ expect(sut.parse("bdelete!")).to.equal(Command.BufferDeleteForce);
+ expect(() => sut.parse("harakiri")).to.throw(UnknownCommandError);
+ })
+ })
+});