2023-11-13 15:33:56 -05:00
|
|
|
import { chars } from './utils.ts';
|
2023-11-14 15:53:45 -05:00
|
|
|
import { getRuntime } from './runtime.ts';
|
2023-11-20 15:14:36 -05:00
|
|
|
import { TAB_SIZE } from './mod.ts';
|
2023-11-13 14:46:04 -05:00
|
|
|
|
|
|
|
export class Row {
|
|
|
|
chars: string[] = [];
|
2023-11-20 15:14:36 -05:00
|
|
|
render: string[] = [];
|
2023-11-13 14:46:04 -05:00
|
|
|
|
|
|
|
constructor(s: string = '') {
|
|
|
|
this.chars = chars(s);
|
2023-11-20 15:14:36 -05:00
|
|
|
this.render = [];
|
2023-11-13 14:46:04 -05:00
|
|
|
}
|
|
|
|
|
2023-11-20 14:21:42 -05:00
|
|
|
public get size(): number {
|
|
|
|
return this.chars.length;
|
|
|
|
}
|
|
|
|
|
2023-11-20 15:14:36 -05:00
|
|
|
public get rsize(): number {
|
|
|
|
return this.render.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
public rstring(offset: number = 0): string {
|
|
|
|
return this.render.slice(offset).join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
public cxToRx(cx: number): number {
|
|
|
|
let rx = 0;
|
|
|
|
let j = 0;
|
|
|
|
for (; j < cx; j++) {
|
|
|
|
if (this.chars[j] === '\t') {
|
|
|
|
rx += (TAB_SIZE - 1) - (rx % TAB_SIZE);
|
|
|
|
}
|
|
|
|
rx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rx;
|
|
|
|
}
|
|
|
|
|
2023-11-13 14:46:04 -05:00
|
|
|
public toString(): string {
|
|
|
|
return this.chars.join('');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Document {
|
|
|
|
#rows: Row[];
|
|
|
|
|
|
|
|
private constructor() {
|
|
|
|
this.#rows = [];
|
|
|
|
}
|
|
|
|
|
2023-11-16 11:10:33 -05:00
|
|
|
get numRows(): number {
|
2023-11-13 14:46:04 -05:00
|
|
|
return this.#rows.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static empty(): Document {
|
|
|
|
return new Document();
|
|
|
|
}
|
|
|
|
|
2023-11-14 15:53:45 -05:00
|
|
|
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 = [];
|
|
|
|
}
|
2023-11-13 14:46:04 -05:00
|
|
|
|
2023-11-14 15:53:45 -05:00
|
|
|
const rawFile = await file.openFile(filename);
|
|
|
|
rawFile.split(/\r?\n/)
|
|
|
|
.forEach((row) => this.appendRow(row));
|
2023-11-13 14:46:04 -05:00
|
|
|
|
2023-11-14 15:53:45 -05:00
|
|
|
return this;
|
2023-11-13 14:46:04 -05:00
|
|
|
}
|
|
|
|
|
2023-11-14 15:53:45 -05:00
|
|
|
public row(i: number): Row | null {
|
2023-11-20 14:21:42 -05:00
|
|
|
return this.#rows[i] ?? null;
|
2023-11-13 14:46:04 -05:00
|
|
|
}
|
2023-11-14 15:53:45 -05:00
|
|
|
|
2023-11-16 20:57:21 -05:00
|
|
|
public appendRow(s: string): void {
|
2023-11-20 15:14:36 -05:00
|
|
|
const at = this.numRows;
|
|
|
|
this.#rows[at] = new Row(s);
|
|
|
|
this.updateRow(this.#rows[at]);
|
|
|
|
}
|
|
|
|
|
|
|
|
private updateRow(r: Row): void {
|
|
|
|
r.render = chars(r.toString().replace('\t', ' '.repeat(TAB_SIZE)));
|
2023-11-14 15:53:45 -05:00
|
|
|
}
|
2023-11-13 14:46:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export default Document;
|