refactor(code/find): reimplement find next

This commit is contained in:
Elian Doran 2025-05-12 21:21:46 +03:00
parent 2fbff5328b
commit 22d9091315
No known key found for this signature in database
3 changed files with 37 additions and 49 deletions

View File

@ -42,29 +42,11 @@ export default class FindInCode {
async findNext(direction: number, currentFound: number, nextFound: number) { async findNext(direction: number, currentFound: number, nextFound: number) {
const codeEditor = await this.getCodeEditor(); const codeEditor = await this.getCodeEditor();
if (!codeEditor || !this.findResult) { if (!codeEditor) {
return; return;
} }
const doc = codeEditor.doc; codeEditor.findNext(direction, currentFound, nextFound);
//
// Dehighlight current, highlight & scrollIntoView next
//
let marker = this.findResult[currentFound];
let pos = marker.find();
marker.clear();
marker = doc.markText(pos.from, pos.to, { className: FIND_RESULT_CSS_CLASSNAME });
this.findResult[currentFound] = marker;
marker = this.findResult[nextFound];
pos = marker.find();
marker.clear();
marker = doc.markText(pos.from, pos.to, { className: FIND_RESULT_SELECTED_CSS_CLASSNAME });
this.findResult[nextFound] = marker;
codeEditor.scrollIntoView(pos.from);
} }
async findBoxClosed(totalFound: number, currentFound: number) { async findBoxClosed(totalFound: number, currentFound: number) {

View File

@ -33,11 +33,34 @@ export class SearchHighlighter {
regexp: regex, regexp: regex,
decoration: searchMatchDecoration, decoration: searchMatchDecoration,
}); });
this.updateSearchData(this.view); this.#updateSearchData(this.view);
this.scrollToMatchNearestSelection(); this.#scrollToMatchNearestSelection();
} }
updateSearchData(view: EditorView) { scrollToMatch(matchIndex: number) {
if (this.parsedMatches.length <= matchIndex) {
return;
}
const match = this.parsedMatches[matchIndex];
this.currentFound = matchIndex + 1;
this.view.dispatch({
effects: EditorView.scrollIntoView(match.from, { y: "center" }),
scrollIntoView: true
});
}
update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) {
this.#updateSearchData(update.view);
}
}
destroy() {
// Do nothing.
}
#updateSearchData(view: EditorView) {
if (!this.matcher) { if (!this.matcher) {
return; return;
} }
@ -56,26 +79,7 @@ export class SearchHighlighter {
this.totalFound = this.parsedMatches.length; this.totalFound = this.parsedMatches.length;
} }
update(update: ViewUpdate) { #scrollToMatchNearestSelection() {
if (update.docChanged || update.viewportChanged) {
this.updateSearchData(update.view);
}
}
scrollToMatch(matchIndex: number) {
if (this.parsedMatches.length <= matchIndex) {
return;
}
const match = this.parsedMatches[matchIndex];
this.currentFound = matchIndex + 1;
this.view.dispatch({
effects: EditorView.scrollIntoView(match.from, { y: "center" }),
scrollIntoView: true
});
}
scrollToMatchNearestSelection() {
const cursorPos = this.view.state.selection.main.head; const cursorPos = this.view.state.selection.main.head;
let index = 0; let index = 0;
for (const match of this.parsedMatches) { for (const match of this.parsedMatches) {
@ -88,10 +92,6 @@ export class SearchHighlighter {
} }
} }
destroy() {
// Do nothing.
}
static deco = (v: SearchHighlighter) => v.matches; static deco = (v: SearchHighlighter) => v.matches;
} }

View File

@ -1,5 +1,5 @@
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands"; import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
import { EditorView, highlightActiveLine, keymap, lineNumbers, placeholder, ViewUpdate, type EditorViewConfig } from "@codemirror/view"; import { EditorView, highlightActiveLine, keymap, lineNumbers, placeholder, ViewPlugin, ViewUpdate, type EditorViewConfig } from "@codemirror/view";
import { defaultHighlightStyle, StreamLanguage, syntaxHighlighting, indentUnit, bracketMatching, foldGutter } from "@codemirror/language"; import { defaultHighlightStyle, StreamLanguage, syntaxHighlighting, indentUnit, bracketMatching, foldGutter } from "@codemirror/language";
import { Compartment, EditorSelection, EditorState, type Extension } from "@codemirror/state"; import { Compartment, EditorSelection, EditorState, type Extension } from "@codemirror/state";
import { highlightSelectionMatches } from "@codemirror/search"; import { highlightSelectionMatches } from "@codemirror/search";
@ -7,7 +7,7 @@ import { vim } from "@replit/codemirror-vim";
import byMimeType from "./syntax_highlighting.js"; import byMimeType from "./syntax_highlighting.js";
import smartIndentWithTab from "./extensions/custom_tab.js"; import smartIndentWithTab from "./extensions/custom_tab.js";
import type { ThemeDefinition } from "./color_themes.js"; import type { ThemeDefinition } from "./color_themes.js";
import { createSearchHighlighter, searchMatchHighlightTheme } from "./find_replace.js"; import { createSearchHighlighter, SearchHighlighter, searchMatchHighlightTheme } from "./find_replace.js";
export { default as ColorThemes, type ThemeDefinition, getThemeById } from "./color_themes.js"; export { default as ColorThemes, type ThemeDefinition, getThemeById } from "./color_themes.js";
@ -31,6 +31,7 @@ export default class CodeMirror extends EditorView {
private themeCompartment: Compartment; private themeCompartment: Compartment;
private lineWrappingCompartment: Compartment; private lineWrappingCompartment: Compartment;
private searchHighlightCompartment: Compartment; private searchHighlightCompartment: Compartment;
private searchPlugin?: SearchHighlighter | null;
constructor(config: EditorConfig) { constructor(config: EditorConfig) {
const languageCompartment = new Compartment(); const languageCompartment = new Compartment();
@ -181,6 +182,7 @@ export default class CodeMirror extends EditorView {
await new Promise(requestAnimationFrame); await new Promise(requestAnimationFrame);
const instance = this.plugin(plugin); const instance = this.plugin(plugin);
instance?.searchFor(searchTerm, matchCase, wholeWord); instance?.searchFor(searchTerm, matchCase, wholeWord);
this.searchPlugin = instance;
return { return {
totalFound: instance?.totalFound ?? 0, totalFound: instance?.totalFound ?? 0,
@ -188,6 +190,10 @@ export default class CodeMirror extends EditorView {
} }
} }
async findNext(direction: number, currentFound: number, nextFound: number) {
this.searchPlugin?.scrollToMatch(nextFound);
}
async setMimeType(mime: string) { async setMimeType(mime: string) {
let newExtension: Extension[] = []; let newExtension: Extension[] = [];