From 38dc4b3060b089bc8829bde2f34ff198830a283e Mon Sep 17 00:00:00 2001 From: Danielo Rodriguez Date: Mon, 8 Jan 2024 17:49:21 +0100 Subject: [PATCH] feat(form): the input file is now fuzzy over path and tags. It shows a nicer UI that includes the path --- src/suggesters/suggestFile.ts | 57 ++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/suggesters/suggestFile.ts b/src/suggesters/suggestFile.ts index 19a87e31..3e54a558 100644 --- a/src/suggesters/suggestFile.ts +++ b/src/suggesters/suggestFile.ts @@ -1,16 +1,16 @@ -import { AbstractInputSuggest, App, TAbstractFile, TFile } from "obsidian"; -import { get_tfiles_from_folder } from "../utils/files"; -import { E } from "@std"; +import { AbstractInputSuggest, App, TFile } from "obsidian"; +import { enrich_tfile, get_tfiles_from_folder } from "../utils/files"; +import { E, pipe, A } from "@std"; +import Fuse from "fuse.js"; // Instead of hardcoding the logic in separate and almost identical classes, // we move this little logic parts into an interface and we can use the samme // input type and configure it to render file-like, note-like, or whatever we want. export interface FileStrategy { - renderSuggestion(file: TFile): string; + renderSuggestion(file: TFile): string | DocumentFragment; selectSuggestion(file: TFile): string; } - export class FileSuggest extends AbstractInputSuggest { constructor( public app: App, @@ -22,24 +22,52 @@ export class FileSuggest extends AbstractInputSuggest { } getSuggestions(input_str: string): TFile[] { - const all_files = get_tfiles_from_folder(this.folder, this.app) + const all_files = pipe( + get_tfiles_from_folder(this.folder, this.app), + E.map(A.map((file) => enrich_tfile(file, this.app))), + ); if (E.isLeft(all_files)) { return []; } const lower_input_str = input_str.toLowerCase(); - - return all_files.right.filter((file: TAbstractFile) => { - return ( - file instanceof TFile && - file.extension === "md" && - file.path.toLowerCase().contains(lower_input_str) - ); + if (input_str === "") return all_files.right; + const fuse = new Fuse(all_files.right, { + keys: ["path", "tags", "frontmatter"], }); + return fuse.search(lower_input_str).map((result) => result.item); } + /* This is an example structure of how a obsidian suggestion looks like in the dom +
+
+
+
+ Fátima +
+
Fátima
+
+
+ + + + + + +
+
+
+In the renderSuggestion the `el` is the suggestion-item div +*/ renderSuggestion(file: TFile, el: HTMLElement): void { - el.setText(this.strategy.renderSuggestion(file)); + const text = this.strategy.renderSuggestion(file); + el.addClasses(["mod-complex"]); + const title = el.createDiv({ cls: "suggestion-title", text: text }); + const note = el.createDiv({ cls: "suggestion-note", text: file.parent?.path }); + const body = el.createDiv({ cls: "suggestion-content" }); + body.appendChild(title); + body.appendChild(note); + el.appendChild(body); } selectSuggestion(file: TFile): void { @@ -48,4 +76,3 @@ export class FileSuggest extends AbstractInputSuggest { this.close(); } } -