MCPcopy
hub / github.com/callumalpass/tasknotes / NLPSuggest

Class NLPSuggest

src/modals/taskCreationSuggest.ts:47–606  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

45}
46
47export class NLPSuggest extends AbstractInputSuggest<
48 TagSuggestion | ContextSuggestion | ProjectSuggestion | StatusSuggestion
49> {
50 private plugin: TaskNotesPlugin;
51 private textarea: HTMLInputElement | HTMLTextAreaElement;
52 private currentTrigger: "@" | "#" | "+" | "status" | null = null;
53 // Store app reference explicitly to avoid relying on plugin.app in tests and runtime
54 private obsidianApp: App;
55 // Cache ProjectMetadataResolver to avoid recreating it for each suggestion
56 private projectMetadataResolver: ProjectMetadataResolver | null = null;
57
58 constructor(
59 app: App,
60 textareaEl: HTMLInputElement | HTMLTextAreaElement,
61 plugin: TaskNotesPlugin
62 ) {
63 super(app, textareaEl as unknown as HTMLInputElement);
64 this.plugin = plugin;
65 this.textarea = textareaEl;
66 this.obsidianApp = app;
67 }
68
69 private getCursorPosition(): number {
70 return this.textarea.selectionStart ?? this.textarea.value.length;
71 }
72
73 /**
74 * Helper: Check if index is at a word boundary
75 */
76 private isBoundary(textBeforeCursor: string, index: number): boolean {
77 if (index === -1) return false;
78 if (index === 0) return true;
79 const prev = textBeforeCursor[index - 1];
80 return !/\w/.test(prev);
81 }
82
83 /**
84 * Find the most recent valid trigger before cursor
85 */
86 private findActiveTrigger(textBeforeCursor: string): {
87 trigger: "@" | "#" | "+" | "status" | null;
88 triggerIndex: number;
89 queryAfterTrigger: string;
90 } {
91 const lastAtIndex = textBeforeCursor.lastIndexOf("@");
92 const lastHashIndex = textBeforeCursor.lastIndexOf("#");
93 const lastPlusIndex = textBeforeCursor.lastIndexOf("+");
94 const statusTrig = (this.plugin.settings.statusSuggestionTrigger || "").trim();
95 const lastStatusIndex = statusTrig ? textBeforeCursor.lastIndexOf(statusTrig) : -1;
96
97 // Determine most recent valid trigger by index
98 const candidates: Array<{ type: "@" | "#" | "+" | "status"; index: number }> = [
99 { type: "@" as const, index: lastAtIndex },
100 { type: "#" as const, index: lastHashIndex },
101 { type: "+" as const, index: lastPlusIndex },
102 { type: "status" as const, index: lastStatusIndex },
103 ].filter((c) => this.isBoundary(textBeforeCursor, c.index));
104

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected