scroll/src/common/search.ts
Timothy J. Warren 1b3e9d9796
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good
Add Option type to remove the need to use null/undefined
2024-07-03 16:13:29 -04:00

81 lines
1.6 KiB
JavaScript

import Document from './document.ts';
import { KeyCommand } from './ansi.ts';
import Option, { None } from './option.ts';
import { Position } from './types.ts';
enum SearchDirection {
Forward = 1,
Backward = -1,
}
export class Search {
private lastMatch: number = -1;
private current: number = -1;
private direction: SearchDirection = SearchDirection.Forward;
public parent: Option<Document> = None;
private 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;
}
private 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;
}
public search(q: string, key: string): Option<Position> {
if (this.parent.isNone()) {
return None;
}
const parent = this.parent.unwrap();
this.parseInput(key);
let i = 0;
for (; i < parent.numRows; i++) {
const current = this.getNextRow(parent.numRows);
const row = parent.row(current);
if (row === null) {
continue;
}
const possible = row.find(q);
if (possible.isSome()) {
this.lastMatch = current;
return possible.map((p: number) => Position.at(p, current));
}
}
return None;
}
}