Move the cursor
This commit is contained in:
parent
c5e7d6e209
commit
1723219452
2
justfile
2
justfile
@ -50,7 +50,7 @@ deno-test:
|
||||
# Create test coverage report with deno
|
||||
deno-coverage:
|
||||
deno test --allow-all --coverage=.deno-cover
|
||||
deno coverage --lcov .deno-cover
|
||||
deno coverage --unstable-ffi .deno-cover
|
||||
|
||||
# Run with deno
|
||||
deno-run:
|
||||
|
@ -9,7 +9,7 @@ export const Ansi = {
|
||||
HideCursor: esc`?25l`,
|
||||
ShowCursor: esc`?25h`,
|
||||
moveCursor: function moveCursor(row: number, col: number): string {
|
||||
return `\x1b${row};${col}H`;
|
||||
return `\x1b[${row};${col}H`;
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ import Buffer from './buffer.ts';
|
||||
import {
|
||||
ctrl_key,
|
||||
importDefaultForRuntime,
|
||||
IPoint,
|
||||
ITerminalSize,
|
||||
truncate,
|
||||
VERSION,
|
||||
@ -10,14 +11,21 @@ import {
|
||||
|
||||
export class Editor {
|
||||
#buffer: Buffer;
|
||||
#screenRows: number;
|
||||
#screenCols: number;
|
||||
#screen: ITerminalSize;
|
||||
#cursor: IPoint;
|
||||
constructor(terminalSize: ITerminalSize) {
|
||||
this.#buffer = new Buffer();
|
||||
this.#screenRows = terminalSize.rows;
|
||||
this.#screenCols = terminalSize.cols;
|
||||
this.#screen = terminalSize;
|
||||
this.#cursor = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Command/input mapping
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determine what to do based on input
|
||||
* @param input - the decoded chunk of stdin
|
||||
@ -28,14 +36,37 @@ export class Editor {
|
||||
this.clearScreen().then(() => {});
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
// Terminal Output / Drawing
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clear the screen and write out the buffer
|
||||
@ -44,6 +75,9 @@ export class Editor {
|
||||
this.#buffer.append(Ansi.HideCursor);
|
||||
this.#buffer.append(Ansi.ResetCursor);
|
||||
this.drawRows();
|
||||
this.#buffer.append(
|
||||
Ansi.moveCursor(this.#cursor.y + 1, this.#cursor.x + 1),
|
||||
);
|
||||
this.#buffer.append(Ansi.ShowCursor);
|
||||
|
||||
await this.writeToScreen();
|
||||
@ -61,11 +95,13 @@ export class Editor {
|
||||
}
|
||||
|
||||
private drawPlaceholderRows(): void {
|
||||
for (let y = 0; y < this.#screenRows; y++) {
|
||||
if (y === Math.trunc(this.#screenRows / 2)) {
|
||||
for (let y = 0; y < this.#screen.rows; y++) {
|
||||
if (y === Math.trunc(this.#screen.rows / 2)) {
|
||||
const message = `Kilo editor -- version ${VERSION}`;
|
||||
const messageLen = (message.length > this.#screenCols) ? this.#screenCols : message.length;
|
||||
let padding = Math.trunc((this.#screenCols - messageLen) / 2);
|
||||
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;
|
||||
@ -79,7 +115,7 @@ export class Editor {
|
||||
}
|
||||
|
||||
this.#buffer.append(Ansi.ClearLine);
|
||||
if (y < this.#screenRows - 1) {
|
||||
if (y < this.#screen.rows - 1) {
|
||||
this.#buffer.appendLine('');
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,15 @@
|
||||
/**
|
||||
* The shared test interface, so tests can be run by both runtimes
|
||||
*/
|
||||
export interface ITestBase {
|
||||
test(name: string, fn: () => void): void;
|
||||
assertEquals(actual: unknown, expected: unknown): void;
|
||||
assertNotEquals(actual: unknown, expected: unknown): void;
|
||||
assertStrictEquals(actual: unknown, expected: unknown): void;
|
||||
assertExists(actual: unknown): void;
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void;
|
||||
assertTrue(actual: boolean): void;
|
||||
assertFalse(actual: boolean): void;
|
||||
// ----------------------------------------------------------------------------
|
||||
// General types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export interface IPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Runtime adapter interfaces
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* The native functions for terminal settings
|
||||
*/
|
||||
@ -69,3 +67,21 @@ export interface IRuntime {
|
||||
*/
|
||||
onExit(cb: () => void): void;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Testing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The shared test interface, so tests can be run by both runtimes
|
||||
*/
|
||||
export interface ITestBase {
|
||||
test(name: string, fn: () => void): void;
|
||||
assertEquals(actual: unknown, expected: unknown): void;
|
||||
assertNotEquals(actual: unknown, expected: unknown): void;
|
||||
assertStrictEquals(actual: unknown, expected: unknown): void;
|
||||
assertExists(actual: unknown): void;
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void;
|
||||
assertTrue(actual: boolean): void;
|
||||
assertFalse(actual: boolean): void;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
// Strings
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Split a string by graphemes, not just bytes
|
||||
|
Loading…
Reference in New Issue
Block a user