91 lines
3.3 KiB
TypeScript

import { App, TFile } from "obsidian";
import {
MAX_RESULTS,
truncateLine,
findLineDetails,
SearchResult,
formatResults,
} from '../search-common';
/**
* Searches using Obsidian's core search plugin and builds context for each match.
*
* @param app The Obsidian App instance.
* @param query The query to search for.
* @returns A promise that resolves to a formatted string of search results.
*/
export async function matchSearchUsingCorePlugin(
query: string,
app: App,
): Promise<string> {
try {
const searchPlugin = (app as any).internalPlugins.plugins['global-search']?.instance;
if (!searchPlugin) {
throw new Error("Core search plugin is not available.");
}
// This function opens the search pane and executes the search.
// It does not return the results directly.
searchPlugin.openGlobalSearch(query);
const searchLeaf = app.workspace.getLeavesOfType('search')[0];
if (!searchLeaf) {
throw new Error("No active search pane found after triggering search.");
}
// Ensure the view is fully loaded before we try to access its properties.
const view = await searchLeaf.open(searchLeaf.view);
const searchResultsMap = await new Promise<Map<TFile, any>>(resolve => {
setTimeout(() => {
// @ts-ignore
const results = (view as any).dom?.resultDomLookup;
resolve(results || new Map());
}, 10000)
});
if (!searchResultsMap || searchResultsMap.size === 0) {
console.error("No results found or search results map is not available.");
return "No results found."
}
const results: SearchResult[] = [];
const vault = app.vault;
for (const [file, fileMatches] of searchResultsMap.entries()) {
if (results.length >= MAX_RESULTS) {
break;
}
const content = await vault.cachedRead(file as TFile);
const lines = content.split('\n');
// `fileMatches.result.content` holds an array of matches for the file.
// Each match is an array: [matched_text, start_offset]
for (const match of fileMatches.result.content) {
if (results.length >= MAX_RESULTS) break;
const startOffset = match[1];
const { lineNumber, columnNumber, lineContent } = findLineDetails(lines, startOffset);
if (lineNumber === -1) continue;
results.push({
file: file.path,
line: lineNumber + 1, // ripgrep is 1-based, so we adjust
column: columnNumber + 1,
match: truncateLine(lineContent.trimEnd()),
beforeContext: lineNumber > 0 ? [truncateLine(lines[lineNumber - 1].trimEnd())] : [],
afterContext:
lineNumber < lines.length - 1
? [truncateLine(lines[lineNumber + 1].trimEnd())]
: [],
});
}
}
return formatResults(results, ".\\");
} catch (error) {
console.error("Error during core plugin processing:", error);
return "An error occurred during the search.";
}
}