ufuzzy suggestions

This commit is contained in:
Daniel Bauer
2024-12-12 23:26:51 +01:00
parent 8beb4ac67d
commit b41d3275d9
4 changed files with 81 additions and 28 deletions

6
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@leeoniya/ufuzzy": "^1.0.17",
"@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.0",
"rollup": "^2.79.2", "rollup": "^2.79.2",
@@ -1093,6 +1094,11 @@
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
} }
}, },
"node_modules/@leeoniya/ufuzzy": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/@leeoniya/ufuzzy/-/ufuzzy-1.0.17.tgz",
"integrity": "sha512-bGNsu11VP70ZgN+bP9SOQ9rsX6Tu/RzLJQ5F5TzgM9IaZncZweu7lDwcMfPAQ9RW3TVMfnbMCD/NnowkjyT+dQ=="
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"license": "MIT", "license": "MIT",

View File

@@ -30,6 +30,7 @@
"typescript": "4.7.4" "typescript": "4.7.4"
}, },
"dependencies": { "dependencies": {
"@leeoniya/ufuzzy": "^1.0.17",
"@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.0",
"rollup": "^2.79.2", "rollup": "^2.79.2",

View File

@@ -9,8 +9,12 @@ import {
TFile, TFile,
} from "obsidian"; } from "obsidian";
import { getTriggerText } from "./trigger"; import { getTriggerText } from "./trigger";
import uFuzzy from "@leeoniya/ufuzzy";
export class DataviewSuggester extends EditorSuggest<String> { export class DataviewSuggester extends EditorSuggest<String> {
suggestionsList: string[] = [];
searcher: uFuzzy = new uFuzzy({});
constructor(plugin: Plugin) { constructor(plugin: Plugin) {
super(plugin.app); super(plugin.app);
} }
@@ -36,34 +40,22 @@ export class DataviewSuggester extends EditorSuggest<String> {
getSuggestions( getSuggestions(
context: EditorSuggestContext, context: EditorSuggestContext,
): string[] | Promise<string[]> { ): string[] | Promise<string[]> {
const suggestions: string[] = []; let idxs = this.searcher.filter(this.suggestionsList, context.query);
// TODO use official dv api? if (idxs != null && idxs.length > 0) {
// @ts-ignore let info = this.searcher.info(
for (const page of this.app.plugins.plugins.dataview.index.pages) { idxs,
const fields = page[1].fields; this.suggestionsList,
for (let [key, val] of fields) { context.query,
let arrayVal; );
if (!Array.isArray(val)) { let order = this.searcher.sort(
arrayVal = [val]; info,
} else { this.suggestionsList,
arrayVal = val; context.query,
} );
for (const value of arrayVal) { return order.map((i) => this.suggestionsList[info.idx[i]]);
// TODO whitespace in match
// Fuzzy matching?
const suggestion = key + ":: " + value;
if (
suggestion.includes(context.query) &&
!suggestions.includes(suggestion)
) {
suggestions.push(key + ":: " + value);
}
}
}
} }
console.log(suggestions); return [];
return suggestions;
} }
renderSuggestion(value: string, el: HTMLElement): void { renderSuggestion(value: string, el: HTMLElement): void {
@@ -71,7 +63,6 @@ export class DataviewSuggester extends EditorSuggest<String> {
} }
selectSuggestion(value: string, evt: MouseEvent | KeyboardEvent): void { selectSuggestion(value: string, evt: MouseEvent | KeyboardEvent): void {
console.log("selected", value);
const { editor, start, end } = this.context!; const { editor, start, end } = this.context!;
editor.replaceRange(value, start, end); editor.replaceRange(value, start, end);
@@ -81,4 +72,42 @@ export class DataviewSuggester extends EditorSuggest<String> {
}; };
editor.setCursor(newCursorPos); editor.setCursor(newCursorPos);
} }
public buildNewIndex() {
console.log("Rebuilding dataview suggestion index");
const newSuggestions: string[] = [];
// Iterate all pages of the Dataview index, and ingest all fields into suggestions
// TODO: can we use official dataview api?
// @ts-ignore
for (const page of this.app.plugins.plugins.dataview.index.pages) {
const fields = page[1].fields;
for (let [key, val] of fields) {
// fields can be a single value or a dict, so we need to handle both
let arrayVal;
if (!Array.isArray(val)) {
arrayVal = [val];
} else {
arrayVal = val;
}
// Add composite value "key:: value" to suggestions list
for (const value of arrayVal) {
const compositeValue = key + ":: " + value;
if (newSuggestions.indexOf(compositeValue) === -1) {
newSuggestions.push(compositeValue);
}
}
}
}
// replace old index
this.suggestionsList = newSuggestions;
}
// possible types: update, rename, delete. rename has oldPath
public onMetadataChange(type: string, file: TFile, oldPath?: string) {
// TODO handle efficiently with delta updates
this.buildNewIndex();
}
} }

View File

@@ -1,4 +1,4 @@
import { App, Plugin, PluginSettingTab, Setting } from "obsidian"; import { App, Plugin, PluginSettingTab, Setting, TFile } from "obsidian";
import { DataviewSuggester } from "./DataviewSuggester"; import { DataviewSuggester } from "./DataviewSuggester";
interface DataviewAutocompleteSettings { interface DataviewAutocompleteSettings {
@@ -19,6 +19,23 @@ export default class DataviewAutocompletePlugin extends Plugin {
// register suggester // register suggester
this.suggester = new DataviewSuggester(this); this.suggester = new DataviewSuggester(this);
this.registerEditorSuggest(this.suggester); this.registerEditorSuggest(this.suggester);
this.registerEvent(
// @ts-ignore
this.app.metadataCache.on("dataview:index-ready", () => {
this.suggester.buildNewIndex();
}),
);
this.registerEvent(
this.app.metadataCache.on(
// @ts-ignore
"dataview:metadata-change",
(type: string, file: TFile, oldPath?: string) => {
this.suggester.onMetadataChange(type, file, oldPath);
},
),
);
} }
onunload() {} onunload() {}