diff --git a/main.js b/main.js
index b5002fd1..ee3a2fd1 100644
--- a/main.js
+++ b/main.js
@@ -9664,6 +9664,7 @@ const DEFAULT_SETTINGS = {
dotsColour: "#000000",
dvWaitTime: 5000,
enableAlphaSort: true,
+ enableRelationSuggestor: false,
fieldSuggestor: true,
filterImpliedSiblingsOfDifferentTypes: false,
limitWriteBCCheckboxes: [],
@@ -9688,6 +9689,7 @@ const DEFAULT_SETTINGS = {
showNameOrType: true,
showRelationType: true,
regexNoteField: "",
+ relSuggestorTrigger: "\\",
rlLeaf: true,
showAllPathsIfNoneToIndexNote: false,
showAllAliases: true,
@@ -9834,6 +9836,10 @@ function strToRegex(input) {
console.log(e);
return null;
}
+}
+// Source: https://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+function escapeRegex(string) {
+ return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
}
/**
@@ -31438,19 +31444,17 @@ class FieldSuggestor extends obsidian.EditorSuggest {
}
onTrigger(cursor, editor, _) {
var _a;
- if (this.plugin.settings.fieldSuggestor) {
- const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
- const match = (_a = sub.match(/^BC-(.*)$/)) === null || _a === void 0 ? void 0 : _a[1];
- if (match !== undefined) {
- return {
- end: cursor,
- start: {
- ch: sub.lastIndexOf(match),
- line: cursor.line,
- },
- query: match,
- };
- }
+ const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
+ const match = (_a = sub.match(/^BC-(.*)$/)) === null || _a === void 0 ? void 0 : _a[1];
+ if (match !== undefined) {
+ return {
+ end: cursor,
+ start: {
+ ch: sub.lastIndexOf(match),
+ line: cursor.line,
+ },
+ query: match,
+ };
}
return null;
}
@@ -33398,6 +33402,49 @@ async function refreshIndex(plugin) {
new obsidian.Notice("Index refreshed");
}
+class RelationSuggestor extends obsidian.EditorSuggest {
+ constructor(plugin) {
+ super(plugin.app);
+ this.getSuggestions = (context) => {
+ const { query } = context;
+ const { userHiers } = this.plugin.settings;
+ return getFields(userHiers).filter((sug) => sug.includes(query));
+ };
+ this.plugin = plugin;
+ }
+ onTrigger(cursor, editor, _) {
+ var _a;
+ const trig = this.plugin.settings.relSuggestorTrigger;
+ const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
+ const regex = new RegExp(`.*?${escapeRegex(trig)}(.*)$`);
+ const match = (_a = regex.exec(sub)) === null || _a === void 0 ? void 0 : _a[1];
+ if (match === undefined)
+ return null;
+ return {
+ start: {
+ ch: sub.lastIndexOf(trig),
+ line: cursor.line,
+ },
+ end: cursor,
+ query: match,
+ };
+ }
+ renderSuggestion(suggestion, el) {
+ el.createDiv({
+ text: suggestion,
+ cls: "codeblock-suggestion",
+ });
+ }
+ selectSuggestion(suggestion) {
+ const { context } = this;
+ if (context) {
+ const trig = this.plugin.settings.relSuggestorTrigger;
+ const { start, end, editor } = context;
+ editor.replaceRange(suggestion + ":", { ch: start.ch + 1 - trig.length, line: start.line }, end);
+ }
+ }
+}
+
/* src\Components\KoFi.svelte generated by Svelte v3.35.0 */
function create_fragment$h(ctx) {
@@ -37488,6 +37535,22 @@ class BCSettingTab extends obsidian.PluginSettingTab {
settings.fieldSuggestor = value;
await plugin.saveSettings();
}));
+ new obsidian.Setting(alternativeHierarchyDetails)
+ .setName("Enable Relation Suggestor")
+ .setDesc(fragWithHTML("Enable an editor suggestor which gets triggered by a custom string to show a list of relations from your hierarchies to insert."))
+ .addToggle((toggle) => toggle
+ .setValue(settings.enableRelationSuggestor)
+ .onChange(async (value) => {
+ settings.enableRelationSuggestor = value;
+ await plugin.saveSettings();
+ }));
+ new obsidian.Setting(alternativeHierarchyDetails)
+ .setName("Relation Suggestor Trigger")
+ .setDesc(fragWithHTML("The string used to trigger the relation suggestor. Default is \\
."))
+ .addText((text) => text.setValue(settings.relSuggestorTrigger).onChange(async (value) => {
+ settings.relSuggestorTrigger = value;
+ await plugin.saveSettings();
+ }));
addTagNoteSettings(plugin, alternativeHierarchyDetails);
addRegexNoteSettings(plugin, alternativeHierarchyDetails);
addNoSystemSettings(plugin, alternativeHierarchyDetails);
@@ -61784,10 +61847,14 @@ class BCPlugin extends obsidian.Plugin {
console.log("loading breadcrumbs plugin");
const { app } = this;
await this.loadSettings();
- const { settings } = this;
this.addSettingTab(new BCSettingTab(app, this));
this.db = new Debugger(this);
- this.registerEditorSuggest(new FieldSuggestor(this));
+ const { settings } = this;
+ const { fieldSuggestor, enableRelationSuggestor } = settings;
+ if (fieldSuggestor)
+ this.registerEditorSuggest(new FieldSuggestor(this));
+ if (enableRelationSuggestor)
+ this.registerEditorSuggest(new RelationSuggestor(this));
const { openMatrixOnLoad, openStatsOnLoad, openDuckOnLoad, openDownOnLoad, showBCs, showBCsInEditLPMode, userHiers, } = settings;
this.VIEWS = [
{
diff --git a/src/FieldSuggestor.ts b/src/FieldSuggestor.ts
index 51e6ac5f..e88f8345 100644
--- a/src/FieldSuggestor.ts
+++ b/src/FieldSuggestor.ts
@@ -22,20 +22,19 @@ export class FieldSuggestor extends EditorSuggest {
editor: Editor,
_: TFile
): EditorSuggestTriggerInfo | null {
- if (this.plugin.settings.fieldSuggestor) {
- const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
- const match = sub.match(/^BC-(.*)$/)?.[1];
- if (match !== undefined) {
- return {
- end: cursor,
- start: {
- ch: sub.lastIndexOf(match),
- line: cursor.line,
- },
- query: match,
- };
- }
+ const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
+ const match = sub.match(/^BC-(.*)$/)?.[1];
+ if (match !== undefined) {
+ return {
+ end: cursor,
+ start: {
+ ch: sub.lastIndexOf(match),
+ line: cursor.line,
+ },
+ query: match,
+ };
}
+
return null;
}
diff --git a/src/RelationSuggestor.ts b/src/RelationSuggestor.ts
new file mode 100644
index 00000000..9a867e8b
--- /dev/null
+++ b/src/RelationSuggestor.ts
@@ -0,0 +1,68 @@
+import {
+ Editor,
+ EditorPosition,
+ EditorSuggest,
+ EditorSuggestContext,
+ EditorSuggestTriggerInfo,
+ TFile,
+} from "obsidian";
+import type BCPlugin from "./main";
+import { escapeRegex } from "./Utils/generalUtils";
+import { getFields } from "./Utils/HierUtils";
+
+export class RelationSuggestor extends EditorSuggest {
+ plugin: BCPlugin;
+
+ constructor(plugin: BCPlugin) {
+ super(plugin.app);
+ this.plugin = plugin;
+ }
+
+ onTrigger(
+ cursor: EditorPosition,
+ editor: Editor,
+ _: TFile
+ ): EditorSuggestTriggerInfo | null {
+ const trig = this.plugin.settings.relSuggestorTrigger;
+ const sub = editor.getLine(cursor.line).substring(0, cursor.ch);
+
+ const regex = new RegExp(`.*?${escapeRegex(trig)}(.*)$`);
+ const match = regex.exec(sub)?.[1];
+
+ if (match === undefined) return null;
+ return {
+ start: {
+ ch: sub.lastIndexOf(trig),
+ line: cursor.line,
+ },
+ end: cursor,
+ query: match,
+ };
+ }
+
+ getSuggestions = (context: EditorSuggestContext) => {
+ const { query } = context;
+ const { userHiers } = this.plugin.settings;
+ return getFields(userHiers).filter((sug) => sug.includes(query));
+ };
+
+ renderSuggestion(suggestion: string, el: HTMLElement): void {
+ el.createDiv({
+ text: suggestion,
+ cls: "codeblock-suggestion",
+ });
+ }
+
+ selectSuggestion(suggestion: string): void {
+ const { context } = this;
+ if (context) {
+ const trig = this.plugin.settings.relSuggestorTrigger;
+ const { start, end, editor } = context;
+ editor.replaceRange(
+ suggestion + ":",
+ { ch: start.ch + 1 - trig.length, line: start.line },
+ end
+ );
+ }
+ }
+}
diff --git a/src/Settings/BreadcrumbsSettingTab.ts b/src/Settings/BreadcrumbsSettingTab.ts
index eaa4f1a3..e54f837b 100644
--- a/src/Settings/BreadcrumbsSettingTab.ts
+++ b/src/Settings/BreadcrumbsSettingTab.ts
@@ -77,6 +77,34 @@ export class BCSettingTab extends PluginSettingTab {
await plugin.saveSettings();
})
);
+ new Setting(alternativeHierarchyDetails)
+ .setName("Enable Relation Suggestor")
+ .setDesc(
+ fragWithHTML(
+ "Enable an editor suggestor which gets triggered by a custom string to show a list of relations from your hierarchies to insert."
+ )
+ )
+ .addToggle((toggle) =>
+ toggle
+ .setValue(settings.enableRelationSuggestor)
+ .onChange(async (value) => {
+ settings.enableRelationSuggestor = value;
+ await plugin.saveSettings();
+ })
+ );
+ new Setting(alternativeHierarchyDetails)
+ .setName("Relation Suggestor Trigger")
+ .setDesc(
+ fragWithHTML(
+ "The string used to trigger the relation suggestor. Default is \\
."
+ )
+ )
+ .addText((text) =>
+ text.setValue(settings.relSuggestorTrigger).onChange(async (value) => {
+ settings.relSuggestorTrigger = value;
+ await plugin.saveSettings();
+ })
+ );
addTagNoteSettings(plugin, alternativeHierarchyDetails);
addRegexNoteSettings(plugin, alternativeHierarchyDetails);
diff --git a/src/Utils/generalUtils.ts b/src/Utils/generalUtils.ts
index 892d8afc..5a53b1ba 100644
--- a/src/Utils/generalUtils.ts
+++ b/src/Utils/generalUtils.ts
@@ -1,5 +1,3 @@
-import type { App } from "obsidian";
-import { isInVault } from "obsidian-community-lib";
import { dropHeaderOrAlias, regNFlags, splitLinksRegex } from "../constants";
import type { BCSettings } from "../interfaces";
@@ -176,3 +174,8 @@ export function strToRegex(input: string) {
return null;
}
}
+
+// Source: https://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+export function escapeRegex(string) {
+ return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
+}
diff --git a/src/constants.ts b/src/constants.ts
index b414f991..e5d185bc 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -252,6 +252,7 @@ export const DEFAULT_SETTINGS: BCSettings = {
dotsColour: "#000000",
dvWaitTime: 5000,
enableAlphaSort: true,
+ enableRelationSuggestor: false,
fieldSuggestor: true,
filterImpliedSiblingsOfDifferentTypes: false,
limitWriteBCCheckboxes: [],
@@ -278,6 +279,7 @@ export const DEFAULT_SETTINGS: BCSettings = {
showNameOrType: true,
showRelationType: true,
regexNoteField: "",
+ relSuggestorTrigger: "\\",
rlLeaf: true,
showAllPathsIfNoneToIndexNote: false,
showAllAliases: true,
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 48d22c90..0e06e6f6 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -28,6 +28,7 @@ export interface BCSettings {
downViewWrap: boolean;
dotsColour: string;
enableAlphaSort: boolean;
+ enableRelationSuggestor: boolean;
fieldSuggestor: boolean;
filterImpliedSiblingsOfDifferentTypes: boolean;
gridDots: boolean;
@@ -76,6 +77,7 @@ export interface BCSettings {
showWriteAllBCsCmd: boolean;
sortByNameShowAlias: boolean;
regexNoteField: string;
+ relSuggestorTrigger: string;
rlLeaf: boolean;
showBCs: boolean;
showBCsInEditLPMode: boolean;
diff --git a/src/main.ts b/src/main.ts
index 937f2e3d..01f335ee 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -26,6 +26,7 @@ import {
import { FieldSuggestor } from "./FieldSuggestor";
import type { BCSettings, Directions, MyView, ViewInfo } from "./interfaces";
import { buildClosedG, buildMainG, refreshIndex } from "./refreshIndex";
+import { RelationSuggestor } from "./RelationSuggestor";
import { BCSettingTab } from "./Settings/BreadcrumbsSettingTab";
import { getFields } from "./Utils/HierUtils";
import { waitForCache } from "./Utils/ObsidianUtils";
@@ -73,11 +74,16 @@ export default class BCPlugin extends Plugin {
const { app } = this;
await this.loadSettings();
- const { settings } = this;
this.addSettingTab(new BCSettingTab(app, this));
this.db = new Debugger(this);
- this.registerEditorSuggest(new FieldSuggestor(this));
+
+ const { settings } = this;
+ const { fieldSuggestor, enableRelationSuggestor } = settings;
+
+ if (fieldSuggestor) this.registerEditorSuggest(new FieldSuggestor(this));
+ if (enableRelationSuggestor)
+ this.registerEditorSuggest(new RelationSuggestor(this));
const {
openMatrixOnLoad,