diff --git a/src/cache-manager.ts b/src/cache-manager.ts index 10132f1..e2a7ca5 100644 --- a/src/cache-manager.ts +++ b/src/cache-manager.ts @@ -11,6 +11,7 @@ import { getTagsFromMetadata, isFileCanvas, isFilePlaintext, + logDebug, makeMD5, removeDiacritics, } from './tools/utils' @@ -150,6 +151,7 @@ class CacheManager { if (this.documents.has(path)) { return this.documents.get(path)! } + logDebug('Generating IndexedDocument from', path) await this.addToLiveCache(path) return this.documents.get(path)! } diff --git a/src/components/ModalVault.svelte b/src/components/ModalVault.svelte index 8c50fae..241bf81 100644 --- a/src/components/ModalVault.svelte +++ b/src/components/ModalVault.svelte @@ -15,6 +15,7 @@ getCtrlKeyLabel, getExtension, isFilePDF, + logDebug, loopIndex, } from 'src/tools/utils' import { @@ -27,7 +28,6 @@ import * as NotesIndex from '../notes-index' import { cacheManager } from '../cache-manager' import { searchEngine } from 'src/search/omnisearch' - import CancelablePromise, { cancelable } from 'cancelable-promise' export let modal: OmnisearchVaultModal export let previousQuery: string | undefined @@ -40,28 +40,13 @@ let searching = true let refInput: InputSearch | undefined - let pWaitingResults: CancelablePromise | null = null - $: selectedNote = resultNotes[selectedIndex] $: searchQuery = searchQuery ?? previousQuery $: if (searchQuery) { - if (pWaitingResults) { - pWaitingResults.cancel() - pWaitingResults = null - } searching = true - pWaitingResults = cancelable( - new Promise((resolve, reject) => { - updateResults() - .then(() => { - searching = false - resolve(null) - }) - .catch(e => { - reject(e) - }) - }) - ) + updateResults().then(() => { + searching = false + }) } else { searching = false resultNotes = [] diff --git a/src/main.ts b/src/main.ts index 039ea86..0f1e655 100644 --- a/src/main.ts +++ b/src/main.ts @@ -18,7 +18,7 @@ import { isCacheEnabled, } from './globals' import api, { notifyOnIndexed } from './tools/api' -import { isFileIndexable } from './tools/utils' +import { isFileIndexable, logDebug } from './tools/utils' import { database, OmnisearchCache } from './database' import * as NotesIndex from './notes-index' import { searchEngine } from './search/omnisearch' @@ -69,6 +69,7 @@ export default class OmnisearchPlugin extends Plugin { this.registerEvent( this.app.vault.on('create', file => { if (isFileIndexable(file.path)) { + logDebug('Indexing new file', file.path) // await cacheManager.addToLiveCache(file.path) searchEngine.addFromPaths([file.path]) } @@ -76,6 +77,7 @@ export default class OmnisearchPlugin extends Plugin { ) this.registerEvent( this.app.vault.on('delete', file => { + logDebug('Removing file', file.path) cacheManager.removeFromLiveCache(file.path) searchEngine.removeFromPaths([file.path]) }) @@ -83,6 +85,7 @@ export default class OmnisearchPlugin extends Plugin { this.registerEvent( this.app.vault.on('modify', async file => { if (isFileIndexable(file.path)) { + logDebug('Updating file', file.path) await cacheManager.addToLiveCache(file.path) NotesIndex.markNoteForReindex(file) } @@ -91,6 +94,7 @@ export default class OmnisearchPlugin extends Plugin { this.registerEvent( this.app.vault.on('rename', async (file, oldPath) => { if (isFileIndexable(file.path)) { + logDebug('Renaming file', file.path) cacheManager.removeFromLiveCache(oldPath) cacheManager.addToLiveCache(file.path) searchEngine.removeFromPaths([oldPath]) diff --git a/src/search/omnisearch.ts b/src/search/omnisearch.ts index 880e65f..a7d7eb4 100644 --- a/src/search/omnisearch.ts +++ b/src/search/omnisearch.ts @@ -9,6 +9,7 @@ import { chsRegex, getChsSegmenter, SPACE_OR_PUNCTUATION } from '../globals' import { settings } from '../settings' import { chunkArray, + logDebug, removeDiacritics, splitCamelCase, stringsToRegex, @@ -122,11 +123,13 @@ export class Omnisearch { * @param paths */ public async addFromPaths(paths: string[]): Promise { + logDebug('Adding files', paths) let documents = ( await Promise.all( paths.map(async path => await cacheManager.getDocument(path)) ) ).filter(d => !!d?.path) + logDebug('Sorting documents to first index markdown') // Index markdown files first documents = sortBy(documents, d => (d.path.endsWith('.md') ? 0 : 1)) @@ -138,13 +141,14 @@ export class Omnisearch { // Split the documents in smaller chunks to add them to minisearch const chunkedDocs = chunkArray(documents, 500) for (const docs of chunkedDocs) { + logDebug('Indexing into search engine', docs) // Update the list of indexed docs docs.forEach(doc => this.indexedDocuments.set(doc.path, doc.mtime)) - + // Discard files that may have been already added (though it shouldn't happen) const alreadyAdded = docs.filter(doc => this.minisearch.has(doc.path)) this.removeFromPaths(alreadyAdded.map(o => o.path)) - + // Add docs to minisearch await this.minisearch.addAllAsync(docs) } @@ -175,6 +179,8 @@ export class Omnisearch { return [] } + logDebug('Starting search for', query) + let results = this.minisearch.search(query.segmentsToStr(), { prefix: term => term.length >= options.prefixLength, // length <= 3: no fuzziness @@ -192,6 +198,8 @@ export class Omnisearch { }, }) + logDebug('Found', results.length, 'results') + // Filter query results to only keep files that match query.extensions (if any) if (query.extensions.length) { results = results.filter(r => { @@ -247,6 +255,8 @@ export class Omnisearch { } } + logDebug('Sorting and limiting results') + // Sort results and keep the 50 best results = results.sort((a, b) => b.score - a.score).slice(0, 50) @@ -257,6 +267,7 @@ export class Omnisearch { // If the search query contains quotes, filter out results that don't have the exact match const exactTerms = query.getExactTerms() if (exactTerms.length) { + logDebug('Filtering with quoted terms') results = results.filter(r => { const document = documents.find(d => d.path === r.id) const title = document?.path.toLowerCase() ?? '' @@ -270,6 +281,7 @@ export class Omnisearch { // If the search query contains exclude terms, filter out results that have them const exclusions = query.exclusions if (exclusions.length) { + logDebug('Filtering with exclusions') results = results.filter(r => { const content = stripMarkdownCharacters( documents.find(d => d.path === r.id)?.content ?? '' @@ -277,6 +289,8 @@ export class Omnisearch { return exclusions.every(q => !content.includes(q.value)) }) } + + logDebug('Deduping') // FIXME: // Dedupe results - clutch for https://github.com/scambier/obsidian-omnisearch/issues/129 results = results.filter( @@ -337,17 +351,13 @@ export class Omnisearch { }) } - // Extract tags from the query - const tags = query.segments - .filter(s => s.value.startsWith('#')) - .map(s => s.value) - const documents = await Promise.all( results.map(async result => await cacheManager.getDocument(result.id)) ) // Map the raw results to get usable suggestions const resultNotes = results.map(result => { + logDebug('Locating matches for', result.id) let note = documents.find(d => d.path === result.id) if (!note) { // throw new Error(`Omnisearch - Note "${result.id}" not indexed`) @@ -363,6 +373,12 @@ export class Omnisearch { query.segments.forEach(s => { s.value = s.value.replace(/^#/, '') }) + + // Extract tags from the query + const tags = query.segments + .filter(s => s.value.startsWith('#')) + .map(s => s.value) + // Clean search matches that match quoted expressions, // and inject those expressions instead const foundWords = [ @@ -376,13 +392,15 @@ export class Omnisearch { // Tags, starting with # ...tags, ].filter(w => w.length > 1 || /\p{Emoji}/u.test(w)) + logDebug('Matching tokens:', foundWords) - // console.log(foundWords) + logDebug('Getting matches locations...') const matches = this.getMatches( note.content, stringsToRegex(foundWords), query ) + logDebug('Matches:', matches) const resultNote: ResultNote = { score: result.score, foundWords, diff --git a/src/settings.ts b/src/settings.ts index 5a6ca90..9f8b536 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -47,6 +47,7 @@ export interface OmnisearchSettings extends WeightingSettings { simpleSearch: boolean highlight: boolean splitCamelCase: boolean + verboseLogging: boolean } /** @@ -357,6 +358,22 @@ export class SettingsTab extends PluginSettingTab { //#endregion Results Weighting + //#region Debugging + + new Setting(containerEl).setName('Debugging').setHeading() + + new Setting(containerEl) + .setName('Enable verbose logging') + .setDesc('Adds a LOT of logs for debugging purposes. Don\'t forget to disable it.') + .addToggle(toggle => + toggle.setValue(settings.verboseLogging).onChange(async v => { + settings.verboseLogging = v + await saveSettings(this.plugin) + }) + ) + + //#endregion Debugginh + //#region Danger Zone if (isCacheEnabled()) { new Setting(containerEl).setName('Danger Zone').setHeading() @@ -416,6 +433,7 @@ export const DEFAULT_SETTINGS: OmnisearchSettings = { weightH3: 1.1, welcomeMessage: '', + verboseLogging: false, } as const export let settings = Object.assign({}, DEFAULT_SETTINGS) as OmnisearchSettings diff --git a/src/tools/utils.ts b/src/tools/utils.ts index 035ae57..6d160d0 100644 --- a/src/tools/utils.ts +++ b/src/tools/utils.ts @@ -324,3 +324,9 @@ export function chunkArray(arr: T[], len: number): T[][] { export function splitCamelCase(text: string): string[] { return text.replace(/([a-z](?=[A-Z]))/g, '$1 ').split(' ') } + +export function logDebug(...attr: any[]): void { + if (settings.verboseLogging) { + console.log(...['Omnisearch -', ...attr]) + } +}