Skip to content

Commit

Permalink
feat: use uuids instead of file names and line numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
prmichaelsen committed Sep 3, 2023
1 parent 9d27101 commit c1fcdac
Show file tree
Hide file tree
Showing 12 changed files with 4,178 additions and 2,197 deletions.
3,010 changes: 3,010 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

81 changes: 56 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,34 @@
],
"main": "./out/extension.js",
"contributes": {
"commands": [{
"command": "linenote.addNote",
"title": "%command.addNote.title%"
}, {
"command": "linenote.openNote",
"title": "%command.openNote.title%"
}, {
"command": "linenote.removeNote",
"title": "%command.removeNote.title%"
}],
"commands": [
{
"command": "linenote.addNote",
"title": "%command.addNote.title%"
},
{
"command": "linenote.openNote",
"title": "%command.openNote.title%"
},
{
"command": "linenote.revealLine",
"title": "%command.revealLine.title%"
},
{
"command": "linenote.removeNote",
"title": "%command.removeNote.title%"
}
],
"menus": {
"editor/context": [{
"command": "linenote.addNote"
}]
"editor/context": [
{
"command": "linenote.addNote"
},
{
"command": "linenote.revealLine",
"when": "isActiveEditorNote"
}
]
},
"configuration": {
"type": "object",
Expand All @@ -57,25 +71,41 @@
"default": "rgba(255, 255, 0, 0.4)",
"description": "%configuration.rulerColor.description%"
},
"linenote.automaticallyDelete": {
"type": "boolean",
"default": true,
"description": "%configuration.automaticallyDelete.description%"
},
"linenote.automaticallyDeleteInterval": {
"linenote.cleanUpOrphanedNotesInterval": {
"type": "integer",
"default": 60000,
"description": "%configuration.automaticallyDeleteInterval.description%"
"description": "%configuration.cleanUpOrphanedNotesInterval.description%"
},
"linenote.showGutterIcon": {
"type": "boolean",
"default": true,
"description": "%configuration.showGutterIcon.description%"
},
"linenote.gutterIconPath": {
"type": ["string", "null"],
"default": null,
"type": [
"string",
"null"
],
"default": "images/gutter.png",
"description": "%configuration.gutterIconPath.description%"
},
"linenote.cleanUpOrphanedNotes": {
"type": [
"on-save",
"on-interval",
"on-save-and-on-interval",
"never"
],
"default": "on-save-and-on-interval",
"description": "%configuration.cleanUpOrphanedNotes.description%"
},
"linenote.includePaths": {
"type": "array",
"default": [
"**/src/**/*",
"**/.vscode/linenote/**/*"
],
"description": "%configuration.includePaths.description%"
}
}
}
Expand All @@ -94,12 +124,13 @@
"@types/node": "^8.10.25",
"tslint": "^5.8.0",
"typescript": "^3.1.4",
"vscode": "^1.1.25"
"vscode": "^1.1.37"
},
"dependencies": {
"@types/fs-extra": "^5.0.4",
"chokidar": "^2.0.4",
"fs-extra": "^7.0.1",
"lodash.debounce": "^4.0.8"
"lodash.debounce": "^4.0.8",
"short-uuid": "^4.2.2"
}
}
}
19 changes: 11 additions & 8 deletions package.nls.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"command.addNote.title": "Add note at current position",
"command.openNote.title": "Open notes at current position",
"command.removeNote.title": "Remove the note at current position",
"configuration.lineColor.description": "Background color of line with notes (name or HEX)",
"configuration.rulerColor.description": "Color of the ruler with notes (name or HEX)",
"configuration.automaticallyDelete.description": "If it set to true, notes that do not correspond to files are automatically deleted.",
"configuration.showGutterIcon.description": "If it set to true, displays the icon on the line where the note exists.",
"configuration.gutterIconPath.description": "File path of the icon to be displayed"
"command.addNote.title": "Line Note: Add note at current position",
"command.openNote.title": "Line Note: Edit note at current position",
"command.revealLine.title": "Line Note: Reveal line in notated file",
"command.removeNote.title": "Line Note: Remove note at current position",
"configuration.cleanUpOrphanedNotesInterval.description": "Interval at which to clean up unused notes in the background in ms. Only applies if cleanupOprhanedNotes is set to 'on-interval' or 'on-save-and-on-interval'. Default: 60000 (60s). For performance, a large value is recommended. In order to determine if a note has a corresponding marker, the entire project directory must be scanned.",
"configuration.cleanUpOrphanedNotes.description": "Whether to cleanup orphaned notes on save file, on change file, on an interval, or never. Default: 'on-save'. Warning: On change file will provide more realtime updates but may affect performance and will delete note files instantly if not found in the changed file. Requires reload.",
"configuration.includePaths.description": "File pattern globs to scan for note markers. Unmatched directories will be ignored.",
"configuration.gutterIconPath.description": "File path of the icon to be displayed",
"configuration.lineColor.description": "Background color of line with notes (name, HEX, or RGB)",
"configuration.rulerColor.description": "Color of the ruler with notes (name, HEX, or RGB)",
"configuration.showGutterIcon.description": "If it set to true, displays the icon on the line where the note exists. Default true."
}
44 changes: 44 additions & 0 deletions src/DocumentLinkProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { DocumentLink, DocumentLinkProvider, Position, ProviderResult, Range, TextDocument, Uri } from "vscode";
import { Note } from "./note";
import { getNotePrefix } from "./util";

export const editText = '[Edit]';
export const removeText = '[Remove]';
export class NoteLinkProvider implements DocumentLinkProvider {
provideDocumentLinks(document: TextDocument): ProviderResult<DocumentLink[]> {
const links: DocumentLink[] = [];
const text = document.getText();
const uuids = Note.matchUuids(text);
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:linenote.openNote?${encodeURIComponent(
JSON.stringify(uuid)
)}`
);
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:linenote.removeNote?${encodeURIComponent(
JSON.stringify(uuid)
)}`
);
const openPosition = new Position(line.lineNumber, line.text.indexOf(getNotePrefix()));
const openEndPosition = new Position(line.lineNumber, editIndex - 1);
const openRange = new Range(openPosition, openEndPosition);
const openLink = new DocumentLink(openRange, editUri);
const editLink = new DocumentLink(editRange, editUri);
const removeLink = new DocumentLink(removeRange, removeUri);
links.push(openLink, editLink, removeLink);
}

return new Promise((res) => res(links));
}
}
20 changes: 20 additions & 0 deletions src/commandUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as vscode from 'vscode';
import { getEditor } from './editorUtil';


export const formatIndentation = async () => {
const editor = getEditor()

const cursorPosition = editor.selection.anchor;
const currentPosition = cursorPosition.line;

// Get the text of the subsequent line
const subsequentLine = editor.document.lineAt(currentPosition + 1);

// Update the indentation of the current line to match the subsequent line
await editor.edit(editBuilder => {
const indentation = subsequentLine.firstNonWhitespaceCharacterIndex;
const position = new vscode.Position(currentPosition, 0);
editBuilder.insert(position, subsequentLine.text.substring(0, indentation));
});
}
128 changes: 70 additions & 58 deletions src/decorator.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import * as vscode from "vscode";
import { filterResolved, splitArr } from "./util";
import { getCorrespondingNotes, isNotePath } from "./noteUtil";
import { filterResolved, getNotesDir, splitArr } from "./util";
import { Note } from "./note";

export class Decorator {
context: vscode.ExtensionContext;
lineDecorator?: vscode.TextEditorDecorationType;
gutterDecorator?: vscode.TextEditorDecorationType;
noteMarkerDecorator?: vscode.TextEditorDecorationType;

constructor(context: vscode.ExtensionContext) {
this.context = context;
Expand All @@ -19,30 +20,33 @@ export class Decorator {
if (this.gutterDecorator) {
this.gutterDecorator.dispose();
}
if (this.noteMarkerDecorator) {
this.noteMarkerDecorator.dispose();
}

const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();

const lineProp: vscode.DecorationRenderOptions = {};
const noteMarkerProp: vscode.DecorationRenderOptions = {};
const gutterProp: vscode.DecorationRenderOptions = {};

// set line color
const line: string | undefined = config.get("linenote.lineColor");
if (line && line.trim().length) {
lineProp.backgroundColor = line.trim();
noteMarkerProp.backgroundColor = line.trim();
}

// set ruler color
const ruler: string | undefined = config.get("linenote.rulerColor");
if (ruler && ruler.trim().length) {
lineProp.overviewRulerLane = vscode.OverviewRulerLane.Right;
lineProp.overviewRulerColor = ruler.trim();
noteMarkerProp.overviewRulerLane = vscode.OverviewRulerLane.Right;
noteMarkerProp.overviewRulerColor = ruler.trim();
}

const showGutterIcon: boolean | undefined = config.get(
"linenote.showGutterIcon"
);
if (showGutterIcon) {
let iconPath: string | undefined = config.get("linenote.gutterIconPath");
let iconPath: string | null = config.get<string | null>("linenote.gutterIconPath")!;
if (iconPath) {
gutterProp.gutterIconPath = iconPath;
} else {
Expand All @@ -53,65 +57,73 @@ export class Decorator {
gutterProp.gutterIconSize = "cover";
}

this.lineDecorator = vscode.window.createTextEditorDecorationType(lineProp);
this.noteMarkerDecorator = vscode.window.createTextEditorDecorationType(noteMarkerProp);
this.lineDecorator = vscode.window.createTextEditorDecorationType({});
this.gutterDecorator = vscode.window.createTextEditorDecorationType(
gutterProp
);
}

async decorate() {
if (!vscode.window.activeTextEditor) {
return;
}

const editor = vscode.window.activeTextEditor;
const fsPath = editor.document.uri.fsPath;

// do not decorate the note itself
if (await isNotePath(fsPath)) {
return;
}

// load notes and create decoration options
const notes = await getCorrespondingNotes(fsPath);
const [lineProps, gutterProps] = splitArr(
await filterResolved(
notes.map(
async (
note
): Promise<[vscode.DecorationOptions, vscode.DecorationOptions]> => {
const markdown = new vscode.MarkdownString(
await note.readAsMarkdown()
);
markdown.isTrusted = true;
return [
{
range: new vscode.Range(
// subtract 1 because api's line number starts with 0, not 1
editor.document.lineAt(note.from - 1).range.start,
editor.document.lineAt(note.to - 1).range.end
),
hoverMessage: markdown
},
{
range: new vscode.Range(
editor.document.lineAt(note.from - 1).range.start,
editor.document.lineAt(note.from - 1).range.start
),
hoverMessage: markdown
}
];
}
const editors = vscode.window.visibleTextEditors;
for (const editor of editors) {
const noteDir = getNotesDir(editor.document.fileName);
// load notes and create decoration options
const uuids = Note.matchUuids(editor.document.getText());
const filePath = editor.document.uri.fsPath;
const notes = uuids.map(uuid => new Note({
filePath,
noteDir,
uuid,
line: Note.getLine(editor.document, uuid),
}));
const [lineProps, gutterProps, noteMarkerProps] = splitArr(
await filterResolved(
notes.map(
async (
note
): Promise<[vscode.DecorationOptions, vscode.DecorationOptions, vscode.DecorationOptions]> => {
const markdown = new vscode.MarkdownString(
await note.readAsMarkdown()
);
markdown.isTrusted = true;
const noteLine = editor.document.lineAt(note.line);
const line = editor.document.lineAt(note.line + 1);
return [
{
// line decorator
// notes marker line and noted line
range: new vscode.Range(
// subtract 1 because api's line number starts with 0, not 1
noteLine.range.start,
line.range.end
),
hoverMessage: markdown,
},
{
// gutter decorator
range: new vscode.Range(
line.range.start,
line.range.start
),
hoverMessage: markdown
},
{
// note marker decoratior
range: new vscode.Range(
noteLine.range.start,
noteLine.range.end
),
}
];
}
)
)
)
);
);

// recheck editor (because I used 'await'!)
if (vscode.window.activeTextEditor !== editor) {
return;
editor.setDecorations(this.noteMarkerDecorator!, noteMarkerProps);
editor.setDecorations(this.lineDecorator!, lineProps);
editor.setDecorations(this.gutterDecorator!, gutterProps);
}

editor.setDecorations(this.lineDecorator!, lineProps);
editor.setDecorations(this.gutterDecorator!, gutterProps);
}
}
Loading

0 comments on commit c1fcdac

Please sign in to comment.