Added autocomplete suggestions to the bibles path setting field. Cleaned up a few things.

This commit is contained in:
Caleb Campbell
2025-07-17 08:06:23 +10:00
parent 62e3498cab
commit 218ddbfea7
5 changed files with 73 additions and 22 deletions

2
package-lock.json generated
View File

@@ -6,7 +6,7 @@
"packages": { "packages": {
"": { "": {
"name": "local-bible-ref", "name": "local-bible-ref",
"version": "1.0.1", "version": "1.0.2",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "^16.11.6", "@types/node": "^16.11.6",

View File

@@ -1,9 +1,10 @@
import LocalBibleRefPlugin from 'main'; import LocalBibleRefPlugin from 'main';
import { App, Notice, PluginSettingTab, Setting } from 'obsidian'; import { App, Notice, PluginSettingTab, Setting } from 'obsidian';
import { PassageFormat } from './passage-reference'; import { PassageFormat } from './passage-reference';
import { PathSuggest } from './path-suggest';
export default class LocalBibleRefSettingTab extends PluginSettingTab { export default class LocalBibleRefSettingTab extends PluginSettingTab {
plugin: LocalBibleRefPlugin; private plugin: LocalBibleRefPlugin;
constructor(app: App, plugin: LocalBibleRefPlugin) { constructor(app: App, plugin: LocalBibleRefPlugin) {
super(app, plugin); super(app, plugin);
@@ -18,8 +19,8 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab {
new Setting(containerEl) new Setting(containerEl)
.setName('Bibles Path') .setName('Bibles Path')
.setDesc('The path to the folder containing your bibles.') .setDesc('The path to the folder containing your bibles.')
.addText(text => text .addText(text => {
.setPlaceholder('e.g. Data/Bibles') text.setPlaceholder('e.g. Data/Bibles')
.setValue(this.plugin.settings.biblesPath) .setValue(this.plugin.settings.biblesPath)
.onChange(async (value) => { .onChange(async (value) => {
this.plugin.settings.biblesPath = value; this.plugin.settings.biblesPath = value;
@@ -30,7 +31,10 @@ export default class LocalBibleRefSettingTab extends PluginSettingTab {
const exists = await this.app.vault.adapter.exists(value); const exists = await this.app.vault.adapter.exists(value);
if (!exists) new Notice(`Bibles folder doesn't exist at path: ${value}.`); if (!exists) new Notice(`Bibles folder doesn't exist at path: ${value}.`);
}, 1000); }, 1000);
})); });
new PathSuggest(this.app, text.inputEl);
});
let defaultVersionTimeout: NodeJS.Timeout; let defaultVersionTimeout: NodeJS.Timeout;
new Setting(containerEl) new Setting(containerEl)

View File

@@ -5,6 +5,8 @@ import {
EditorSuggest, EditorSuggest,
EditorSuggestContext, EditorSuggestContext,
EditorSuggestTriggerInfo, EditorSuggestTriggerInfo,
Notice,
TFile,
TFolder, TFolder,
} from "obsidian"; } from "obsidian";
import { PassageFormat, PassageReference } from "./passage-reference"; import { PassageFormat, PassageReference } from "./passage-reference";
@@ -12,6 +14,7 @@ import { LocalBibleRefSettings } from "./settings";
export class PassageSuggest extends EditorSuggest<PassageSuggestion> { export class PassageSuggest extends EditorSuggest<PassageSuggestion> {
private settings: LocalBibleRefSettings; private settings: LocalBibleRefSettings;
private noSettingsNotice: Notice;
constructor(app: App, settings: LocalBibleRefSettings) { constructor(app: App, settings: LocalBibleRefSettings) {
super(app); super(app);
@@ -21,15 +24,27 @@ export class PassageSuggest extends EditorSuggest<PassageSuggestion> {
onTrigger( onTrigger(
cursor: EditorPosition, cursor: EditorPosition,
editor: Editor, editor: Editor,
_: any _: TFile | null
): EditorSuggestTriggerInfo | null { ): EditorSuggestTriggerInfo | null {
// min ref length is 6 ('--gen1')
if (cursor.ch < 6) return null;
// line must start with '--' // line must start with '--'
const line = editor.getLine(cursor.line); const line = editor.getLine(cursor.line);
if (!line.startsWith("--")) return null; if (!line.startsWith("--")) return null;
// if no settings, alert user
if (!this.settings.biblesPath) {
if (!this.noSettingsNotice?.noticeEl.isShown()) {
const noticeText = "Local Bible Ref settings are not " +
"configured. Please set the bibles path before " +
"attempting to reference passages.";
this.noSettingsNotice = new Notice(noticeText);
}
return null;
}
// min ref length is 6 ('--gen1')
if (cursor.ch < 6) return null;
// must be a passage ref // must be a passage ref
const isPassage = PassageReference.regExp.test(line); const isPassage = PassageReference.regExp.test(line);
if (!isPassage) return null; if (!isPassage) return null;
@@ -48,9 +63,14 @@ export class PassageSuggest extends EditorSuggest<PassageSuggestion> {
async getSuggestions( async getSuggestions(
context: EditorSuggestContext context: EditorSuggestContext
): Promise<PassageSuggestion[]> { ): Promise<PassageSuggestion[]> {
let version = this.settings.defaultVersionShorthand;
if (!version) {
const folder = this.app.vault.getFolderByPath(this.settings.biblesPath);
version = folder?.children?.filter(c => c instanceof TFolder)?.first()?.name ?? '';
}
const passageRef = PassageReference.parse( const passageRef = PassageReference.parse(
context.query, context.query,
this.settings.defaultVersionShorthand, version,
this.settings.defaultPassageFormat, this.settings.defaultPassageFormat,
); );
if (!passageRef) return []; if (!passageRef) return [];
@@ -90,7 +110,7 @@ export class PassageSuggest extends EditorSuggest<PassageSuggestion> {
} }
renderSuggestion(item: PassageSuggestion, el: HTMLElement): void { renderSuggestion(item: PassageSuggestion, el: HTMLElement): void {
el.innerText = item.excerpt; el.setText(item.excerpt);
} }
selectSuggestion( selectSuggestion(

27
src/path-suggest.ts Normal file
View File

@@ -0,0 +1,27 @@
import { AbstractInputSuggest, App } from "obsidian";
export class PathSuggest extends AbstractInputSuggest<string> {
private textInputEl: HTMLInputElement | HTMLDivElement;
constructor(app: App, textInputEl: HTMLInputElement | HTMLDivElement) {
super(app, textInputEl);
this.textInputEl = textInputEl;
}
async getSuggestions(query: string): Promise<string[]> {
let searchPath = '';
if (await this.app.vault.adapter.exists(query)) searchPath = query;
let folders = (await this.app.vault.adapter.list(searchPath)).folders;
folders = folders.filter(folder => !folder.startsWith('.') && folder.startsWith(query));
return folders;
}
renderSuggestion(item: string, el: HTMLElement): void {
el.setText(item);
}
selectSuggestion(item: string, _: MouseEvent | KeyboardEvent): void {
this.setValue(item);
this.textInputEl.dispatchEvent(new Event('input'));
}
}