Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 4 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<string>('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
Expand Down
8 changes: 8 additions & 0 deletions src/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
15 changes: 14 additions & 1 deletion src/test/suite/location.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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'));
});
});
Loading