scroll/src/common/document.ts

97 lines
1.7 KiB
JavaScript

import Row from './row.ts';
import { getRuntime } from './runtime.ts';
import { Position } from './mod.ts';
export class Document {
#filename: string | null;
#rows: Row[];
dirty: boolean;
private constructor() {
this.#rows = [];
this.#filename = null;
this.dirty = false;
}
get numRows(): number {
return this.#rows.length;
}
public static empty(): Document {
return new Document();
}
public isEmpty(): boolean {
return this.#rows.length === 0;
}
public async open(filename: string): Promise<Document> {
const { file } = await getRuntime();
// Clear any existing rows
if (!this.isEmpty()) {
this.#rows = [];
}
const rawFile = await file.openFile(filename);
rawFile.split(/\r?\n/)
.forEach((row) => this.appendRow(row));
this.#filename = filename;
this.dirty = false;
return this;
}
public async save() {
if (this.#filename === null) {
return;
}
const { file } = await getRuntime();
await file.saveFile(this.#filename, this.rowsToString());
this.dirty = false;
}
public insert(at: Position, c: string): void {
if (at.y === this.numRows) {
this.appendRow(c);
} else {
this.#rows[at.y].insertChar(at.x, c);
this.#rows[at.y].updateRender();
}
this.dirty = true;
}
public delete(at: Position): void {
const row = this.row(at.y);
if (row === null) {
return;
}
row.delete(at.x);
row.updateRender();
}
public row(i: number): Row | null {
return this.#rows[i] ?? null;
}
public appendRow(s: string): void {
const at = this.numRows;
this.#rows[at] = new Row(s);
this.#rows[at].updateRender();
this.dirty = true;
}
private rowsToString(): string {
return this.#rows.map((r) => r.toString()).join('\n');
}
}
export default Document;