Resolve Khoj Obsidian Plugin feedback

### Details
- b415f87 Split find and jump to notes code in `onChooseSuggestion' method
- 37063f6 Truncate query to 8k chars for find similar notes from Obsidian plugin
- 4456cf5 No need to use `then' or `finally' in `async' functions after an `await'
- 4070be6 Pass app object from plugin instance to child objects and functions
- c203c6a Use Sentence case for Find similar mote Obsidian command name
This commit is contained in:
Debanjum
2023-01-26 18:54:33 -03:00
committed by GitHub
4 changed files with 39 additions and 36 deletions

View File

@@ -24,7 +24,7 @@ export default class Khoj extends Plugin {
// Add similar notes command. It can only be triggered from the editor // Add similar notes command. It can only be triggered from the editor
this.addCommand({ this.addCommand({
id: 'similar', id: 'similar',
name: 'Find Similar Notes', name: 'Find similar notes',
editorCheckCallback: (checking) => { editorCheckCallback: (checking) => {
if (!checking && this.settings.connectedToBackend) if (!checking && this.settings.connectedToBackend)
new KhojModal(this.app, this.settings, true).open(); new KhojModal(this.app, this.settings, true).open();
@@ -49,11 +49,11 @@ export default class Khoj extends Plugin {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
// Load, configure khoj server settings // Load, configure khoj server settings
await configureKhojBackend(this.settings); await configureKhojBackend(this.app.vault, this.settings);
} }
async saveSettings() { async saveSettings() {
await configureKhojBackend(this.settings, false) await configureKhojBackend(this.app.vault, this.settings, false)
.then(() => this.saveData(this.settings)); .then(() => this.saveData(this.settings));
} }
} }

View File

@@ -10,9 +10,11 @@ export class KhojModal extends SuggestModal<SearchResult> {
setting: KhojSetting; setting: KhojSetting;
rerank: boolean = false; rerank: boolean = false;
find_similar_notes: boolean; find_similar_notes: boolean;
app: App;
constructor(app: App, setting: KhojSetting, find_similar_notes: boolean = false) { constructor(app: App, setting: KhojSetting, find_similar_notes: boolean = false) {
super(app); super(app);
this.app = app;
this.setting = setting; this.setting = setting;
this.find_similar_notes = find_similar_notes; this.find_similar_notes = find_similar_notes;
@@ -61,8 +63,9 @@ export class KhojModal extends SuggestModal<SearchResult> {
if (file && file.extension === 'md') { if (file && file.extension === 'md') {
// Enable rerank of search results // Enable rerank of search results
this.rerank = true this.rerank = true
// Set contents of active markdown file to input element // Set input element to contents of active markdown file
this.inputEl.value = await this.app.vault.read(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 // Trigger search to get and render similar notes from khoj backend
this.inputEl.dispatchEvent(new Event('input')); this.inputEl.dispatchEvent(new Event('input'));
this.rerank = false this.rerank = false
@@ -76,12 +79,12 @@ export class KhojModal extends SuggestModal<SearchResult> {
async getSuggestions(query: string): Promise<SearchResult[]> { async getSuggestions(query: string): Promise<SearchResult[]> {
// Query Khoj backend for search results // Query Khoj backend for search results
let encodedQuery = encodeURIComponent(query); let encodedQuery = encodeURIComponent(query);
let searchUrl = `${this.setting.khojUrl}/api/search?q=${encodedQuery}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown` let searchUrl = `${this.setting.khojUrl}/api/search?q=${encodedQuery}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown`;
let results = await request(searchUrl) let response = await request(searchUrl);
.then(response => JSON.parse(response)) let data = JSON.parse(response);
.then(data => data let results = data
.filter((result: any) => !this.find_similar_notes || !result.additional.file.endsWith(this.app.workspace.getActiveFile()?.path)) .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; })); .map((result: any) => { return { entry: result.entry, file: result.additional.file } as SearchResult; });
return results; return results;
} }
@@ -98,21 +101,21 @@ export class KhojModal extends SuggestModal<SearchResult> {
// Get all markdown files in vault // Get all markdown files in vault
const mdFiles = this.app.vault.getMarkdownFiles(); const mdFiles = this.app.vault.getMarkdownFiles();
// Find the vault file matching file of result. Open file at result heading // Find the vault file matching file of chosen search result
mdFiles let file_match = mdFiles
// Sort by descending length of path // Sort by descending length of path
// This finds longest path match when multiple files have same name // This finds longest path match when multiple files have same name
.sort((a, b) => b.path.length - a.path.length) .sort((a, b) => b.path.length - a.path.length)
.forEach((file) => { // The first match is the best file match across OS
// Find best file match across operating systems // e.g Khoj server on Linux, Obsidian vault on Android
// E.g Khoj Server on Linux, Obsidian Vault on Android .find(file => result.file.endsWith(file.path))
if (result.file.endsWith(file.path)) {
let resultHeading = result.entry.split('\n', 1)[0]; // Open vault file at heading of chosen search result
let linkToEntry = `${file.path}${resultHeading}` if (file_match){
this.app.workspace.openLinkText(linkToEntry, ''); let resultHeading = result.entry.split('\n', 1)[0];
console.log(`Link: ${linkToEntry}, File: ${file.path}, Heading: ${resultHeading}`); let linkToEntry = `${file_match.path}${resultHeading}`
return this.app.workspace.openLinkText(linkToEntry, '');
} console.log(`Link: ${linkToEntry}, File: ${file_match.path}, Heading: ${resultHeading}`);
}); }
} }
} }

View File

@@ -36,8 +36,8 @@ export class KhojSettingTab extends PluginSettingTab {
.setValue(`${this.plugin.settings.khojUrl}`) .setValue(`${this.plugin.settings.khojUrl}`)
.onChange(async (value) => { .onChange(async (value) => {
this.plugin.settings.khojUrl = value.trim(); this.plugin.settings.khojUrl = value.trim();
await this.plugin.saveSettings() await this.plugin.saveSettings();
.finally(() => containerEl.firstElementChild?.setText(this.getBackendStatusMessage())); containerEl.firstElementChild?.setText(this.getBackendStatusMessage());
})); }));
new Setting(containerEl) new Setting(containerEl)
.setName('Results Count') .setName('Results Count')
@@ -60,15 +60,15 @@ export class KhojSettingTab extends PluginSettingTab {
.onClick(async () => { .onClick(async () => {
// Disable button while updating index // Disable button while updating index
button.setButtonText('Updating...'); button.setButtonText('Updating...');
button.removeCta() button.removeCta();
indexVaultSetting = indexVaultSetting.setDisabled(true); indexVaultSetting = indexVaultSetting.setDisabled(true);
await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`) await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`);
.then(() => new Notice('✅ Updated Khoj index.')); new Notice('✅ Updated Khoj index.');
// Re-enable button once index is updated // Re-enable button once index is updated
button.setButtonText('Update'); button.setButtonText('Update');
button.setCta() button.setCta();
indexVaultSetting = indexVaultSetting.setDisabled(false); indexVaultSetting = indexVaultSetting.setDisabled(false);
}) })
); );

View File

@@ -1,16 +1,16 @@
import { FileSystemAdapter, Notice, RequestUrlParam, request } from 'obsidian'; import { FileSystemAdapter, Notice, RequestUrlParam, request, Vault } from 'obsidian';
import { KhojSetting } from 'src/settings' import { KhojSetting } from 'src/settings'
export function getVaultAbsolutePath(): string { export function getVaultAbsolutePath(vault: Vault): string {
let adaptor = this.app.vault.adapter; let adaptor = vault.adapter;
if (adaptor instanceof FileSystemAdapter) { if (adaptor instanceof FileSystemAdapter) {
return adaptor.getBasePath(); return adaptor.getBasePath();
} }
return ''; return '';
} }
export async function configureKhojBackend(setting: KhojSetting, notify: boolean = true) { export async function configureKhojBackend(vault: Vault, setting: KhojSetting, notify: boolean = true) {
let mdInVault = `${getVaultAbsolutePath()}/**/*.md`; let mdInVault = `${getVaultAbsolutePath(vault)}/**/*.md`;
let khojConfigUrl = `${setting.khojUrl}/api/config/data`; let khojConfigUrl = `${setting.khojUrl}/api/config/data`;
// Check if khoj backend is configured, note if cannot connect to backend // 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; if (!setting.connectedToBackend) return;
// Set index name from the path of the current vault // 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 // Get default index directory from khoj backend
let khojDefaultIndexDirectory = await request(`${khojConfigUrl}/default`) let khojDefaultIndexDirectory = await request(`${khojConfigUrl}/default`)
.then(response => JSON.parse(response)) .then(response => JSON.parse(response))