diff --git a/package.json b/package.json index 3a1b79a..f658d0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linenoteplus", - "version": "4.0.0", + "version": "4.0.1", "displayName": "Line Note Plus", "license": "MIT", "main": "./build/extension.js", diff --git a/src/extension.ts b/src/extension.ts index 071bd2b..385a3e6 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -21,178 +21,266 @@ import { } from "./extension/commands"; import { refreshCache } from "./lib/cache/refreshCache"; import { cleanUpOrphanedNotes } from "./utils/helpers/note-utils"; +import { getOutputChannel } from "./extension/output/getOutputChannel"; export const activate = async (context: vscode.ExtensionContext) => { - initializeGlobalNoteCache(); - refreshCache(Context); - refreshCache(Config); - - const provider = new NoteLinkProvider(); - const documentLinkDisposable = vscode.languages.registerDocumentLinkProvider( - "*", - provider - ); - - const decorator: Decorator = new Decorator(context); - let disposed: boolean = false; - - // exclude notes dirs by default - const conf = vscode.workspace.getConfiguration(); - const exclude: any = conf.get("files.exclude"); - const notesDirs = Context.notesDir.cached(); - const excludeFiles = { - ...exclude, - }; - for (const _workspaceFolder in notesDirs) { - // make this configurable. (show or hide on default) - // const notesDir = notesDirs[workspaceFolder]; - // excludeFiles[notesDir] = true; - } - conf.update("files.exclude", excludeFiles); - // end - - let tid: NodeJS.Timer; - const cleanUpOnInterval = () => { - // watch orphaned notes - if (disposed) { - if (tid) { - clearTimeout(tid); - } - return; + try { + initializeGlobalNoteCache(); + refreshCache(Context); + refreshCache(Config); + + const provider = new NoteLinkProvider(); + const documentLinkDisposable = + vscode.languages.registerDocumentLinkProvider("*", provider); + + const decorator: Decorator = new Decorator(context); + let disposed: boolean = false; + + // exclude notes dirs by default + const conf = vscode.workspace.getConfiguration(); + const exclude: any = conf.get("files.exclude"); + const notesDirs = Context.notesDir.cached(); + const excludeFiles = { + ...exclude, + }; + for (const _workspaceFolder in notesDirs) { + // make this configurable. (show or hide on default) + // const notesDir = notesDirs[workspaceFolder]; + // excludeFiles[notesDir] = true; } - const interval = Config.cleanUpOrphanedNotesInterval.cached(); - const cleanUpStrategy = Config.cleanUpOrphanedNotes.cached(); - if (typeof interval === "number" && interval >= 0) { - if ( - ["on-interval", "on-save-and-on-interval"].some( - (s) => s === cleanUpStrategy - ) - ) { - cleanUpOrphanedNotes(); - const start = +new Date(); - const duration = +new Date() - start; - tid = setTimeout(cleanUpOnInterval, Math.max(0, interval - duration)); - } else { - clearTimeout(tid); + conf.update("files.exclude", excludeFiles); + // end + + let tid: NodeJS.Timer; + const cleanUpOnInterval = () => { + try { + // watch orphaned notes + if (disposed) { + if (tid) { + clearTimeout(tid); + } + return; + } + const interval = Config.cleanUpOrphanedNotesInterval.cached(); + const cleanUpStrategy = Config.cleanUpOrphanedNotes.cached(); + if (typeof interval === "number" && interval >= 0) { + if ( + ["on-interval", "on-save-and-on-interval"].some( + (s) => s === cleanUpStrategy + ) + ) { + cleanUpOrphanedNotes(); + const start = +new Date(); + const duration = +new Date() - start; + tid = setTimeout( + cleanUpOnInterval, + Math.max(0, interval - duration) + ); + } else { + clearTimeout(tid); + } + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } + }; + + const cleanupOnSave = () => { + context.subscriptions.push( + vscode.workspace.onDidSaveTextDocument(onDidSaveTextDocument) + ); + }; + + // set cleanup orphaned nodes logic + // based on conf + const cleanUpStrategy = Config.cleanUpOrphanedNotes.cached(); + switch (cleanUpStrategy) { + case "on-save": + cleanupOnSave(); + break; + case "on-interval": + cleanUpOnInterval(); + break; + case "on-save-and-on-interval": + cleanupOnSave(); + cleanUpOnInterval(); + break; + case "never": + default: } - }; - const cleanupOnSave = () => { + const decorateDebounce = debounce({ + wait: 500, + func: () => { + if (disposed) { + return; + } + decorator.decorate(); + }, + }); + decorateDebounce(); + + const registerCommand = vscode.commands.registerCommand; context.subscriptions.push( - vscode.workspace.onDidSaveTextDocument(onDidSaveTextDocument) - ); - }; - - // set cleanup orphaned nodes logic - // based on conf - const cleanUpStrategy = Config.cleanUpOrphanedNotes.cached(); - switch (cleanUpStrategy) { - case "on-save": - cleanupOnSave(); - break; - case "on-interval": - cleanUpOnInterval(); - break; - case "on-save-and-on-interval": - cleanupOnSave(); - cleanUpOnInterval(); - break; - case "never": - default: - } + new vscode.Disposable(() => (disposed = true)), - const decorateDebounce = debounce({ - wait: 500, - func: () => { - if (disposed) { - return; - } - decorator.decorate(); - }, - }); - decorateDebounce(); + documentLinkDisposable, - const registerCommand = vscode.commands.registerCommand; - context.subscriptions.push( - new vscode.Disposable(() => (disposed = true)), + vscode.window.onDidChangeActiveTextEditor((editor) => { + try { + if (editor) { + updateIsActiveEditorNoteContext(); + decorateDebounce(); + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); + } + }), - documentLinkDisposable, + vscode.workspace.onDidChangeTextDocument((event) => { + try { + if ( + vscode.window.activeTextEditor && + event.document === vscode.window.activeTextEditor.document + ) { + decorateDebounce(); + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); + } + }), - vscode.window.onDidChangeActiveTextEditor((editor) => { - if (editor) { - updateIsActiveEditorNoteContext(); - decorateDebounce(); - } - }), - - vscode.workspace.onDidChangeTextDocument((event) => { - if ( - vscode.window.activeTextEditor && - event.document === vscode.window.activeTextEditor.document - ) { - decorateDebounce(); - } - }), + vscode.workspace.onDidCloseTextDocument(onDidCloseTextDocument), - vscode.workspace.onDidCloseTextDocument(onDidCloseTextDocument), + vscode.workspace.onDidChangeConfiguration(async (event) => { + try { + if ( + event.affectsConfiguration("linenoteplus.lineColor") || + event.affectsConfiguration("linenoteplus.rulerColor") + ) { + decorator.reload(); + decorator.decorate(); + } + if ( + event.affectsConfiguration("linenoteplus.cleanUpOrphanedNotes") || + event.affectsConfiguration( + "linenoteplus.cleanUpOrphanedNotesInterval" + ) + ) { + // TODO + // initializeCleanupStrategy + await vscode.window.showInformationMessage( + "Line Note Plus: Configuration updates to cleanUpOrphanedNotes or " + + "cleanUpOrphanedNotesInterval requires reloading." + ); + await vscode.commands.executeCommand( + "workbench.action.reloadExtension" + ); + } + if ( + event.affectsConfiguration("linenoteplus.removeText") || + event.affectsConfiguration("linenoteplus.editText") || + event.affectsConfiguration("linenoteplus.notePrefix") || + event.affectsConfiguration("linenoteplus.openNoteBehavior") + ) { + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); + } + }), - vscode.workspace.onDidChangeConfiguration(async (event) => { - if ( - event.affectsConfiguration("linenoteplus.lineColor") || - event.affectsConfiguration("linenoteplus.rulerColor") - ) { - decorator.reload(); - decorator.decorate(); - } - if ( - event.affectsConfiguration("linenoteplus.cleanUpOrphanedNotes") || - event.affectsConfiguration("linenoteplus.cleanUpOrphanedNotesInterval") - ) { - // TODO - // initializeCleanupStrategy - await vscode.window.showInformationMessage( - "Line Note Plus: Configuration updates to cleanUpOrphanedNotes or " + - "cleanUpOrphanedNotesInterval requires reloading." - ); - await vscode.commands.executeCommand( - "workbench.action.reloadExtension" - ); - } - if ( - event.affectsConfiguration("linenoteplus.removeText") || - event.affectsConfiguration("linenoteplus.editText") || - event.affectsConfiguration("linenoteplus.notePrefix") || - event.affectsConfiguration("linenoteplus.openNoteBehavior") - ) { - } - }), - - registerCommand("linenoteplus.addNote", addNote), - - registerCommand("linenoteplus.openNote", openNote), - - registerCommand("linenoteplus.showPreviewToSide", showPreviewToSide), - - registerCommand("linenoteplus.removeNote", async (uuid?: string) => { - const _uuid = uuid || Note.matchUuidOnActiveLine(getEditor()); - if (_uuid) { - // remove specified note (when invoked from the hover text) - const note = getNoteCache().get(_uuid); - if (note.line > -1) { - const uri = vscode.Uri.parse(note.targetPath); - const document = await vscode.workspace.openTextDocument(uri); - const line = document.lineAt(note.line); - const edit = new vscode.WorkspaceEdit(); - edit.delete(uri, line.rangeIncludingLineBreak); - vscode.workspace.applyEdit(edit); + registerCommand("linenoteplus.addNote", addNote), + + registerCommand("linenoteplus.openNote", openNote), + + registerCommand("linenoteplus.showPreviewToSide", showPreviewToSide), + + registerCommand("linenoteplus.removeNote", async (uuid?: string) => { + try { + const _uuid = uuid || Note.matchUuidOnActiveLine(getEditor()); + if (_uuid) { + // remove specified note (when invoked from the hover text) + const note = getNoteCache().get(_uuid); + if (note.line > -1) { + const uri = vscode.Uri.parse(note.targetPath); + const document = await vscode.workspace.openTextDocument(uri); + const line = document.lineAt(note.line); + const edit = new vscode.WorkspaceEdit(); + edit.delete(uri, line.rangeIncludingLineBreak); + vscode.workspace.applyEdit(edit); + } + await note.remove(); + decorateDebounce(); + return; + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } - await note.remove(); - decorateDebounce(); - return; - } - }), + }), - registerCommand("linenoteplus.revealLine", revealLine) - ); + registerCommand("linenoteplus.revealLine", revealLine) + ); + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); + } }; diff --git a/src/extension/commands/openNote.ts b/src/extension/commands/openNote.ts index 65b67b9..f54e329 100644 --- a/src/extension/commands/openNote.ts +++ b/src/extension/commands/openNote.ts @@ -1,25 +1,38 @@ - -import { window } from 'vscode'; -import { getEditor } from '../../lib/getters/getEditor'; -import { Note } from '../../models/Note'; - +import { window } from "vscode"; +import { getEditor } from "../../lib/getters/getEditor"; +import { Note } from "../../models/Note"; +import { getOutputChannel } from "../output/getOutputChannel"; export const openNote = async (uuid?: string) => { - const editor = getEditor(); - if (uuid) { - const note = Note.asNote(editor.document, uuid); - await note.touch(); - await note.open(); - return; - } - // 📌 test note 📝 🗑 - const _uuid = Note.matchUuidOnActiveLine(editor); - if (_uuid) { - const note = Note.asNote(editor.document, _uuid); - await note.touch(); - await note.open(); - return; - } else { - window.showErrorMessage("Select a note marker to edit a note."); + try { + const editor = getEditor(); + if (uuid) { + const note = Note.asNote(editor.document, uuid); + await note.touch(); + await note.open(); + return; + } + // 📌 test note 📝 🗑 + const _uuid = Note.matchUuidOnActiveLine(editor); + if (_uuid) { + const note = Note.asNote(editor.document, _uuid); + await note.touch(); + await note.open(); + return; + } else { + window.showErrorMessage("Select a note marker to edit a note."); + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } }; diff --git a/src/extension/commands/revealLine.ts b/src/extension/commands/revealLine.ts index aa0aad8..77fc993 100644 --- a/src/extension/commands/revealLine.ts +++ b/src/extension/commands/revealLine.ts @@ -5,29 +5,43 @@ import { Note } from "../../models/Note"; import { getOpenNoteBehavior } from "../../utils/helpers/misc-utils"; import { getUuidFromNotePath } from "../../utils/helpers/note-path-utils"; import { Uri, window, workspace } from "vscode"; +import { getOutputChannel } from "../output/getOutputChannel"; export const revealLine = async () => { - const editor = getEditor(); - const filePath = editor.document.uri.fsPath; - const uuid = await getUuidFromNotePath(filePath); - if (!uuid) { - throw new Error(ErrorCodes['Error_0002']({ filePath })); + try { + const editor = getEditor(); + const filePath = editor.document.uri.fsPath; + const uuid = await getUuidFromNotePath(filePath); + if (!uuid) { + throw new Error(ErrorCodes["Error_0002"]({ filePath })); + } + const note = getNoteCache().get(uuid); + if (!note) { + throw new Error(ErrorCodes["Error_0001"]({ uuid })); + } + if (!(await note.fsExists())) { + return; + } + const document = await workspace.openTextDocument( + Uri.file(note.targetPath) + ); + const line = Note.getLine(document, uuid); + const selection = document.lineAt(line).range; + await window.showTextDocument(document, { + selection, + ...getOpenNoteBehavior(), + }); + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } - const note = getNoteCache().get(uuid); - if (!note) { - throw new Error(ErrorCodes['Error_0001']({ uuid })); - } - if (!await note.fsExists()) { - return; - } - const document = await workspace.openTextDocument( - Uri.file(note.targetPath) - ); - const line = Note.getLine(document, uuid); - const selection = document.lineAt(line).range; - await window.showTextDocument(document, { - selection, - ...getOpenNoteBehavior(), - });; }; - diff --git a/src/extension/commands/showPreviewToSide.ts b/src/extension/commands/showPreviewToSide.ts index 86c4a36..7070974 100644 --- a/src/extension/commands/showPreviewToSide.ts +++ b/src/extension/commands/showPreviewToSide.ts @@ -1,35 +1,50 @@ -import { commands, window } from 'vscode'; -import * as fs from 'fs-extra'; -import { getEditor } from '../../lib/getters/getEditor'; -import { getNotesDir } from '../../utils/helpers/note-path-utils'; -import { Note } from '../../models/Note'; -import { getBesideViewColumn } from '../../utils/helpers/misc-utils'; +import { commands, window } from "vscode"; +import * as fs from "fs-extra"; +import { getEditor } from "../../lib/getters/getEditor"; +import { getNotesDir } from "../../utils/helpers/note-path-utils"; +import { Note } from "../../models/Note"; +import { getBesideViewColumn } from "../../utils/helpers/misc-utils"; +import { getOutputChannel } from "../output/getOutputChannel"; -export const showPreviewToSide = async (uuid?: string) => { - const editor = getEditor(); - const notesDir = getNotesDir(editor.document.fileName); - if (!fs.existsSync(notesDir)) { +export const showPreviewToSide = async (uuid?: string) => { + try { + const editor = getEditor(); + const notesDir = getNotesDir(editor.document.fileName); + if (!fs.existsSync(notesDir)) { window.showErrorMessage(`Can preview existing notes.`); return; - } - if (uuid) { - const note = Note.asNote(editor.document, uuid); - await note.open({ - viewColumn: getBesideViewColumn(), - preserveFocus: false, - }); - await commands.executeCommand('markdown.showPreview'); - return; - } - const _uuid = Note.matchUuidOnActiveLine(editor); - if (_uuid) { - const note = Note.asNote(editor.document, _uuid); - await note.open({ - viewColumn: getBesideViewColumn(), - preserveFocus: false, - }); - await commands.executeCommand('markdown.showPreview'); - } else { + } + if (uuid) { + const note = Note.asNote(editor.document, uuid); + await note.open({ + viewColumn: getBesideViewColumn(), + preserveFocus: false, + }); + await commands.executeCommand("markdown.showPreview"); + return; + } + const _uuid = Note.matchUuidOnActiveLine(editor); + if (_uuid) { + const note = Note.asNote(editor.document, _uuid); + await note.open({ + viewColumn: getBesideViewColumn(), + preserveFocus: false, + }); + await commands.executeCommand("markdown.showPreview"); + } else { window.showErrorMessage("Select a note marker to preview a note."); + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } }; diff --git a/src/extension/decorators/decorator.ts b/src/extension/decorators/decorator.ts index 0262818..69da6a1 100644 --- a/src/extension/decorators/decorator.ts +++ b/src/extension/decorators/decorator.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import { Note } from "../../models/Note"; import { filterResolved, splitArr } from "../../utils/utils"; import { matchUuids } from "../../utils/helpers/match-helpers"; +import { getOutputChannel } from "../output/getOutputChannel"; export class Decorator { context: vscode.ExtensionContext; diff --git a/src/extension/events/onDidCloseTextDocument.ts b/src/extension/events/onDidCloseTextDocument.ts index 9313f75..5194d02 100644 --- a/src/extension/events/onDidCloseTextDocument.ts +++ b/src/extension/events/onDidCloseTextDocument.ts @@ -1,24 +1,38 @@ import { commands, TextDocument } from "vscode"; import { getNoteCache } from "../../lib/getters/getNoteCache"; import { getUuidFromNotePath } from "../../utils/helpers/note-path-utils"; -import { log } from "../output/getOutputChannel"; +import { getOutputChannel, log } from "../output/getOutputChannel"; /** remove note if it is empty */ export const onDidCloseTextDocument = log.time( "onDidCloseTextDocument", async (event: TextDocument) => { - const notePath = event.uri.fsPath; - const uuid = getUuidFromNotePath(notePath); - if (!uuid) { - return; - } - const note = getNoteCache().get(uuid); - if (!note) { - return; - } - const body = await note.read(); - if (!body.trim().length) { - await commands.executeCommand("linenoteplus.removeNote", uuid); + try { + const notePath = event.uri.fsPath; + const uuid = getUuidFromNotePath(notePath); + if (!uuid) { + return; + } + const note = getNoteCache().get(uuid); + if (!note) { + return; + } + const body = await note.read(); + if (!body.trim().length) { + await commands.executeCommand("linenoteplus.removeNote", uuid); + } + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + }, + null, + 2 + ) + ); } } ); diff --git a/src/extension/events/onDidSaveTextDocument.ts b/src/extension/events/onDidSaveTextDocument.ts index 7a314b4..b6b8356 100644 --- a/src/extension/events/onDidSaveTextDocument.ts +++ b/src/extension/events/onDidSaveTextDocument.ts @@ -4,43 +4,66 @@ import { matchUuids } from "../../utils/helpers/match-helpers"; import { getOrphanedUuidsForCurDoc } from "../../utils/helpers/note-utils"; import { commands, TextDocument } from "vscode"; import { Config } from "../../lib/caches/ConfigurationCache"; -import { log } from "../output/getOutputChannel"; +import { getOutputChannel, log } from "../output/getOutputChannel"; /** create notes or cleanup orphaned notes */ export const onDidSaveTextDocument = log.time( "onDidSaveTextDocument", async (document: TextDocument) => { - // create notes for notemarkers - // with no corresponding notes - const uuids: string[] = matchUuids(document.getText()); - const targetPath = document.uri.fsPath; - await Promise.all( - uuids.map(async (uuid) => { - const note = Note.asNote(document, uuid); - getNoteCache().set(note.uuid, note); - if (!note.noteExists()) { - await note.write(""); - await note.open(); - } - }) - ); + try { + // create notes for notemarkers + // with no corresponding notes + const uuids: string[] = matchUuids(document.getText()); + const targetPath = document.uri.fsPath; + await Promise.all( + uuids.map(async (uuid) => { + const note = Note.asNote(document, uuid); + getNoteCache().set(note.uuid, note); + if (!note.noteExists()) { + await note.write(""); + await note.open(); + } + }) + ); - // delete notes based on cleanup - // strategy - const cleanUpStrategy = await Config.cleanUpOrphanedNotes.forceMiss(); - if ( - !["on-save", "on-save-and-on-interval"].some((s) => s === cleanUpStrategy) - ) { - return; - } - const uuidsToDelete = getOrphanedUuidsForCurDoc({ - filePath: targetPath, - uuids, - }); - uuidsToDelete.forEach(async (uuid) => { - if (uuid) { - await commands.executeCommand("linenoteplus.removeNote", uuid); + // delete notes based on cleanup + // strategy + const cleanUpStrategy = await Config.cleanUpOrphanedNotes.forceMiss(); + if ( + !["on-save", "on-save-and-on-interval"].some( + (s) => s === cleanUpStrategy + ) + ) { + return; } - }); + const uuidsToDelete = getOrphanedUuidsForCurDoc({ + filePath: targetPath, + uuids, + }); + uuidsToDelete.forEach(async (uuid) => { + if (uuid) { + await commands.executeCommand("linenoteplus.removeNote", uuid); + } + }); + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + context: { + document: { + fileName: document.fileName, + }, + uuids: matchUuids(document.getText()), + targetPath: document.uri.fsPath, + }, + }, + null, + 2 + ) + ); + } } ); diff --git a/src/extension/providers/NoteLinkProvider.ts b/src/extension/providers/NoteLinkProvider.ts index 1131cc9..0f8c217 100644 --- a/src/extension/providers/NoteLinkProvider.ts +++ b/src/extension/providers/NoteLinkProvider.ts @@ -10,61 +10,81 @@ import { import { matchUuids } from "../../utils/helpers/match-helpers"; import { Note } from "../../models/Note"; import { Config } from "../../lib/caches/ConfigurationCache"; +import { getOutputChannel } from "../output/getOutputChannel"; export class NoteLinkProvider implements DocumentLinkProvider { provideDocumentLinks(document: TextDocument): ProviderResult { - const links: DocumentLink[] = []; - const text = document.getText(); - const uuids = matchUuids(text); - const notePrefix = Config.notePrefix.cached(); - const editText = Config.editText.cached(); - const removeText = Config.removeText.cached(); - for (const uuid of uuids) { - const lineIndex = Note.getLine(document, uuid); - const line = document.lineAt(lineIndex); - const editIndex = line.text.indexOf(editText); - const editPosition = new Position(line.lineNumber, editIndex); - const editEndPosition = new Position( - line.lineNumber, - editIndex + editText.length - ); - const editRange = new Range(editPosition, editEndPosition); - const editUri = Uri.parse( - `command:linenoteplus.openNote?${encodeURIComponent( - JSON.stringify(uuid) - )}` - ); - const editLink = new DocumentLink(editRange, editUri); - links.push(editLink); + try { + const links: DocumentLink[] = []; + const text = document.getText(); + const uuids = matchUuids(text); + const notePrefix = Config.notePrefix.cached(); + const editText = Config.editText.cached(); + const removeText = Config.removeText.cached(); + for (const uuid of uuids) { + const lineIndex = Note.getLine(document, uuid); + const line = document.lineAt(lineIndex); + const editIndex = line.text.indexOf(editText); + const editPosition = new Position(line.lineNumber, editIndex); + const editEndPosition = new Position( + line.lineNumber, + editIndex + editText.length + ); + const editRange = new Range(editPosition, editEndPosition); + const editUri = Uri.parse( + `command:linenoteplus.openNote?${encodeURIComponent( + JSON.stringify(uuid) + )}` + ); + const editLink = new DocumentLink(editRange, editUri); + links.push(editLink); - const removeIndex = line.text.indexOf(removeText); - const removePosition = new Position(line.lineNumber, removeIndex); - const removeEndPosition = new Position( - line.lineNumber, - removeIndex + removeText.length - ); - const removeRange = new Range(removePosition, removeEndPosition); - const removeUri = Uri.parse( - `command:linenoteplus.removeNote?${encodeURIComponent( - JSON.stringify(uuid) - )}` - ); - const removeLink = new DocumentLink(removeRange, removeUri); - links.push(removeLink); + const removeIndex = line.text.indexOf(removeText); + const removePosition = new Position(line.lineNumber, removeIndex); + const removeEndPosition = new Position( + line.lineNumber, + removeIndex + removeText.length + ); + const removeRange = new Range(removePosition, removeEndPosition); + const removeUri = Uri.parse( + `command:linenoteplus.removeNote?${encodeURIComponent( + JSON.stringify(uuid) + )}` + ); + const removeLink = new DocumentLink(removeRange, removeUri); + links.push(removeLink); - // TODO check for either ducky or note prefix - const prefixIdx = [notePrefix] - .map((p) => line.text.indexOf(p)) - .find((idx) => idx !== -1); - if (prefixIdx) { - const openPosition = new Position(line.lineNumber, prefixIdx); - const openEndPosition = new Position(line.lineNumber, editIndex - 1); - const openRange = new Range(openPosition, openEndPosition); - const openLink = new DocumentLink(openRange, editUri); - links.push(openLink); + // TODO check for either ducky or note prefix + const prefixIdx = [notePrefix] + .map((p) => line.text.indexOf(p)) + .find((idx) => idx !== -1); + if (prefixIdx) { + const openPosition = new Position(line.lineNumber, prefixIdx); + const openEndPosition = new Position(line.lineNumber, editIndex - 1); + const openRange = new Range(openPosition, openEndPosition); + const openLink = new DocumentLink(openRange, editUri); + links.push(openLink); + } } - } - return new Promise((res) => res(links)); + return new Promise((res) => res(links)); + } catch (e: any) { + getOutputChannel().appendLine( + JSON.stringify( + { + error: true, + message: e.message, + stack: e.stack, + context: { + document: { + fileName: document.fileName, + }, + }, + }, + null, + 2 + ) + ); + } } } diff --git a/src/models/Note.ts b/src/models/Note.ts index 7d60095..ba3e21e 100644 --- a/src/models/Note.ts +++ b/src/models/Note.ts @@ -94,15 +94,28 @@ export class Note implements NoteProps { } async open(options?: vscode.TextDocumentShowOptions): Promise { - getNoteCache().set(this.uuid, this); - await vscode.commands.executeCommand( - "vscode.open", - vscode.Uri.file(this.selfPath), - { - ...getOpenNoteBehavior(), - ...options, - } - ); + try { + getNoteCache().set(this.uuid, this); + await vscode.commands.executeCommand( + "vscode.open", + vscode.Uri.file(this.selfPath), + { + ...getOpenNoteBehavior(), + ...options, + } + ); + } catch (e: any) { + e.context = { + ...e.context, + note: { + selfPath: this.selfPath, + targetPath: this.targetPath, + uuid: this.uuid, + line: this.line, + }, + }; + throw new Error(e); + } } async write(body: string): Promise {