scroll/src/common/editor/editor.ts

131 lines
2.8 KiB
JavaScript
Raw Normal View History

2023-11-08 18:07:34 -05:00
import Ansi from './ansi.ts';
import Buffer from './buffer.ts';
2023-11-09 12:05:30 -05:00
import {
ctrl_key,
importDefaultForRuntime,
2023-11-10 08:36:18 -05:00
IPoint,
2023-11-09 12:05:30 -05:00
ITerminalSize,
truncate,
VERSION,
} from '../mod.ts';
2023-11-08 11:11:19 -05:00
export class Editor {
2023-11-08 11:11:19 -05:00
#buffer: Buffer;
2023-11-10 08:36:18 -05:00
#screen: ITerminalSize;
#cursor: IPoint;
constructor(terminalSize: ITerminalSize) {
2023-11-08 11:11:19 -05:00
this.#buffer = new Buffer();
2023-11-10 08:36:18 -05:00
this.#screen = terminalSize;
this.#cursor = {
x: 0,
y: 0,
};
2023-11-08 11:11:19 -05:00
}
2023-11-10 08:36:18 -05:00
// --------------------------------------------------------------------------
// Command/input mapping
// --------------------------------------------------------------------------
2023-11-08 11:11:19 -05:00
/**
* Determine what to do based on input
* @param input - the decoded chunk of stdin
*/
public processKeyPress(input: string): boolean {
switch (input) {
case ctrl_key('q'):
2023-11-09 12:32:41 -05:00
this.clearScreen().then(() => {});
2023-11-08 11:11:19 -05:00
return false;
2023-11-10 08:36:18 -05:00
case 'w':
case 's':
case 'a':
case 'd':
this.moveCursor(input);
break;
}
return true;
}
private moveCursor(char: string): void {
switch (char) {
case 'a':
this.#cursor.x--;
break;
case 'd':
this.#cursor.x++;
break;
case 'w':
this.#cursor.y--;
break;
case 's':
this.#cursor.y++;
break;
2023-11-08 11:11:19 -05:00
}
}
2023-11-10 08:36:18 -05:00
// --------------------------------------------------------------------------
2023-11-09 12:05:30 -05:00
// Terminal Output / Drawing
2023-11-10 08:36:18 -05:00
// --------------------------------------------------------------------------
2023-11-09 12:05:30 -05:00
2023-11-08 11:11:19 -05:00
/**
* Clear the screen and write out the buffer
*/
public async refreshScreen(): Promise<void> {
2023-11-09 12:05:30 -05:00
this.#buffer.append(Ansi.HideCursor);
this.#buffer.append(Ansi.ResetCursor);
this.drawRows();
2023-11-10 08:36:18 -05:00
this.#buffer.append(
Ansi.moveCursor(this.#cursor.y + 1, this.#cursor.x + 1),
);
2023-11-09 12:05:30 -05:00
this.#buffer.append(Ansi.ShowCursor);
2023-11-09 12:32:41 -05:00
await this.writeToScreen();
}
2023-11-08 11:11:19 -05:00
2023-11-09 12:32:41 -05:00
private async clearScreen(): Promise<void> {
this.#buffer.append(Ansi.ClearScreen);
this.#buffer.append(Ansi.ResetCursor);
await this.writeToScreen();
}
2023-11-09 12:05:30 -05:00
private drawRows(): void {
this.drawPlaceholderRows();
}
private drawPlaceholderRows(): void {
2023-11-10 08:36:18 -05:00
for (let y = 0; y < this.#screen.rows; y++) {
if (y === Math.trunc(this.#screen.rows / 2)) {
2023-11-09 12:05:30 -05:00
const message = `Kilo editor -- version ${VERSION}`;
2023-11-10 08:36:18 -05:00
const messageLen = (message.length > this.#screen.cols)
? this.#screen.cols
: message.length;
let padding = Math.trunc((this.#screen.cols - messageLen) / 2);
if (padding > 0) {
this.#buffer.append('~');
padding -= 1;
this.#buffer.append(' '.repeat(padding));
}
this.#buffer.append(truncate(message, messageLen));
2023-11-09 12:05:30 -05:00
} else {
this.#buffer.append('~');
}
this.#buffer.append(Ansi.ClearLine);
2023-11-10 08:36:18 -05:00
if (y < this.#screen.rows - 1) {
2023-11-09 12:32:41 -05:00
this.#buffer.appendLine('');
2023-11-09 12:05:30 -05:00
}
}
}
2023-11-09 12:32:41 -05:00
private async writeToScreen(): Promise<void> {
const io = await importDefaultForRuntime('terminal_io');
await io.write(this.#buffer.getBuffer());
this.#buffer.clear();
}
}