Do basic highlighting of search results, finish stop #151 of the kilo tutorial
Some checks failed
timw4mail/scroll/pipeline/head There was a failure building this commit
Some checks failed
timw4mail/scroll/pipeline/head There was a failure building this commit
This commit is contained in:
parent
faf59b4235
commit
e6b53ef327
8
justfile
8
justfile
@ -30,9 +30,9 @@ clean:
|
||||
rm -f scroll.err
|
||||
rm -f tsconfig.tsbuildinfo
|
||||
|
||||
########################################################################################################################
|
||||
##########################################################################################
|
||||
# Bun-specific commands
|
||||
########################################################################################################################
|
||||
##########################################################################################
|
||||
|
||||
# Check code with actual Typescript compiler
|
||||
bun-check:
|
||||
@ -46,9 +46,9 @@ bun-test:
|
||||
bun-run file="":
|
||||
bun run ./src/scroll.ts {{file}}
|
||||
|
||||
########################################################################################################################
|
||||
##########################################################################################
|
||||
# Deno-specific commands
|
||||
########################################################################################################################
|
||||
##########################################################################################
|
||||
|
||||
# Lint code and check types
|
||||
deno-check:
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Row from './row.ts';
|
||||
import { arrayInsert } from './fns.ts';
|
||||
import { arrayInsert, strlen } from './fns.ts';
|
||||
import { HighlightType } from './highlight.ts';
|
||||
import { getRuntime } from './runtime.ts';
|
||||
import { Position } from './types.ts';
|
||||
import { Search } from './search.ts';
|
||||
@ -74,7 +75,26 @@ export class Document {
|
||||
q: string,
|
||||
key: string,
|
||||
): Position | null {
|
||||
return this.#search.search(q, key);
|
||||
const potential = this.#search.search(q, key);
|
||||
if (potential !== null) {
|
||||
// Update highlight of search match
|
||||
const row = this.#rows[potential.y];
|
||||
|
||||
// Okay, we have to take the Javascript string index (potential.x), convert
|
||||
// it to the Row character index, and then convert that to the Row render index
|
||||
// so that the highlighted color starts in the right place.
|
||||
const start = row.cxToRx(row.byteIndexToCharIndex(potential.x));
|
||||
|
||||
// Just to be safe with unicode searches, take the number of 'characters'
|
||||
// as the search query length, not the JS string length.
|
||||
const end = start + strlen(q);
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
row.hl[i] = HighlightType.Match;
|
||||
}
|
||||
}
|
||||
|
||||
return potential;
|
||||
}
|
||||
|
||||
public insert(at: Position, c: string): void {
|
||||
|
@ -295,7 +295,8 @@ class Editor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find text within the document
|
||||
* Find text within the document. This is roughly equivalent to the
|
||||
* `editorFindCallback` function in the kilo tutorial.
|
||||
*/
|
||||
public async find(): Promise<void> {
|
||||
const savedCursor = Position.from(this.#cursor);
|
||||
@ -314,6 +315,7 @@ class Editor {
|
||||
if (query !== null && query.length > 0) {
|
||||
const pos = this.#document.find(query, key);
|
||||
if (pos !== null) {
|
||||
// We have a match here
|
||||
this.#cursor = pos;
|
||||
this.scroll();
|
||||
} else {
|
||||
|
18
src/common/position.ts
Normal file
18
src/common/position.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Convenience type for (x,y) coordinate values
|
||||
*/
|
||||
export class Position {
|
||||
private constructor(public x: number = 0, public y: number = 0) {}
|
||||
|
||||
public static at(x: number, y: number): Position {
|
||||
return new Position(x, y);
|
||||
}
|
||||
|
||||
public static from(p: Position): Position {
|
||||
return new Position(p.x, p.y);
|
||||
}
|
||||
|
||||
public static default(): Position {
|
||||
return new Position();
|
||||
}
|
||||
}
|
@ -12,18 +12,18 @@ export class Row {
|
||||
/**
|
||||
* The actual characters in the current row
|
||||
*/
|
||||
chars: string[] = [];
|
||||
public chars: string[] = [];
|
||||
|
||||
/**
|
||||
* The characters rendered for the current row
|
||||
* (like replacing tabs with spaces)
|
||||
*/
|
||||
rchars: string[] = [];
|
||||
public rchars: string[] = [];
|
||||
|
||||
/**
|
||||
* The syntax highlighting map
|
||||
*/
|
||||
hl: HighlightType[] = [];
|
||||
public hl: HighlightType[] = [];
|
||||
|
||||
private constructor(s: string | string[] = '') {
|
||||
this.chars = Array.isArray(s) ? s : strChars(s);
|
||||
@ -84,6 +84,10 @@ export class Row {
|
||||
this.chars.splice(at, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the current row for the specified string, and return
|
||||
* the index of the start of that match
|
||||
*/
|
||||
public find(s: string, offset: number = 0): number | null {
|
||||
const thisStr = this.toString();
|
||||
if (!this.toString().includes(s)) {
|
||||
|
@ -49,13 +49,22 @@ export class Search {
|
||||
}
|
||||
|
||||
public search(q: string, key: string): Position | null {
|
||||
if (this.parent === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.parseInput(key);
|
||||
|
||||
let i = 0;
|
||||
for (; i < this.parent!.numRows; i++) {
|
||||
const current = this.getNextRow(this.parent!.numRows);
|
||||
for (; i < this.parent.numRows; i++) {
|
||||
const current = this.getNextRow(this.parent.numRows);
|
||||
const row = this.parent.row(current);
|
||||
|
||||
const possible = this.parent!.row(current)!.find(q);
|
||||
if (row === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const possible = row.find(q);
|
||||
if (possible !== null) {
|
||||
this.lastMatch = current;
|
||||
return Position.at(possible, current);
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { RunTimeType } from './runtime.ts';
|
||||
|
||||
export { Position } from './position.ts';
|
||||
|
||||
/**
|
||||
* The size of terminal in rows and columns
|
||||
*/
|
||||
@ -100,32 +102,6 @@ export type ITerminal = IRuntime['term'];
|
||||
*/
|
||||
export type IFileIO = IRuntime['file'];
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// General types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export class Position {
|
||||
public x: number;
|
||||
public y: number;
|
||||
|
||||
private constructor(x: number = 0, y: number = 0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public static at(x: number, y: number): Position {
|
||||
return new Position(x, y);
|
||||
}
|
||||
|
||||
public static from(p: Position): Position {
|
||||
return new Position(p.x, p.y);
|
||||
}
|
||||
|
||||
public static default(): Position {
|
||||
return new Position();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Testing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user