findwidget cleanup

This commit is contained in:
zadam 2022-05-15 21:03:51 +02:00
parent 1d8664927d
commit c50d8e85dc

View File

@ -1,32 +1,6 @@
/**
* Find in note replacement for Trilium ctrl+f search
* (c) Antonio Tejada 2022
* https://github.com/antoniotejada/Trilium-FindWidget
*
* Features:
* - Find in writeable using ctrl+f and F3
* - Tested on Trilium Desktop 0.50.3
*
* Installation:
* - Create a code note of language JS Frontend with the contents of this file
* - Set the owned attributes (alt-a) to #widget
* - Set the owned attributes of any note you don't want to enable finding to
* #noFindWidget
* - Disable Ctrl+f shorcut in Trilium options
*
* Todo:
* - Refactoring/code cleanup
* - Case-sensitive option
* - Regexp option
* - Full word option
* - Find & Replace
*
* Note that many times some common code is replicated between CodeMirror and
* CKEditor codepaths because the CKEditor update is done inside a callback that
* is deferred so the code cannot be put outside of the callback or it will
* execute too early.
*
* See https://github.com/zadam/trilium/discussions/2806 for discussions
*/
import NoteContextAwareWidget from "./note_context_aware_widget.js";
@ -44,7 +18,6 @@ const TPL = `
<input type="text" id="input">
<label tabIndex="-1" id="caseLabel"><input type="checkbox" id="caseCheck"> case sensitive</label>
<label tabIndex="-1" id="wordLabel"><input type="checkbox" id="wordCheck"> match words</label>
<label tabIndex="-1" id="regexpLabel"><input type="checkbox" id="regexpCheck" disabled> regexp</label>
<span style="font-weight: bold;" id="curFound">0</span>/<span style="font-weight: bold;" id="numFound">0</span>
</div>
</div>`;
@ -75,76 +48,6 @@ export default class FindWidget extends NoteContextAwareWidget {
this.findResult = null;
this.needle = null;
// XXX Use api.bindGlobalShortcut?
$(window).keydown(async (e) => {
if ((e.key === 'F3') ||
// Note that for ctrl+f to work, needs to be disabled in Trilium's
// shortcut config menu
// XXX Maybe not if using bindShorcut?
((e.metaKey || e.ctrlKey) && ((e.key === 'f') || (e.key === 'F')))) {
const note = appContext.tabManager.getActiveContextNote();
// Only writeable text and code supported
const readOnly = note.getAttribute("label", "readOnly");
if (!readOnly && (note.type === "code" || note.type === "text")) {
if (this.$findBox.is(":hidden")) {
this.$findBox.show();
this.$input.focus();
this.$numFound.text(0);
this.$curFound.text(0);
// Initialize the input field to the text selection, if any
if (note.type === "code") {
let codeEditor = getActiveContextCodeEditor();
// highlightSelectionMatches is the overlay that highlights
// the words under the cursor. This occludes the search
// markers style, save it, disable it. Will be restored when
// the focus is back into the note
this.oldHighlightSelectionMatches = codeEditor.getOption("highlightSelectionMatches");
codeEditor.setOption("highlightSelectionMatches", false);
// Fill in the findbox with the current selection if any
const selectedText = codeEditor.getSelection()
if (selectedText !== "") {
this.$input.val(selectedText);
}
// Directly perform the search if there's some text to find,
// without delaying or waiting for enter
const needle = this.$input.val();
if (needle !== "") {
this.$input.select();
await this.performFind(needle);
}
} else {
const textEditor = await getActiveContextTextEditor();
const selection = textEditor.model.document.selection;
const range = selection.getFirstRange();
for (const item of range.getItems()) {
// Fill in the findbox with the current selection if
// any
this.$input.val(item.data);
break;
}
// Directly perform the search if there's some text to
// find, without delaying or waiting for enter
const needle = this.$input.val();
if (needle !== "") {
this.$input.select();
await this.performFind(needle);
}
}
}
e.preventDefault();
return false;
}
}
return true;
});
this.$input.keydown(async e => {
if ((e.metaKey || e.ctrlKey) && ((e.key === 'F') || (e.key === 'f'))) {
// If ctrl+f is pressed when the findbox is shown, select the
@ -173,8 +76,8 @@ export default class FindWidget extends NoteContextAwareWidget {
const note = appContext.tabManager.getActiveContextNote();
if (note.type === "code") {
let codeEditor = getActiveContextCodeEditor();
let doc = codeEditor.doc;
const codeEditor = await getActiveContextCodeEditor();
const doc = codeEditor.doc;
//
// Dehighlight current, highlight & scrollIntoView next
@ -216,19 +119,15 @@ export default class FindWidget extends NoteContextAwareWidget {
e.preventDefault();
return false;
} else if (e.key === 'Escape') {
let numFound = parseInt(this.$numFound.text());
const note = appContext.tabManager.getActiveContextNote();
if (note.type === "code") {
let codeEditor = getActiveContextCodeEditor();
const codeEditor = await getActiveContextCodeEditor();
codeEditor.focus();
} else {
const textEditor = await getActiveContextTextEditor();
textEditor.focus();
}
}
// e.preventDefault();
});
this.$input.on('input', () => {
@ -275,14 +174,14 @@ export default class FindWidget extends NoteContextAwareWidget {
// XXX Switching to a different tab with crl+tab doesn't invoke
// blur and leaves a stale search which then breaks when
// navigating it
let numFound = parseInt(this.$numFound.text());
let curFound = parseInt(this.$curFound.text()) - 1;
const numFound = parseInt(this.$numFound.text());
const curFound = parseInt(this.$curFound.text()) - 1;
const note = appContext.tabManager.getActiveContextNote();
if (note.type === "code") {
let codeEditor = await getActiveContextCodeEditor();
const codeEditor = await getActiveContextCodeEditor();
if (numFound > 0) {
let doc = codeEditor.doc;
let pos = this.findResult[curFound].find();
const doc = codeEditor.doc;
const pos = this.findResult[curFound].find();
// Note setting the selection sets the cursor to
// the end of the selection and scrolls it into
// view
@ -305,7 +204,7 @@ export default class FindWidget extends NoteContextAwareWidget {
// Clear the markers and set the caret to the
// current occurrence
const model = textEditor.model;
let range = this.findResult.results.get(curFound).marker.getRange();
const range = this.findResult.results.get(curFound).marker.getRange();
// From
// https://github.com/ckeditor/ckeditor5/blob/b95e2faf817262ac0e1e21993d9c0bde3f1be594/packages/ckeditor5-find-and-replace/src/findandreplace.js#L92
// XXX Roll our own since already done for codeEditor and
@ -329,6 +228,65 @@ export default class FindWidget extends NoteContextAwareWidget {
return this.$widget;
}
async findInTextEvent() {
const note = appContext.tabManager.getActiveContextNote();
// Only writeable text and code supported
const readOnly = note.getAttribute("label", "readOnly");
if (!readOnly && (note.type === "code" || note.type === "text")) {
if (this.$findBox.is(":hidden")) {
this.$findBox.show();
this.$input.focus();
this.$numFound.text(0);
this.$curFound.text(0);
// Initialize the input field to the text selection, if any
if (note.type === "code") {
const codeEditor = await getActiveContextCodeEditor();
// highlightSelectionMatches is the overlay that highlights
// the words under the cursor. This occludes the search
// markers style, save it, disable it. Will be restored when
// the focus is back into the note
this.oldHighlightSelectionMatches = codeEditor.getOption("highlightSelectionMatches");
codeEditor.setOption("highlightSelectionMatches", false);
// Fill in the findbox with the current selection if any
const selectedText = codeEditor.getSelection()
if (selectedText !== "") {
this.$input.val(selectedText);
}
// Directly perform the search if there's some text to find,
// without delaying or waiting for enter
const needle = this.$input.val();
if (needle !== "") {
this.$input.select();
await this.performFind(needle);
}
} else {
const textEditor = await getActiveContextTextEditor();
const selection = textEditor.model.document.selection;
const range = selection.getFirstRange();
for (const item of range.getItems()) {
// Fill in the findbox with the current selection if
// any
this.$input.val(item.data);
break;
}
// Directly perform the search if there's some text to
// find, without delaying or waiting for enter
const needle = this.$input.val();
if (needle !== "") {
this.$input.select();
await this.performFind(needle);
}
}
}
}
}
async performTextNoteFind(needle, matchCase, wholeWord) {
// Do this even if the needle is empty so the markers are cleared and
// the counters updated
@ -403,7 +361,7 @@ export default class FindWidget extends NoteContextAwareWidget {
});
}
if (needle != "") {
if (needle !== "") {
needle = escapeRegExp(needle);
// Find and highlight matches
@ -451,7 +409,7 @@ export default class FindWidget extends NoteContextAwareWidget {
if (curFound === -1) {
const cursorPos = codeEditor.getCursor();
if ((fromPos.line > cursorPos.line) ||
((fromPos.line == cursorPos.line) &&
((fromPos.line === cursorPos.line) &&
(fromPos.ch >= cursorPos.ch))){
curFound = numFound;
}
@ -510,9 +468,7 @@ export default class FindWidget extends NoteContextAwareWidget {
}
isEnabled() {
return super.isEnabled()
&& ((this.note.type === 'text') || (this.note.type === 'code'))
&& !this.note.hasLabel('noFindWidget');
return super.isEnabled() && (this.note.type === 'text' || this.note.type === 'code');
}
async entitiesReloadedEvent({loadResults}) {