Skip to content

Commit

Permalink
feat: show better errors
Browse files Browse the repository at this point in the history
fix: dataview input was not filtering
  • Loading branch information
danielo515 committed Sep 14, 2023
1 parent 93020bd commit 8202d37
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 57 deletions.
82 changes: 41 additions & 41 deletions src/suggesters/suggestFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,54 @@
import { App, TAbstractFile, TFile } from "obsidian";
import { TextInputSuggest } from "./suggest";
import { get_tfiles_from_folder } from "../utils/files";
import { errorWrapperSync } from "../utils/Error";
import { tryCatch } from "../utils/Error";

// 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;
selectSuggestion(file: TFile): string;
renderSuggestion(file: TFile): string;
selectSuggestion(file: TFile): string;
}

export class FileSuggest extends TextInputSuggest<TFile> {
constructor(
protected app: App,
public inputEl: HTMLInputElement,
private strategy: FileStrategy,
private folder: string,
) {
super(app, inputEl);
}

getSuggestions(input_str: string): TFile[] {
const all_files = errorWrapperSync(
() => get_tfiles_from_folder(this.folder, this.app),
"The folder does not exist"
);
if (!all_files) {
return [];
}

const lower_input_str = input_str.toLowerCase();

return all_files.filter((file: TAbstractFile) => {
return (
file instanceof TFile &&
file.extension === "md" &&
file.path.toLowerCase().contains(lower_input_str)
);
});
}

renderSuggestion(file: TFile, el: HTMLElement): void {
el.setText(this.strategy.renderSuggestion(file));
}

selectSuggestion(file: TFile): void {
this.inputEl.value = this.strategy.selectSuggestion(file);
this.inputEl.trigger("input");
this.close();
}
constructor(
protected app: App,
public inputEl: HTMLInputElement,
private strategy: FileStrategy,
private folder: string,
) {
super(app, inputEl);
}

getSuggestions(input_str: string): TFile[] {
const all_files = tryCatch(
() => get_tfiles_from_folder(this.folder, this.app),
"The folder does not exist"
);
if (!all_files) {
return [];
}

const lower_input_str = input_str.toLowerCase();

return all_files.filter((file: TAbstractFile) => {
return (
file instanceof TFile &&
file.extension === "md" &&
file.path.toLowerCase().contains(lower_input_str)
);
});
}

renderSuggestion(file: TFile, el: HTMLElement): void {
el.setText(this.strategy.renderSuggestion(file));
}

selectSuggestion(file: TFile): void {
this.inputEl.value = this.strategy.selectSuggestion(file);
this.inputEl.trigger("input");
this.close();
}
}

19 changes: 12 additions & 7 deletions src/suggesters/suggestFromDataview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
import { App, TAbstractFile, TFolder } from "obsidian";
import { TextInputSuggest } from "./suggest";
import { ModalFormError } from "src/utils/Error";
import { ModalFormError, tryCatch } from "src/utils/Error";
import { log_error } from "src/utils/Log";

/**
* Offers suggestions based on a dataview query.
Expand All @@ -13,24 +14,28 @@ export class DataviewSuggest extends TextInputSuggest<string> {

constructor(
public inputEl: HTMLInputElement,
private dvQuery: string,
dvQuery: string,
protected app: App,
) {
super(app, inputEl);
this.sandboxedQuery = eval(`(function sandboxedQuery(dv, pages) { return ${dvQuery} })`)

this.sandboxedQuery = tryCatch(
() => eval(`(function sandboxedQuery(dv, pages) { return ${dvQuery} })`),
"Invalid dataview query"
)
}

getSuggestions(inputStr: string): string[] {
const dv = this.app.plugins.plugins.dataview?.api
if (!dv) {
throw new ModalFormError("Dataview plugin is not enabled")
log_error(new ModalFormError("Dataview plugin is not enabled"))
return [];
}
const result = this.sandboxedQuery(dv, dv.pages)
if (!Array.isArray(result)) {
throw new ModalFormError("The dataview query did not return an array")
log_error(new ModalFormError("The dataview query did not return an array"))
return [];
}
return result
return result.filter(r => r.toLowerCase().includes(inputStr.toLowerCase()))
}

renderSuggestion(option: string, el: HTMLElement): void {
Expand Down
13 changes: 11 additions & 2 deletions src/utils/Error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@ export async function errorWrapper<T>(
log_error(e);
}
return null;
}
}
}

export function errorWrapperSync<T>(fn: () => T, msg: string): T | null {
/**
* I case of error, logs it to the console and to the UI
* and returns null
* @export
* @template T
* @param {() => T} fn
* @param {string} msg
* @return {*} {(T | null)}
*/
export function tryCatch<T>(fn: () => T, msg: string): T | null {
try {
return fn();
} catch (e: any) {
Expand Down
11 changes: 4 additions & 7 deletions src/utils/Log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,15 @@ export function log_update(msg: string): void {
const notice = new Notice("", 15000);
// TODO: Find better way for this
// @ts-ignore
notice.noticeEl.innerHTML = `<b>Templater update</b>:<br/>${msg}`;
notice.noticeEl.innerHTML = `<b>Modal form update</b>:<br/>${msg}`;
}

export function log_error(e: Error | ModalFormError): void {
const notice = new Notice("", 8000);
if (e instanceof ModalFormError && e.console_msg) {
// TODO: Find a better way for this
// @ts-ignore
notice.noticeEl.innerHTML = `<b>Templater Error</b>:<br/>${e.message}<br/>Check console for more information`;
console.error(`Templater Error:`, e.message, "\n", e.console_msg);
notice.noticeEl.innerHTML = `<b>Modal form Error</b>:<br/>${e.message}<br/>Check console for more information`;
console.error(`Modal form Error:`, e.message, "\n", e.console_msg);
} else {
// @ts-ignore
notice.noticeEl.innerHTML = `<b>Templater Error</b>:<br/>${e.message}`;
notice.noticeEl.innerHTML = `<b>Modal form Error</b>:<br/>${e.message}`;
}
}

0 comments on commit 8202d37

Please sign in to comment.