diff --git a/src/common/all_test.ts b/src/common/all_test.ts index 1d08b27..7555a4c 100644 --- a/src/common/all_test.ts +++ b/src/common/all_test.ts @@ -110,20 +110,20 @@ testSuite({ }, Document: { 'Document.empty': () => { - const doc = Document.empty(); + const doc = Document.default(); assertEquals(doc.numRows, 0); assertTrue(doc.isEmpty()); assertEquals(doc.row(0), null); }, 'Document.insertRow': () => { - const doc = Document.empty(); + const doc = Document.default(); doc.insertRow(undefined, 'foobar'); assertEquals(doc.numRows, 1); assertFalse(doc.isEmpty()); assertInstanceOf(doc.row(0), Row); }, 'Document.insert': () => { - const doc = Document.empty(); + const doc = Document.default(); assertFalse(doc.dirty); doc.insert(Position.at(0, 0), 'foobar'); assertEquals(doc.numRows, 1); @@ -146,7 +146,7 @@ testSuite({ assertTrue(doc.dirty); }, 'Document.delete': () => { - const doc = Document.empty(); + const doc = Document.default(); doc.insert(Position.default(), 'foobar'); doc.delete(Position.at(3, 0)); assertEquals(doc.row(0)?.toString(), 'fooar'); diff --git a/src/common/ansi.ts b/src/common/ansi.ts index cc17b44..cd1094b 100644 --- a/src/common/ansi.ts +++ b/src/common/ansi.ts @@ -33,7 +33,7 @@ export const Ansi = { GetCursorLocation: ANSI_PREFIX + '6n', InvertColor: ANSI_PREFIX + '7m', ResetFormatting: ANSI_PREFIX + 'm', - moveCursor: function moveCursor(row: number, col: number): string { + moveCursor: (row: number, col: number): string => { // Convert to 1-based counting row++; col++; diff --git a/src/common/document.ts b/src/common/document.ts index 511269e..3cc80f1 100644 --- a/src/common/document.ts +++ b/src/common/document.ts @@ -3,13 +3,11 @@ import { getRuntime } from './runtime.ts'; import { arrayInsert, Position } from './mod.ts'; export class Document { - #filename: string | null; #rows: Row[]; dirty: boolean; private constructor() { this.#rows = []; - this.#filename = null; this.dirty = false; } @@ -17,7 +15,7 @@ export class Document { return this.#rows.length; } - public static empty(): Document { + public static default(): Document { return new Document(); } @@ -37,20 +35,15 @@ export class Document { rawFile.split(/\r?\n/) .forEach((row) => this.insertRow(this.numRows, row)); - this.#filename = filename; this.dirty = false; return this; } - public async save() { - if (this.#filename === null) { - return; - } - + public async save(filename: string) { const { file } = await getRuntime(); - await file.saveFile(this.#filename, this.rowsToString()); + await file.saveFile(filename, this.rowsToString()); this.dirty = false; } diff --git a/src/common/editor.ts b/src/common/editor.ts index 2a18424..f3a638c 100644 --- a/src/common/editor.ts +++ b/src/common/editor.ts @@ -2,6 +2,7 @@ import Ansi, { KeyCommand } from './ansi.ts'; import Buffer from './buffer.ts'; import Document from './document.ts'; import { + getRuntime, isControl, ITerminalSize, logToFile, @@ -74,7 +75,7 @@ class Editor { this.#cursor = Position.default(); this.#offset = Position.default(); - this.#document = Document.empty(); + this.#document = Document.default(); } private get numRows(): number { @@ -92,6 +93,20 @@ class Editor { return this; } + public async save(): Promise { + if (this.#filename === '') { + const filename = await this.prompt('Save as: '); + if (filename === null) { + return; + } + + this.#filename = filename; + } + + await this.#document.save(this.#filename); + this.setStatusMessage(`${this.#filename} was saved to disk.`); + } + // -------------------------------------------------------------------------- // Command/input mapping // -------------------------------------------------------------------------- @@ -106,8 +121,7 @@ class Editor { // Ctrl-key chords // ---------------------------------------------------------------------- case ctrlKey('s'): - await this.#document.save(); - this.setStatusMessage(`${this.#filename} was saved to disk.`); + await this.save(); break; case ctrlKey('q'): @@ -210,6 +224,33 @@ class Editor { return true; } + public async prompt(p: string): Promise { + const { term } = await getRuntime(); + + let res = ''; + + while (true) { + this.setStatusMessage(`${p}${res}`); + await this.refreshScreen(); + const chunk = await term.inputLoop().next(); + const char = chunk.value!; + // End the prompt + if (char === KeyCommand.Enter) { + this.setStatusMessage(''); + if (res.length === 0) { + return null; + } + + return res; + } + + // Add to the prompt result + if (!isControl(char)) { + res += char; + } + } + } + /** * Filter out any additional unwanted keyboard input * @param input diff --git a/src/common/main.ts b/src/common/main.ts index 01c9454..7e0d2c7 100644 --- a/src/common/main.ts +++ b/src/common/main.ts @@ -23,7 +23,6 @@ export async function main() { // Create the editor itself const editor = new Editor(terminalSize); - editor.setStatusMessage('HELP: Ctrl-S = save | Ctrl-Q = quit'); // Process cli arguments if (term.argv.length > 0) { @@ -33,6 +32,8 @@ export async function main() { } } + editor.setStatusMessage('HELP: Ctrl-S = save | Ctrl-Q = quit'); + // Clear the screen await editor.refreshScreen();