From 768e874185a6d4109c22c159a25ccb2f50529270 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 17:03:50 -0300 Subject: [PATCH 1/6] Load obsidian plugin even if fail to connect to backend but show warning - Previously the plugin would not load if cannot connect to Khoj backend - Silently failing to load with no reason provided is not helpful - Load plugin to allow user to fix the Khoj URL in their plugin setting - Show reason for khoj plugin not working. More helpful than failing silently --- src/interface/obsidian/src/utils.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/interface/obsidian/src/utils.ts b/src/interface/obsidian/src/utils.ts index d46a58dd..02ea6349 100644 --- a/src/interface/obsidian/src/utils.ts +++ b/src/interface/obsidian/src/utils.ts @@ -13,16 +13,23 @@ export async function configureKhojBackend(setting: KhojSetting) { let mdInVault = `${setting.obsidianVaultPath}/**/*.md`; let khojConfigUrl = `${setting.khojUrl}/api/config/data`; - // Load khoj app config from backend API, Update Markdown config and save - let khoj_configured = await request(khojConfigUrl) - .then(response => response !== "null"); + // Check if khoj backend is configured, show error if backend is not running + let khoj_already_configured = await request(khojConfigUrl) + .then(response => { + return response !== "null" + }) + .catch(error => { + new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the Khoj plugin settings.\n\n${error}`); + }) + // Short-circuit configuring khoj if unable to connect to khoj backend + if (khoj_already_configured === null) return; // Get current config if khoj backend configured, else get default config from khoj backend - await request(khoj_configured ? khojConfigUrl : `${khojConfigUrl}/default`) + await request(khoj_already_configured ? khojConfigUrl : `${khojConfigUrl}/default`) .then(response => JSON.parse(response)) .then(data => { // If khoj backend not configured yet - if (!khoj_configured) { + if (!khoj_already_configured) { // Create khoj content-type config with only markdown configured let khojObsidianPluginPath = `${setting.obsidianVaultPath}/${this.app.vault.configDir}/plugins/khoj/`; data["content-type"] = { @@ -70,9 +77,10 @@ export async function configureKhojBackend(setting: KhojSetting) { updateKhojBackend(setting.khojUrl, data); console.log(`Khoj: Updated markdown config in khoj backend config:\n${JSON.stringify(data["content-type"]["markdown"])}`) } + new Notice(`✅ Successfully Setup Khoj`); }) .catch(error => { - new Notice(`Ensure Khoj backend is running and Khoj URL is correct in the Khoj plugin settings.\nError: ${error}`); + new Notice(`❗️Failed to configure Khoj backend. Contact developer on Github. \n\nError: ${error}`); }) } From f046a95f3d9b9f842be1ea60b46c53fcb85d36e3 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 17:11:56 -0300 Subject: [PATCH 2/6] Track connectedToBackend as a setting. Use it across obsidian plugin - Display warning at top of khoj obsidian plugin settings - Make search command available only if connected to backend - Show warning notice on clicking khoj search ribbon button - Call saveData after configureKhojBackend to ensure connnectedToBackend setting saved after being (potentially) updated in configureKhojBackend function --- src/interface/obsidian/src/main.ts | 18 +++++++++++------- src/interface/obsidian/src/settings.ts | 11 ++++++++++- src/interface/obsidian/src/utils.ts | 6 ++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/interface/obsidian/src/main.ts b/src/interface/obsidian/src/main.ts index f8cf621f..23082895 100644 --- a/src/interface/obsidian/src/main.ts +++ b/src/interface/obsidian/src/main.ts @@ -1,4 +1,4 @@ -import { Plugin } from 'obsidian'; +import { Notice, Plugin } from 'obsidian'; import { KhojSetting, KhojSettingTab, DEFAULT_SETTINGS } from 'src/settings' import { KhojModal } from 'src/modal' import { configureKhojBackend } from './utils'; @@ -14,18 +14,22 @@ export default class Khoj extends Plugin { this.addCommand({ id: 'search', name: 'Search', - callback: () => { - new KhojModal(this.app, this.settings).open(); + checkCallback: (checking) => { + if (!checking && this.settings.connectedToBackend) + new KhojModal(this.app, this.settings).open(); + return this.settings.connectedToBackend; } }); // Create an icon in the left ribbon. this.addRibbonIcon('search', 'Khoj', (_: MouseEvent) => { // Called when the user clicks the icon. - new KhojModal(this.app, this.settings).open(); + this.settings.connectedToBackend + ? new KhojModal(this.app, this.settings).open() + : new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings`); }); - // Add a settings tab so the user can configure various aspects of the plugin + // Add a settings tab so the user can configure khoj this.addSettingTab(new KhojSettingTab(this.app, this)); } @@ -41,7 +45,7 @@ export default class Khoj extends Plugin { } async saveSettings() { - await this.saveData(this.settings) - .then(() => configureKhojBackend(this.settings)); + await configureKhojBackend(this.settings) + .then(() => this.saveData(this.settings)); } } diff --git a/src/interface/obsidian/src/settings.ts b/src/interface/obsidian/src/settings.ts index 941c8b4d..e719ed8b 100644 --- a/src/interface/obsidian/src/settings.ts +++ b/src/interface/obsidian/src/settings.ts @@ -6,12 +6,14 @@ export interface KhojSetting { resultsCount: number; khojUrl: string; obsidianVaultPath: string; + connectedToBackend: boolean; } export const DEFAULT_SETTINGS: KhojSetting = { resultsCount: 6, khojUrl: 'http://localhost:8000', - obsidianVaultPath: getVaultAbsolutePath() + obsidianVaultPath: getVaultAbsolutePath(), + connectedToBackend: false, } export class KhojSettingTab extends PluginSettingTab { @@ -25,6 +27,13 @@ export class KhojSettingTab extends PluginSettingTab { display(): void { const { containerEl } = this; containerEl.empty(); + + // Add notice if unable to connect to khoj backend + if (!this.plugin.settings.connectedToBackend) { + containerEl.createEl('small', { text: '❗Ensure Khoj backend is running and Khoj URL is correctly set below' }); + } + + // Add khoj settings configurable from the plugin settings tab new Setting(containerEl) .setName('Vault Paths') .setDesc('The Obsidian Vault to search with Khoj') diff --git a/src/interface/obsidian/src/utils.ts b/src/interface/obsidian/src/utils.ts index 02ea6349..0cc67faa 100644 --- a/src/interface/obsidian/src/utils.ts +++ b/src/interface/obsidian/src/utils.ts @@ -16,13 +16,15 @@ export async function configureKhojBackend(setting: KhojSetting) { // Check if khoj backend is configured, show error if backend is not running let khoj_already_configured = await request(khojConfigUrl) .then(response => { + setting.connectedToBackend = true; return response !== "null" }) .catch(error => { - new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the Khoj plugin settings.\n\n${error}`); + setting.connectedToBackend = false; + new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings.\n\n${error}`); }) // Short-circuit configuring khoj if unable to connect to khoj backend - if (khoj_already_configured === null) return; + if (!setting.connectedToBackend) return; // Get current config if khoj backend configured, else get default config from khoj backend await request(khoj_already_configured ? khojConfigUrl : `${khojConfigUrl}/default`) From 7991ab7a86a4f817812b7c756bf4308ef60d300a Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 19:49:12 -0300 Subject: [PATCH 3/6] Add button in Obsidian plugin settings to force re-indexing your vault --- src/interface/obsidian/src/settings.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/interface/obsidian/src/settings.ts b/src/interface/obsidian/src/settings.ts index e719ed8b..d502d962 100644 --- a/src/interface/obsidian/src/settings.ts +++ b/src/interface/obsidian/src/settings.ts @@ -1,4 +1,4 @@ -import { App, PluginSettingTab, Setting } from 'obsidian'; +import { App, PluginSettingTab, request, Setting } from 'obsidian'; import Khoj from 'src/main'; import { getVaultAbsolutePath } from 'src/utils'; @@ -35,7 +35,7 @@ export class KhojSettingTab extends PluginSettingTab { // Add khoj settings configurable from the plugin settings tab new Setting(containerEl) - .setName('Vault Paths') + .setName('Vault Path') .setDesc('The Obsidian Vault to search with Khoj') .addText(text => text .setValue(`${this.plugin.settings.obsidianVaultPath}`) @@ -53,7 +53,7 @@ export class KhojSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })); new Setting(containerEl) - .setName('Number of Results') + .setName('Results Count') .setDesc('The number of search results to show') .addText(text => text .setPlaceholder('6') @@ -62,5 +62,14 @@ export class KhojSettingTab extends PluginSettingTab { this.plugin.settings.resultsCount = parseInt(value); await this.plugin.saveSettings(); })); + new Setting(containerEl) + .setName('Index Vault') + .setDesc('Manually force Khoj to re-index your Obsidian Vault') + .addButton(button => button + .setButtonText('Update') + .onClick(async () => { + await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`); + } + )); } } From b52cd85c76769e82f0d0eb3857cfec63536fe9e3 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 21:59:38 -0300 Subject: [PATCH 4/6] Allow Reranking Results using Keybinding from Khoj Search Modal --- src/interface/obsidian/src/modal.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index c9eeadde..7653c2bf 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -9,15 +9,29 @@ export interface SearchResult { export class KhojModal extends SuggestModal { setting: KhojSetting; + rerank: boolean; constructor(app: App, setting: KhojSetting) { super(app); this.setting = setting; + this.rerank = false; + + // Register Modal Keybindings to Rerank Results + this.scope.register(['Mod'], 'Enter', async () => { + this.rerank = true + let results = await this.getSuggestions(this.inputEl.value); + + this.resultContainerEl.empty(); + results.forEach((result) => { + this.renderSuggestion(result, this.resultContainerEl); + }); + this.rerank = false + }); } async getSuggestions(query: string): Promise { // Query Khoj backend for search results - var searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&t=markdown` + var searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown` var results = await request(searchUrl) .then(response => JSON.parse(response)) .then(data => { From 580f4aca230ff5781b45d0c0ed19fc58f77ea136 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 22:01:54 -0300 Subject: [PATCH 5/6] Add hints to Modal for available Keybindings --- src/interface/obsidian/src/modal.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index 7653c2bf..b72a0d30 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -1,4 +1,4 @@ -import { App, SuggestModal, Notice, request, MarkdownRenderer } from 'obsidian'; +import { App, SuggestModal, Notice, request, MarkdownRenderer, Instruction, Platform } from 'obsidian'; import { KhojSetting } from 'src/settings'; import { getVaultAbsolutePath } from 'src/utils'; @@ -27,6 +27,27 @@ export class KhojModal extends SuggestModal { }); this.rerank = false }); + + // Add Hints to Modal for available Keybindings + const modalInstructions: Instruction[] = [ + { + command: '↑↓', + purpose: 'to navigate', + }, + { + command: '↵', + purpose: 'to open', + }, + { + command: Platform.isMacOS ? 'cmd ↵': 'ctrl ↵', + purpose: 'to rerank', + }, + { + command: 'esc', + purpose: 'to dismiss', + }, + ] + this.setInstructions(modalInstructions); } async getSuggestions(query: string): Promise { From da49ea272c6abc9ab898785bb48930e59b9776e6 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Tue, 10 Jan 2023 22:50:11 -0300 Subject: [PATCH 6/6] Add placeholder text to modal in Khoj Obsidian plugin --- src/interface/obsidian/src/modal.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index b72a0d30..af4455a6 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -48,12 +48,15 @@ export class KhojModal extends SuggestModal { }, ] this.setInstructions(modalInstructions); + + // Set Placeholder Text for Modal + this.setPlaceholder('Search with Khoj...'); } async getSuggestions(query: string): Promise { // Query Khoj backend for search results - var searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown` - var results = await request(searchUrl) + let searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown` + let results = await request(searchUrl) .then(response => JSON.parse(response)) .then(data => { return data.map((result: any) => {