From 85dbd506c6dca6101fa535cc3371f8fb745cc2d0 Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Wed, 28 Feb 2024 15:44:57 -0500 Subject: [PATCH] Implement backwards/forwards searching --- src/common/document.ts | 63 ++++++++++++++++++++++++++++++++++++++---- src/common/editor.ts | 5 ++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/common/document.ts b/src/common/document.ts index f81a41d..e6ac5bb 100644 --- a/src/common/document.ts +++ b/src/common/document.ts @@ -1,10 +1,53 @@ import Row from './row.ts'; import { arrayInsert } from './fns.ts'; import { getRuntime } from './runtime.ts'; -import { Position } from './types.ts'; +import { Position, SearchDirection } from './types.ts'; +import { KeyCommand } from './ansi.ts'; + +class Search { + public lastMatch: number = -1; + public current: number = -1; + public direction: SearchDirection = SearchDirection.Forward; + + public parseInput(key: string) { + switch (key) { + case KeyCommand.ArrowRight: + case KeyCommand.ArrowDown: + this.direction = SearchDirection.Forward; + break; + + case KeyCommand.ArrowLeft: + case KeyCommand.ArrowUp: + this.direction = SearchDirection.Backward; + break; + + default: + this.lastMatch = -1; + this.direction = SearchDirection.Forward; + } + + if (this.lastMatch === -1) { + this.direction = SearchDirection.Forward; + } + + this.current = this.lastMatch; + } + + public getNextRow(rowCount: number): number { + this.current += this.direction; + if (this.current === -1) { + this.current = rowCount - 1; + } else if (this.current === rowCount) { + this.current = 0; + } + + return this.current; + } +} export class Document { #rows: Row[]; + #search: Search; /** * Has the document been modified? @@ -13,6 +56,7 @@ export class Document { private constructor() { this.#rows = []; + this.#search = new Search(); this.dirty = false; } @@ -53,15 +97,24 @@ export class Document { this.dirty = false; } + public resetFind() { + this.#search = new Search(); + } + public find( q: string, - offset: Position = Position.default(), + key: string, ): Position | null { - let i = offset.y; + this.#search.parseInput(key); + + let i = 0; for (; i < this.numRows; i++) { - const possible = this.#rows[i].find(q, offset.x); + const current = this.#search.getNextRow(this.numRows); + + const possible = this.#rows[current].find(q); if (possible !== null) { - return Position.at(possible, i); + this.#search.lastMatch = current; + return Position.at(possible, current); } } diff --git a/src/common/editor.ts b/src/common/editor.ts index 6b5ac14..daae49c 100644 --- a/src/common/editor.ts +++ b/src/common/editor.ts @@ -302,14 +302,15 @@ class Editor { const savedOffset = Position.from(this.#offset); const query = await this.prompt( - 'Search: %s (ESC to cancel)', + 'Search: %s (Use ESC/Arrows/Enter)', (query: string, key: string) => { if (key === KeyCommand.Enter || key === KeyCommand.Escape) { + this.#document.resetFind(); return; } if (query !== null && query.length > 0) { - const pos = this.#document.find(query); + const pos = this.#document.find(query, key); if (pos !== null) { this.#cursor = pos; } else {