Basic deletion functionality
This commit is contained in:
parent
a7f5fed9a3
commit
b665ce8ce7
@ -18,6 +18,12 @@ const {
|
||||
testSuite,
|
||||
} = await getTestRunner();
|
||||
|
||||
const testKeyMap = (codes: string[], expected: string) => {
|
||||
codes.forEach((code) => {
|
||||
assertEquals(readKey(code), expected);
|
||||
});
|
||||
};
|
||||
|
||||
testSuite({
|
||||
'ANSI::ANSI utils': {
|
||||
'Ansi.moveCursor': () => {
|
||||
@ -39,27 +45,21 @@ testSuite({
|
||||
assertEquals(readKey(KeyCommand.ArrowUp), KeyCommand.ArrowUp);
|
||||
assertEquals(readKey(KeyCommand.Home), KeyCommand.Home);
|
||||
assertEquals(readKey(KeyCommand.Delete), KeyCommand.Delete);
|
||||
|
||||
// And pass through whatever else
|
||||
assertEquals(readKey('foobaz'), 'foobaz');
|
||||
},
|
||||
'readKey Esc': () => {
|
||||
['\x1b', Util.ctrlKey('l')].forEach((code) => {
|
||||
assertEquals(readKey(code), KeyCommand.Escape);
|
||||
});
|
||||
},
|
||||
'readKey Backspace': () => {
|
||||
[Util.ctrlKey('h'), String.fromCodePoint(127)].forEach((code) => {
|
||||
assertEquals(readKey(code), KeyCommand.Backspace);
|
||||
});
|
||||
},
|
||||
'readKey Home': () => {
|
||||
['\x1b[1~', '\x1b[7~', '\x1b[H', '\x1bOH'].forEach((code) => {
|
||||
assertEquals(readKey(code), KeyCommand.Home);
|
||||
});
|
||||
},
|
||||
'readKey End': () => {
|
||||
['\x1b[4~', '\x1b[8~', '\x1b[F', '\x1bOF'].forEach((code) => {
|
||||
assertEquals(readKey(code), KeyCommand.End);
|
||||
});
|
||||
},
|
||||
'readKey Esc': () =>
|
||||
testKeyMap(['\x1b', Util.ctrlKey('l')], KeyCommand.Escape),
|
||||
'readKey Backspace': () =>
|
||||
testKeyMap(
|
||||
[Util.ctrlKey('h'), '\x7f'],
|
||||
KeyCommand.Backspace,
|
||||
),
|
||||
'readKey Home': () =>
|
||||
testKeyMap(['\x1b[1~', '\x1b[7~', '\x1b[H', '\x1bOH'], KeyCommand.Home),
|
||||
'readKey End': () =>
|
||||
testKeyMap(['\x1b[4~', '\x1b[8~', '\x1b[F', '\x1bOF'], KeyCommand.End),
|
||||
},
|
||||
Buffer: {
|
||||
'Buffer exists': () => {
|
||||
@ -137,6 +137,12 @@ testSuite({
|
||||
assertEquals(doc.numRows, 2);
|
||||
assertTrue(doc.dirty);
|
||||
},
|
||||
'Document.delete': () => {
|
||||
const doc = Document.empty();
|
||||
doc.insert(Position.default(), 'foobar');
|
||||
doc.delete(Position.at(3, 0));
|
||||
assertEquals(doc.row(0)?.toString(), 'fooar');
|
||||
},
|
||||
},
|
||||
Editor: {
|
||||
'new Editor': () => {
|
||||
|
@ -76,7 +76,7 @@ export function readKey(parsed: string): string {
|
||||
return KeyCommand.Escape;
|
||||
|
||||
case ctrlKey('h'):
|
||||
case String.fromCodePoint(127):
|
||||
case '\x7f':
|
||||
return KeyCommand.Backspace;
|
||||
|
||||
default:
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { chars } from './utils.ts';
|
||||
import Row from './row.ts';
|
||||
import { getRuntime } from './runtime.ts';
|
||||
import { Position, SCROLL_TAB_SIZE } from './mod.ts';
|
||||
import { Position } from './mod.ts';
|
||||
|
||||
export class Document {
|
||||
#filename: string | null;
|
||||
@ -61,12 +60,22 @@ export class Document {
|
||||
this.appendRow(c);
|
||||
} else {
|
||||
this.#rows[at.y].insertChar(at.x, c);
|
||||
this.updateRow(this.#rows[at.y]);
|
||||
this.#rows[at.y].updateRender();
|
||||
}
|
||||
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
public delete(at: Position): void {
|
||||
const row = this.row(at.y);
|
||||
if (row === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
row.delete(at.x);
|
||||
row.updateRender();
|
||||
}
|
||||
|
||||
public row(i: number): Row | null {
|
||||
return this.#rows[i] ?? null;
|
||||
}
|
||||
@ -74,15 +83,11 @@ export class Document {
|
||||
public appendRow(s: string): void {
|
||||
const at = this.numRows;
|
||||
this.#rows[at] = new Row(s);
|
||||
this.updateRow(this.#rows[at]);
|
||||
this.#rows[at].updateRender();
|
||||
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
private updateRow(r: Row): void {
|
||||
r.render = chars(r.toString().replace('\t', ' '.repeat(SCROLL_TAB_SIZE)));
|
||||
}
|
||||
|
||||
private rowsToString(): string {
|
||||
return this.#rows.map((r) => r.toString()).join('\n');
|
||||
}
|
||||
|
@ -113,9 +113,17 @@ class Editor {
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyCommand.Backspace:
|
||||
case KeyCommand.Delete:
|
||||
// TODO
|
||||
this.#document.delete(this.#cursor);
|
||||
break;
|
||||
|
||||
case KeyCommand.Backspace:
|
||||
{
|
||||
if (this.#cursor.x > 0 || this.#cursor.y > 0) {
|
||||
this.moveCursor(KeyCommand.ArrowLeft);
|
||||
this.#document.delete(this.#cursor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyCommand.PageUp:
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { SCROLL_TAB_SIZE } from './mod.ts';
|
||||
import { chars, SCROLL_TAB_SIZE } from './mod.ts';
|
||||
import * as Util from './utils.ts';
|
||||
|
||||
/**
|
||||
@ -44,6 +44,14 @@ export class Row {
|
||||
}
|
||||
}
|
||||
|
||||
public delete(at: number): void {
|
||||
if (at >= this.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.chars.splice(at, 1);
|
||||
}
|
||||
|
||||
public cxToRx(cx: number): number {
|
||||
let rx = 0;
|
||||
let j = 0;
|
||||
@ -60,6 +68,15 @@ export class Row {
|
||||
public toString(): string {
|
||||
return this.chars.join('');
|
||||
}
|
||||
|
||||
public updateRender(): void {
|
||||
const newString = this.chars.join('').replace(
|
||||
'\t',
|
||||
' '.repeat(SCROLL_TAB_SIZE),
|
||||
);
|
||||
|
||||
this.render = chars(newString);
|
||||
}
|
||||
}
|
||||
|
||||
export default Row;
|
||||
|
Loading…
Reference in New Issue
Block a user