diff --git a/index.ts b/index.ts deleted file mode 100644 index ed9b234..0000000 --- a/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Editor } from "./src/editor.ts"; -import { Renderer } from "./src/renderer.ts"; -import { Terminal } from "./src/terminal.ts"; -import { parseKey } from "./src/utils.ts"; -import { Viewport } from "./src/viewport.ts"; - -const editor = new Editor(); - -const terminal = new Terminal(); -let size = terminal.size(); - -const viewport = new Viewport(size.width, size.height); -const renderer = new Renderer(terminal, viewport); - -terminal.start(); -viewport.followCursor(editor.cursor); -renderer.render(editor); - -process.stdin.on("data", (input: string) => { - const key = parseKey(input); - if (key === null) return; - switch (key.type) { - case "character": - editor.insert(key.value); - break; - case "backspace": - editor.backspace(); - break; - case "enter": - editor.newline(); - break; - case "left": - editor.moveLeft(); - break; - case "right": - editor.moveRight(); - break; - case "up": - editor.moveUp(); - break; - case "down": - editor.moveDown(); - break; - case "quit": - terminal.stop(); - process.exit(0); - } - viewport.followCursor(editor.cursor); - renderer.render(editor); -}); diff --git a/package.json b/package.json index 2971570..b261201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fae", - "module": "./index.ts", + "module": "./src/index.ts", "type": "module", "private": true, "devDependencies": { diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..360b38c --- /dev/null +++ b/src/index.ts @@ -0,0 +1,20 @@ +import { Editor } from "./services/editor.ts"; +import { Renderer } from "./services/renderer.ts"; +import { Terminal } from "./services/terminal.ts"; +import { parseKey } from "./utils/inputs.ts"; +import { Viewport } from "./services/viewport.ts"; +import { InputHandler } from "./services/inputs.ts"; +import { Listener } from "./services/listeners.ts"; + +const editor = new Editor(); +const terminal = new Terminal(); +const size = terminal.size(); +const viewport = new Viewport(size.width, size.height); +const renderer = new Renderer(terminal, viewport); +const handler = new InputHandler(editor); +const listeners = new Listener(editor, renderer, handler, terminal, viewport); + +terminal.start(); +viewport.followCursor(editor.cursor); +renderer.render(editor); +listeners.start(); diff --git a/src/buffer.ts b/src/services/buffer.ts similarity index 94% rename from src/buffer.ts rename to src/services/buffer.ts index 51562e3..61b4a79 100644 --- a/src/buffer.ts +++ b/src/services/buffer.ts @@ -1,4 +1,4 @@ -import type { BufferType, InsertType } from "./types"; +import type { BufferType, InsertType } from "../types"; export class TextBuffer { lines: string[] = [""]; diff --git a/src/cursor.ts b/src/services/cursor.ts similarity index 100% rename from src/cursor.ts rename to src/services/cursor.ts diff --git a/src/editor.ts b/src/services/editor.ts similarity index 95% rename from src/editor.ts rename to src/services/editor.ts index 6cfd1c2..157c510 100644 --- a/src/editor.ts +++ b/src/services/editor.ts @@ -1,6 +1,6 @@ import { Cursor } from "./cursor.ts"; import { TextBuffer } from "./buffer.ts"; -import type { BufferType, InsertType } from "./types"; +import type { BufferType, InsertType } from "../types"; export class Editor { readonly buffer: TextBuffer; diff --git a/src/services/inputs.ts b/src/services/inputs.ts new file mode 100644 index 0000000..1957127 --- /dev/null +++ b/src/services/inputs.ts @@ -0,0 +1,22 @@ +import type { Key } from "../types"; +import { Editor } from "../services/editor"; + +export class InputHandler { + constructor(private editor: Editor) {} + private commands = new Map void>([ + ["backspace", () => this.editor.backspace()], + ["enter", () => this.editor.newline()], + ["left", () => this.editor.moveLeft()], + ["right", () => this.editor.moveRight()], + ["down", () => this.editor.moveDown()], + ["up", () => this.editor.moveUp()], + ]); + + handle(key: Key) { + if (key.type === "character") { + this.editor.insert(key.value); + return; + } + this.commands.get(key.type)?.(); + } +} diff --git a/src/services/listeners.ts b/src/services/listeners.ts new file mode 100644 index 0000000..e8c1bca --- /dev/null +++ b/src/services/listeners.ts @@ -0,0 +1,38 @@ +import type { Editor } from "./editor.ts"; +import type { Renderer } from "./renderer.ts"; +import type { InputHandler } from "./inputs.ts"; +import type { Terminal } from "./terminal.ts"; +import type { Viewport } from "./viewport.ts"; +import { parseKey } from "../utils/inputs.ts"; + +export class Listener { + constructor( + private editor: Editor, + private renderer: Renderer, + private handler: InputHandler, + private terminal: Terminal, + private viewport: Viewport, + ) {} + + start() { + process.stdin.on("data", (data: string) => { + const key = parseKey(data); + if (key === null) return; + if (key.type === "quit") { + this.terminal.stop(); + process.exit(0); + } + this.handler.handle(key); + this.viewport.followCursor(this.editor.cursor); + this.renderer.render(this.editor); + }); + + process.stdout.on("resize", () => { + const size = this.terminal.size(); + this.viewport.height = size.height; + this.viewport.width = size.width; + this.viewport.followCursor(this.editor.cursor); + this.renderer.render(this.editor); + }); + } +} diff --git a/src/renderer.ts b/src/services/renderer.ts similarity index 100% rename from src/renderer.ts rename to src/services/renderer.ts diff --git a/src/terminal.ts b/src/services/terminal.ts similarity index 100% rename from src/terminal.ts rename to src/services/terminal.ts diff --git a/src/viewport.ts b/src/services/viewport.ts similarity index 100% rename from src/viewport.ts rename to src/services/viewport.ts diff --git a/src/tests/buffer.test.ts b/src/tests/buffer.test.ts index 8b97591..a1021b5 100644 --- a/src/tests/buffer.test.ts +++ b/src/tests/buffer.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { TextBuffer } from "../buffer"; -import type { BufferType, InsertType } from "../types.ts"; +import { TextBuffer } from "../services/buffer.ts"; +import type { BufferType, InsertType } from "../types"; test("starts on empty line", () => { const buffer = new TextBuffer(); diff --git a/src/tests/cursor.test.ts b/src/tests/cursor.test.ts index d9db87a..7f91df3 100644 --- a/src/tests/cursor.test.ts +++ b/src/tests/cursor.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { TextBuffer } from "../buffer"; -import { Cursor } from "../cursor"; +import { TextBuffer } from "../services/buffer.ts"; +import { Cursor } from "../services/cursor.ts"; test("starts at 0,0", () => { const cursor = new Cursor(); diff --git a/src/tests/editor.test.ts b/src/tests/editor.test.ts index 02ea3ff..90c0a03 100644 --- a/src/tests/editor.test.ts +++ b/src/tests/editor.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test"; -import { Editor } from "../editor"; +import { Editor } from "../services/editor.ts"; test("starts on empty buffer", () => { const editor = new Editor(); diff --git a/src/tests/terminal.test.ts b/src/tests/terminal.test.ts index 9996726..f310ff5 100644 --- a/src/tests/terminal.test.ts +++ b/src/tests/terminal.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test"; -import { Terminal } from "../terminal"; +import { Terminal } from "../services/terminal.ts"; test("fetches terminal size", () => { const terminal = new Terminal(); diff --git a/src/tests/utils.test.ts b/src/tests/utils.test.ts index 1a8a710..0017641 100644 --- a/src/tests/utils.test.ts +++ b/src/tests/utils.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test"; -import { parseKey } from "../utils.ts"; +import { parseKey } from "../utils/inputs.ts"; test("parse character", () => { expect(parseKey("a")).toEqual({ diff --git a/src/tests/viewport.test.ts b/src/tests/viewport.test.ts index b97e4dc..7d421d6 100644 --- a/src/tests/viewport.test.ts +++ b/src/tests/viewport.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { Viewport } from "../viewport"; -import { Cursor } from "../cursor"; +import { Viewport } from "../services/viewport.ts"; +import { Cursor } from "../services/cursor.ts"; test("viewport shows cursor (right)", () => { const viewport = new Viewport(8, 8); diff --git a/src/types.ts b/src/types/index.ts similarity index 100% rename from src/types.ts rename to src/types/index.ts diff --git a/src/utils.ts b/src/utils/inputs.ts similarity index 95% rename from src/utils.ts rename to src/utils/inputs.ts index 9358146..923fbc6 100644 --- a/src/utils.ts +++ b/src/utils/inputs.ts @@ -1,4 +1,4 @@ -import type { Key } from "./types.ts"; +import type { Key } from "../types"; export function parseKey(input: string): Key | null { if (input === "\x1b[A") {