From c203c6a3fd9e74dcea4614c5e2b2e67ae93727fe Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 26 Jan 2023 16:57:37 -0300 Subject: [PATCH 1/5] Use Sentence case for Find Similar Note command name in Khoj Obsidian --- src/interface/obsidian/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/obsidian/src/main.ts b/src/interface/obsidian/src/main.ts index 1adc1eff..a400da76 100644 --- a/src/interface/obsidian/src/main.ts +++ b/src/interface/obsidian/src/main.ts @@ -24,7 +24,7 @@ export default class Khoj extends Plugin { // Add similar notes command. It can only be triggered from the editor this.addCommand({ id: 'similar', - name: 'Find Similar Notes', + name: 'Find similar notes', editorCheckCallback: (checking) => { if (!checking && this.settings.connectedToBackend) new KhojModal(this.app, this.settings, true).open(); From 4070be637c61038607d088322db5106315f30800 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 26 Jan 2023 16:58:51 -0300 Subject: [PATCH 2/5] Pass app object from plugin instance to child objects and functions Do not reference global app object from child objects and funcs directly. It is only available for debugging purposes and access to it maybe dropped in the future. --- src/interface/obsidian/src/main.ts | 4 ++-- src/interface/obsidian/src/modal.ts | 2 ++ src/interface/obsidian/src/utils.ts | 12 ++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/interface/obsidian/src/main.ts b/src/interface/obsidian/src/main.ts index a400da76..f5992061 100644 --- a/src/interface/obsidian/src/main.ts +++ b/src/interface/obsidian/src/main.ts @@ -49,11 +49,11 @@ export default class Khoj extends Plugin { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); // Load, configure khoj server settings - await configureKhojBackend(this.settings); + await configureKhojBackend(this.app.vault, this.settings); } async saveSettings() { - await configureKhojBackend(this.settings, false) + await configureKhojBackend(this.app.vault, this.settings, false) .then(() => this.saveData(this.settings)); } } diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index d44da44a..f0ded644 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -10,9 +10,11 @@ export class KhojModal extends SuggestModal { setting: KhojSetting; rerank: boolean = false; find_similar_notes: boolean; + app: App; constructor(app: App, setting: KhojSetting, find_similar_notes: boolean = false) { super(app); + this.app = app; this.setting = setting; this.find_similar_notes = find_similar_notes; diff --git a/src/interface/obsidian/src/utils.ts b/src/interface/obsidian/src/utils.ts index bc3ec598..b8142f6d 100644 --- a/src/interface/obsidian/src/utils.ts +++ b/src/interface/obsidian/src/utils.ts @@ -1,16 +1,16 @@ -import { FileSystemAdapter, Notice, RequestUrlParam, request } from 'obsidian'; +import { FileSystemAdapter, Notice, RequestUrlParam, request, Vault } from 'obsidian'; import { KhojSetting } from 'src/settings' -export function getVaultAbsolutePath(): string { - let adaptor = this.app.vault.adapter; +export function getVaultAbsolutePath(vault: Vault): string { + let adaptor = vault.adapter; if (adaptor instanceof FileSystemAdapter) { return adaptor.getBasePath(); } return ''; } -export async function configureKhojBackend(setting: KhojSetting, notify: boolean = true) { - let mdInVault = `${getVaultAbsolutePath()}/**/*.md`; +export async function configureKhojBackend(vault: Vault, setting: KhojSetting, notify: boolean = true) { + let mdInVault = `${getVaultAbsolutePath(vault)}/**/*.md`; let khojConfigUrl = `${setting.khojUrl}/api/config/data`; // Check if khoj backend is configured, note if cannot connect to backend @@ -28,7 +28,7 @@ export async function configureKhojBackend(setting: KhojSetting, notify: boolean if (!setting.connectedToBackend) return; // Set index name from the path of the current vault - let indexName = getVaultAbsolutePath().replace(/\//g, '_').replace(/ /g, '_'); + let indexName = getVaultAbsolutePath(vault).replace(/\//g, '_').replace(/ /g, '_'); // Get default index directory from khoj backend let khojDefaultIndexDirectory = await request(`${khojConfigUrl}/default`) .then(response => JSON.parse(response)) From 4456cf5c8fe6e9a3ddcf8aa10d80df8ab931132b Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 26 Jan 2023 17:05:53 -0300 Subject: [PATCH 3/5] No need to use then or finally in async functions after an await --- src/interface/obsidian/src/modal.ts | 12 ++++++------ src/interface/obsidian/src/settings.ts | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index f0ded644..6d21a4f6 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -78,12 +78,12 @@ export class KhojModal extends SuggestModal { async getSuggestions(query: string): Promise { // Query Khoj backend for search results let encodedQuery = encodeURIComponent(query); - let searchUrl = `${this.setting.khojUrl}/api/search?q=${encodedQuery}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown` - let results = await request(searchUrl) - .then(response => JSON.parse(response)) - .then(data => data - .filter((result: any) => !this.find_similar_notes || !result.additional.file.endsWith(this.app.workspace.getActiveFile()?.path)) - .map((result: any) => { return { entry: result.entry, file: result.additional.file } as SearchResult; })); + let searchUrl = `${this.setting.khojUrl}/api/search?q=${encodedQuery}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown`; + let response = await request(searchUrl); + let data = JSON.parse(response); + let results = data + .filter((result: any) => !this.find_similar_notes || !result.additional.file.endsWith(this.app.workspace.getActiveFile()?.path)) + .map((result: any) => { return { entry: result.entry, file: result.additional.file } as SearchResult; }); return results; } diff --git a/src/interface/obsidian/src/settings.ts b/src/interface/obsidian/src/settings.ts index edfbb123..ce4f50f4 100644 --- a/src/interface/obsidian/src/settings.ts +++ b/src/interface/obsidian/src/settings.ts @@ -36,8 +36,8 @@ export class KhojSettingTab extends PluginSettingTab { .setValue(`${this.plugin.settings.khojUrl}`) .onChange(async (value) => { this.plugin.settings.khojUrl = value.trim(); - await this.plugin.saveSettings() - .finally(() => containerEl.firstElementChild?.setText(this.getBackendStatusMessage())); + await this.plugin.saveSettings(); + containerEl.firstElementChild?.setText(this.getBackendStatusMessage()); })); new Setting(containerEl) .setName('Results Count') @@ -60,15 +60,15 @@ export class KhojSettingTab extends PluginSettingTab { .onClick(async () => { // Disable button while updating index button.setButtonText('Updating...'); - button.removeCta() + button.removeCta(); indexVaultSetting = indexVaultSetting.setDisabled(true); - await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`) - .then(() => new Notice('✅ Updated Khoj index.')); + await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`); + new Notice('✅ Updated Khoj index.'); // Re-enable button once index is updated button.setButtonText('Update'); - button.setCta() + button.setCta(); indexVaultSetting = indexVaultSetting.setDisabled(false); }) ); From 37063f6a38e0959f7c7465cf05e010ba1d8511a5 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 26 Jan 2023 17:41:14 -0300 Subject: [PATCH 4/5] Truncate query to 8k chars for find similar notes from obsidian plugin Truncate current file data passed to khoj backend API via query string below default query size supported by popular servers --- src/interface/obsidian/src/modal.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index 6d21a4f6..f1c9ef7c 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -63,8 +63,9 @@ export class KhojModal extends SuggestModal { if (file && file.extension === 'md') { // Enable rerank of search results this.rerank = true - // Set contents of active markdown file to input element - this.inputEl.value = await this.app.vault.read(file); + // Set input element to contents of active markdown file + // truncate to first 8,000 characters to avoid hitting query size limits + this.inputEl.value = await this.app.vault.read(file).then(file_str => file_str.slice(0, 8000)); // Trigger search to get and render similar notes from khoj backend this.inputEl.dispatchEvent(new Event('input')); this.rerank = false From b415f87093364279606d388c104de808b8927693 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 26 Jan 2023 17:51:11 -0300 Subject: [PATCH 5/5] Split code in onChooseSuggestion method to make it more readable Split find file, jump to file code to make onChooseSuggestion more readable - Use find, instead of using return in forEach to get first match - Move the jump to file+heading code out from forEach --- src/interface/obsidian/src/modal.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/interface/obsidian/src/modal.ts b/src/interface/obsidian/src/modal.ts index f1c9ef7c..0e46c047 100644 --- a/src/interface/obsidian/src/modal.ts +++ b/src/interface/obsidian/src/modal.ts @@ -101,21 +101,21 @@ export class KhojModal extends SuggestModal { // Get all markdown files in vault const mdFiles = this.app.vault.getMarkdownFiles(); - // Find the vault file matching file of result. Open file at result heading - mdFiles + // Find the vault file matching file of chosen search result + let file_match = mdFiles // Sort by descending length of path // This finds longest path match when multiple files have same name .sort((a, b) => b.path.length - a.path.length) - .forEach((file) => { - // Find best file match across operating systems - // E.g Khoj Server on Linux, Obsidian Vault on Android - if (result.file.endsWith(file.path)) { - let resultHeading = result.entry.split('\n', 1)[0]; - let linkToEntry = `${file.path}${resultHeading}` - this.app.workspace.openLinkText(linkToEntry, ''); - console.log(`Link: ${linkToEntry}, File: ${file.path}, Heading: ${resultHeading}`); - return - } - }); + // The first match is the best file match across OS + // e.g Khoj server on Linux, Obsidian vault on Android + .find(file => result.file.endsWith(file.path)) + + // Open vault file at heading of chosen search result + if (file_match){ + let resultHeading = result.entry.split('\n', 1)[0]; + let linkToEntry = `${file_match.path}${resultHeading}` + this.app.workspace.openLinkText(linkToEntry, ''); + console.log(`Link: ${linkToEntry}, File: ${file_match.path}, Heading: ${resultHeading}`); + } } }