Add horizontal scrolling

This commit is contained in:
Timothy Warren 2023-11-20 14:21:42 -05:00
parent 9b95850e86
commit 28ec91798a
3 changed files with 83 additions and 23 deletions

View File

@ -8,6 +8,10 @@ export class Row {
this.chars = chars(s);
}
public get size(): number {
return this.chars.length;
}
public toString(): string {
return this.chars.join('');
}
@ -48,11 +52,7 @@ export class Document {
}
public row(i: number): Row | null {
if (this.#rows[i] !== undefined) {
return this.#rows[i];
}
return null;
return this.#rows[i] ?? null;
}
public appendRow(s: string): void {

View File

@ -1,8 +1,8 @@
import Ansi, { KeyCommand } from './ansi.ts';
import Buffer from './buffer.ts';
import Document from './document.ts';
import Document, { Row } from './document.ts';
import { IPoint, ITerminalSize, logToFile, VERSION } from './mod.ts';
import { ctrlKey } from './utils.ts';
import { ctrlKey, posSub } from './utils.ts';
export class Editor {
/**
@ -29,6 +29,11 @@ export class Editor {
* @private
*/
#document: Document;
private get currentRow(): Row | null {
return this.#document.row(this.#cursor.y);
}
constructor(terminalSize: ITerminalSize) {
this.#buffer = new Buffer();
this.#screen = terminalSize;
@ -102,11 +107,24 @@ export class Editor {
case KeyCommand.ArrowLeft:
if (this.#cursor.x > 0) {
this.#cursor.x--;
} else if (this.#cursor.y > 0) {
this.#cursor.y--;
this.#cursor.x = (this.currentRow !== null)
? this.currentRow.size - 1
: 0;
}
break;
case KeyCommand.ArrowRight:
if (this.#cursor.x < this.#screen.cols) {
if (
this.currentRow !== null && this.#cursor.x < this.currentRow.size - 1
) {
this.#cursor.x++;
} else if (
this.currentRow !== null &&
this.#cursor.x === this.currentRow.size - 1
) {
this.#cursor.y++;
this.#cursor.x = 0;
}
break;
case KeyCommand.ArrowUp:
@ -115,11 +133,16 @@ export class Editor {
}
break;
case KeyCommand.ArrowDown:
if (this.#cursor.y < this.#screen.rows) {
if (this.#cursor.y < this.#document.numRows) {
this.#cursor.y++;
}
break;
}
const rowLen = this.currentRow?.size ?? 0;
if (this.#cursor.x > rowLen) {
this.#cursor.x = rowLen;
}
}
private scroll(): void {
@ -129,6 +152,12 @@ export class Editor {
if (this.#cursor.y >= this.#offset.y + this.#screen.rows) {
this.#offset.y = this.#cursor.y - this.#screen.rows + 1;
}
if (this.#cursor.x < this.#offset.x) {
this.#offset.x = this.#cursor.x;
}
if (this.#cursor.x >= this.#offset.x + this.#screen.cols) {
this.#offset.x = this.#cursor.x - this.#screen.cols + 1;
}
}
// --------------------------------------------------------------------------
@ -144,7 +173,10 @@ export class Editor {
this.#buffer.append(Ansi.ResetCursor);
this.drawRows();
this.#buffer.append(
Ansi.moveCursor(this.#cursor.y, this.#cursor.x),
Ansi.moveCursor(
this.#cursor.y - this.#offset.y,
this.#cursor.x - this.#offset.x,
),
);
this.#buffer.append(Ansi.ShowCursor);
@ -160,11 +192,16 @@ export class Editor {
private drawRows(): void {
for (let y = 0; y < this.#screen.rows; y++) {
let filerow = y + this.#offset.y;
const filerow = y + this.#offset.y;
if (filerow >= this.#document.numRows) {
this.drawPlaceholderRow(y);
this.drawPlaceholderRow(filerow);
} else {
this.drawFileRow(y);
this.drawFileRow(filerow);
}
this.#buffer.append(Ansi.ClearLine);
if (y < this.#screen.rows - 1) {
this.#buffer.appendLine();
}
}
}
@ -176,13 +213,12 @@ export class Editor {
return this.drawPlaceholderRow(y);
}
let len = row.chars.length ?? 0;
if (len > this.#screen.cols) {
len = this.#screen.cols;
}
const len = Math.min(
posSub(row.chars.length, this.#offset.x),
this.#screen.cols,
);
this.#buffer.append(row.toString(), len);
this.#buffer.appendLine(Ansi.ClearLine);
}
private drawPlaceholderRow(y: number): void {
@ -203,10 +239,5 @@ export class Editor {
} else {
this.#buffer.append('~');
}
this.#buffer.append(Ansi.ClearLine);
if (y < this.#screen.rows - 1) {
this.#buffer.appendLine();
}
}
}

View File

@ -4,6 +4,35 @@
export const noop = () => {};
/**
* Subtract two numbers, returning a zero if the result is negative
* @param l
* @param s
*/
export function posSub(l: number, s: number): number {
return minSub(l, s, 0);
}
/**
* Subtract two numbers, returning at least the minimum specified
* @param l
* @param s
* @param min
*/
export function minSub(l: number, s: number, min: number): number {
return Math.max(l - s, min);
}
/**
* Add two numbers, up to a max value
* @param n1
* @param n2
* @param max
*/
export function maxAdd(n1: number, n2: number, max: number): number {
return Math.min(n1 + n2, max);
}
// ----------------------------------------------------------------------------
// Strings
// ----------------------------------------------------------------------------