diff --git a/CHANGELOG.md b/CHANGELOG.md index cf34dce..9cf63b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * the Notes view is refreshed after a note has been deleted, instead of before * deleting a folder relied on a package that was only installed as a development dependency * New Note and New Folder failed when a note was selected, they now create next to the note (#67, #76) +* in a portable VS Code, a relative storage location is relative to the folder holding VS Code, so notes can be kept with it and opened from there (#38) ## [2.0.0] - 2025-03-26 diff --git a/README.md b/README.md index 154b44c..79a848b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ A multi-root workspace uses the first folder for relative locations. This extension contributes the following settings: -* `Notes.notesLocation`: location of the notes in the Notes section, set in your user settings and not synced between machines +* `Notes.notesLocation`: location of the notes in the Notes section, set in your user settings and not synced between machines. In a [portable](https://code.visualstudio.com/docs/editor/portable) VS Code, a relative path is relative to the folder holding VS Code, so the notes can travel with it (for example `data/Notes` on Windows and Linux) * `Notes.workspaceNotesLocation`: location of the notes in the Workspace Notes section, relative to the workspace folder or a full path * `Notes.notesDefaultNotesExtension`: extension used for new notes * `Notes.notesExtensions`: list of extensions recognized as notes or '*' for all extensions diff --git a/package.json b/package.json index 063b2f5..6f54407 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "type": "string", "default": "", "scope": "machine-overridable", - "description": "Storage location for the Notes view, set in your user settings. A path starting with `~` is in your home folder. Not synced between machines. A value in a workspace's settings is used as that workspace's notes, use `notes.workspaceNotesLocation` for that instead." + "description": "Storage location for the Notes view, set in your user settings. A path starting with `~` is in your home folder. In a portable VS Code, a relative path is relative to the folder holding it, so the notes can travel with it. Not synced between machines. A value in a workspace's settings is used as that workspace's notes, use `notes.workspaceNotesLocation` for that instead." }, "notes.workspaceNotesLocation": { "type": "string", diff --git a/src/extension.ts b/src/extension.ts index 9e2a367..8016028 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,7 +6,7 @@ import * as path from 'path'; import { Note } from './note'; import { NotesViewProvider } from './notesViewProvider'; import { NotesWatcher } from './notesWatcher'; -import { getLocationState, resolveNotesLocation, toWorkspaceSetting } from './location'; +import { getLocationState, getPortableFolder, resolveNotesLocation, toWorkspaceSetting } from './location'; let extId = 'vscode-notes'; let extPub = 'dionmunk'; @@ -231,11 +231,12 @@ export class Notes { return vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; } - // get notes storage location, with ~ and a path relative to the workspace folder resolved + // get notes storage location, with ~ and a relative path resolved: against the folder holding a portable + // VS Code, so the notes travel with it, otherwise against the workspace folder // only the user settings count: a notesLocation in workspace settings is that workspace's notes static getNotesLocation(): string { const notesLocation = vscode.workspace.getConfiguration('notes').inspect('notesLocation')?.globalValue; - return resolveNotesLocation(notesLocation, os.homedir(), Notes.getWorkspaceFolder()); + return resolveNotesLocation(notesLocation, os.homedir(), getPortableFolder() ?? Notes.getWorkspaceFolder()); } // get the workspace notes location, '' without a workspace folder or a location diff --git a/src/location.ts b/src/location.ts index 199dfe2..5f63fe3 100644 --- a/src/location.ts +++ b/src/location.ts @@ -61,3 +61,11 @@ export function toWorkspaceSetting(folder: string, workspaceDir: string): string // forward slashes work on every platform, and the setting may be shared through the repository return relative.split(path.sep).join('/'); } + +// the folder holding a portable VS Code, which a relative notes location is resolved against so the notes +// travel with it: VS Code sets VSCODE_PORTABLE to its portable data folder, the `data` folder in the +// program folder on Windows and Linux, or `code-portable-data` next to the application on macOS +export function getPortableFolder(env: NodeJS.ProcessEnv = process.env): string | undefined { + const portableData = env.VSCODE_PORTABLE; + return portableData ? path.dirname(portableData) : undefined; +} diff --git a/src/test/suite/location.test.ts b/src/test/suite/location.test.ts index bb5f21c..0f4d727 100644 --- a/src/test/suite/location.test.ts +++ b/src/test/suite/location.test.ts @@ -2,7 +2,7 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { getLocationState, resolveNotesLocation, toWorkspaceSetting } from '../../location'; +import { getLocationState, getPortableFolder, resolveNotesLocation, toWorkspaceSetting } from '../../location'; suite('Notes Location', () => { const home = path.join(path.sep, 'home', 'someone'); @@ -77,4 +77,17 @@ suite('Notes Location', () => { const picked = path.join(workspace, 'docs', 'notes'); assert.strictEqual(resolveNotesLocation(toWorkspaceSetting(picked, workspace), home, workspace), picked); }); + + test('a portable VS Code is the folder holding its portable data folder', () => { + const install = path.join(path.sep, 'usb', 'VSCode'); + assert.strictEqual(getPortableFolder({ VSCODE_PORTABLE: path.join(install, 'data') }), install); + assert.strictEqual(getPortableFolder({}), undefined); + assert.strictEqual(getPortableFolder({ VSCODE_PORTABLE: '' }), undefined); + }); + + test('a relative location in a portable VS Code is inside its folder (#38)', () => { + const install = path.join(path.sep, 'usb', 'VSCode'); + const portable = getPortableFolder({ VSCODE_PORTABLE: path.join(install, 'data') }); + assert.strictEqual(resolveNotesLocation('data/Notes', home, portable), path.join(install, 'data', 'Notes')); + }); });