Basic file opening and display. Off-by-one bug skipping first line, though
This commit is contained in:
parent
816295ff9c
commit
d5ce04fe8b
@ -3,7 +3,7 @@
|
||||
"include": ["src/"],
|
||||
"rules": {
|
||||
"tags": ["recommended"],
|
||||
"exclude": ["no-explicit-any"]
|
||||
"exclude": ["no-explicit-any", "no-inferrable-types"]
|
||||
}
|
||||
},
|
||||
"fmt": {
|
||||
|
8
justfile
8
justfile
@ -34,8 +34,8 @@ bun-test:
|
||||
bun test --coverage
|
||||
|
||||
# Run with bun
|
||||
bun-run:
|
||||
bun run ./src/scroll.ts
|
||||
bun-run file="":
|
||||
bun run ./src/scroll.ts {{file}}
|
||||
|
||||
########################################################################################################################
|
||||
# Deno-specific commands
|
||||
@ -56,5 +56,5 @@ deno-coverage:
|
||||
deno coverage --unstable-ffi .deno-cover
|
||||
|
||||
# Run with deno
|
||||
deno-run:
|
||||
deno run --allow-all --allow-ffi --deny-net --deny-hrtime --unstable ./src/scroll.ts
|
||||
deno-run file="":
|
||||
deno run --allow-all --allow-ffi --deny-net --deny-hrtime --unstable ./src/scroll.ts {{file}}
|
||||
|
@ -8,7 +8,7 @@ const BunFileIO: IFIO = {
|
||||
return await file.text();
|
||||
},
|
||||
openFileSync: (path: string): string => {
|
||||
return readFileSync(path);
|
||||
return readFileSync(path).toString();
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,10 @@ import { ITerminal, ITerminalSize } from '../common/mod.ts';
|
||||
import Ansi from '../common/ansi.ts';
|
||||
|
||||
const BunTerminalIO: ITerminal = {
|
||||
argv: Bun.argv,
|
||||
// Deno only returns arguments passed to the script, so
|
||||
// remove the bun runtime executable, and entry script arguments
|
||||
// to have consistent argument lists
|
||||
argv: (Bun.argv.length > 2) ? Bun.argv.slice(2) : [],
|
||||
inputLoop: async function* inputLoop() {
|
||||
for await (const chunk of Bun.stdin.stream()) {
|
||||
yield chunk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { strlen } from './utils.ts';
|
||||
import { strlen, truncate } from './utils.ts';
|
||||
import { getRuntime } from './runtime.ts';
|
||||
|
||||
class Buffer {
|
||||
@ -7,12 +7,12 @@ class Buffer {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public append(s: string): void {
|
||||
this.#b += s;
|
||||
public append(s: string, maxLen?: number): void {
|
||||
this.#b += (maxLen === undefined) ? s : truncate(s, maxLen);
|
||||
}
|
||||
|
||||
public appendLine(s: string): void {
|
||||
this.#b += s + '\r\n';
|
||||
public appendLine(s = ''): void {
|
||||
this.#b += (s ?? '') + '\r\n';
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { chars } from './utils.ts';
|
||||
import { getRuntime } from './runtime.ts';
|
||||
|
||||
export class Row {
|
||||
chars: string[] = [];
|
||||
@ -27,23 +28,36 @@ export class Document {
|
||||
return new Document();
|
||||
}
|
||||
|
||||
public static open(_filename: string): Document {
|
||||
const doc = new Document();
|
||||
const line = 'Hello, World!';
|
||||
const row = new Row(line);
|
||||
|
||||
doc.#rows.push(row);
|
||||
|
||||
return doc;
|
||||
public isEmpty(): boolean {
|
||||
return this.#rows.length === 0;
|
||||
}
|
||||
|
||||
public getRow(i: number): Row | null {
|
||||
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));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public row(i: number): Row | null {
|
||||
if (this.#rows[i] !== undefined) {
|
||||
return this.#rows[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected appendRow(s: string): void {
|
||||
this.#rows.push(new Row(s));
|
||||
}
|
||||
}
|
||||
|
||||
export default Document;
|
||||
|
@ -1,23 +1,45 @@
|
||||
import Ansi, { KeyCommand } from './ansi.ts';
|
||||
import Buffer from './buffer.ts';
|
||||
import Document from './document.ts';
|
||||
import { ctrl_key, IPoint, ITerminalSize, truncate, VERSION } from './mod.ts';
|
||||
import { IPoint, ITerminalSize, VERSION } from './mod.ts';
|
||||
import { ctrl_key } from './utils.ts';
|
||||
|
||||
export class Editor {
|
||||
/**
|
||||
* The output buffer for the terminal
|
||||
* @private
|
||||
*/
|
||||
#buffer: Buffer;
|
||||
/**
|
||||
* The size of the screen in rows/columns
|
||||
* @private
|
||||
*/
|
||||
#screen: ITerminalSize;
|
||||
/**
|
||||
* The current location of the mouse cursor
|
||||
* @private
|
||||
*/
|
||||
#cursor: IPoint;
|
||||
/**
|
||||
* The document being edited
|
||||
* @private
|
||||
*/
|
||||
#document: Document;
|
||||
constructor(terminalSize: ITerminalSize, args: string[]) {
|
||||
constructor(terminalSize: ITerminalSize) {
|
||||
this.#buffer = new Buffer();
|
||||
this.#screen = terminalSize;
|
||||
this.#cursor = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
this.#document = (args.length >= 2)
|
||||
? Document.open(args[1])
|
||||
: Document.empty();
|
||||
|
||||
this.#document = Document.empty();
|
||||
}
|
||||
|
||||
public async open(filename: string): Promise<Editor> {
|
||||
await this.#document.open(filename);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -120,7 +142,7 @@ export class Editor {
|
||||
|
||||
private drawRows(): void {
|
||||
for (let y = 0; y < this.#screen.rows; y++) {
|
||||
if (y >= this.#document.numrows) {
|
||||
if (this.#document.numrows < y) {
|
||||
this.drawPlaceholderRow(y);
|
||||
} else {
|
||||
this.drawFileRow(y);
|
||||
@ -128,18 +150,19 @@ export class Editor {
|
||||
}
|
||||
}
|
||||
|
||||
private drawFileRow(_y: number): void {
|
||||
const row = this.#document.getRow(0);
|
||||
private drawFileRow(y: number): void {
|
||||
const row = this.#document.row(y);
|
||||
let len = row?.chars.length ?? 0;
|
||||
if (len > this.#screen.cols) {
|
||||
len = this.#screen.cols;
|
||||
}
|
||||
|
||||
this.#buffer.appendLine(truncate(row!.toString(), len));
|
||||
this.#buffer.append(row!.toString(), len);
|
||||
this.#buffer.appendLine(Ansi.ClearLine);
|
||||
}
|
||||
|
||||
private drawPlaceholderRow(y: number): void {
|
||||
if (y === Math.trunc(this.#screen.rows / 2)) {
|
||||
if (y === Math.trunc(this.#screen.rows / 2) && this.#document.isEmpty()) {
|
||||
const message = `Kilo editor -- version ${VERSION}`;
|
||||
const messageLen = (message.length > this.#screen.cols)
|
||||
? this.#screen.cols
|
||||
@ -152,14 +175,14 @@ export class Editor {
|
||||
this.#buffer.append(' '.repeat(padding));
|
||||
}
|
||||
|
||||
this.#buffer.append(truncate(message, messageLen));
|
||||
this.#buffer.append(message, messageLen);
|
||||
} else {
|
||||
this.#buffer.append('~');
|
||||
}
|
||||
|
||||
this.#buffer.append(Ansi.ClearLine);
|
||||
if (y < this.#screen.rows - 1) {
|
||||
this.#buffer.appendLine('');
|
||||
this.#buffer.appendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,13 @@ export async function main() {
|
||||
const terminalSize = await term.getTerminalSize();
|
||||
|
||||
// Create the editor itself
|
||||
const editor = new Editor(terminalSize, term.argv);
|
||||
const editor = new Editor(terminalSize);
|
||||
if (term.argv.length > 0) {
|
||||
const filename = term.argv[0];
|
||||
if (filename.trim() !== '') {
|
||||
await editor.open(filename);
|
||||
}
|
||||
}
|
||||
await editor.refreshScreen();
|
||||
|
||||
// The main event loop
|
||||
|
Loading…
Reference in New Issue
Block a user