Skip to content

Commit c0594bd

Browse files
committed
Handle cwd relative to workspace and named folders
1 parent b98320e commit c0594bd

File tree

3 files changed

+55
-23
lines changed

3 files changed

+55
-23
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@
735735
"powershell.cwd": {
736736
"type": "string",
737737
"default": "",
738-
"markdownDescription": "An explicit start path where the Extension Terminal will be launched. Both the PowerShell process's and the shell's location will be set to this directory. **Path must be fully resolved: variables are not supported!**"
738+
"markdownDescription": "A path where the Extension Terminal will be launched. Both the PowerShell process's and the shell's location will be set to this directory. Does not support variables, but does support the use of '~' and paths relative to a single workspace. **For multi-root workspaces, use the name of the folder you wish to have as the cwd.**"
739739
},
740740
"powershell.scriptAnalysis.enable": {
741741
"type": "boolean",

src/settings.ts

+45-20
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,11 @@ export async function getChosenWorkspace(logger: ILogger | undefined): Promise<v
236236
};
237237

238238
chosenWorkspace = await vscode.window.showWorkspaceFolderPick(options);
239+
239240
logger?.writeVerbose(`User selected workspace: '${chosenWorkspace?.name}'`);
241+
if (chosenWorkspace === undefined) {
242+
chosenWorkspace = vscode.workspace.workspaceFolders[0];
243+
}
240244
}
241245

242246
// NOTE: We don't rely on checking if `chosenWorkspace` is undefined because
@@ -247,34 +251,55 @@ export async function getChosenWorkspace(logger: ILogger | undefined): Promise<v
247251
}
248252

249253
export async function validateCwdSetting(logger: ILogger | undefined): Promise<string> {
250-
let cwd: string | undefined = utils.stripQuotePair(
251-
vscode.workspace.getConfiguration(utils.PowerShellLanguageId).get<string>("cwd"));
252-
253-
// Use the resolved cwd setting if it exists. We're checking truthiness
254-
// because it could be an empty string, in which case we ignore it.
255-
if (cwd) {
256-
cwd = path.resolve(untildify(cwd));
257-
if (await utils.checkIfDirectoryExists(cwd)) {
258-
return cwd;
254+
let cwd = utils.stripQuotePair(
255+
vscode.workspace.getConfiguration(utils.PowerShellLanguageId).get<string>("cwd"))
256+
?? "";
257+
258+
// Replace ~ with home directory.
259+
cwd = untildify(cwd);
260+
261+
// Use the cwd setting if it's absolute and exists. We don't use or resolve
262+
// relative paths here because it'll be relative to the Code process's cwd,
263+
// which is not what the user is expecting.
264+
if (path.isAbsolute(cwd) && await utils.checkIfDirectoryExists(cwd)) {
265+
return cwd;
266+
}
267+
268+
// If the cwd matches the name of a workspace folder, use it. Essentially
269+
// "choose" a workspace folder based off the cwd path, and so set the state
270+
// appropriately for `getChosenWorkspace`.
271+
if (vscode.workspace.workspaceFolders) {
272+
for (const workspaceFolder of vscode.workspace.workspaceFolders) {
273+
// TODO: With some more work, we could support paths relative to a
274+
// workspace folder name too.
275+
if (cwd === workspaceFolder.name) {
276+
hasChosen = true;
277+
chosenWorkspace = workspaceFolder;
278+
cwd = "";
279+
}
259280
}
260281
}
261282

262283
// Otherwise get a cwd from the workspace, if possible.
263284
const workspace = await getChosenWorkspace(logger);
264-
cwd = workspace?.uri.fsPath;
285+
if (workspace === undefined) {
286+
logger?.writeVerbose("Workspace was undefined, using homedir!");
287+
return os.homedir();
288+
}
265289

266-
// Save the picked 'cwd' to the workspace settings.
267-
if (cwd && await utils.checkIfDirectoryExists(cwd)) {
268-
// TODO: Stop saving this to settings! Instead, save the picked
269-
// workspace (or save this, but in a cache).
270-
await changeSetting("cwd", cwd, undefined, logger);
290+
const workspacePath = workspace.uri.fsPath;
291+
292+
// Use the chosen workspace's root to resolve the cwd.
293+
const relativePath = path.join(workspacePath, cwd);
294+
if (await utils.checkIfDirectoryExists(relativePath)) {
295+
return relativePath;
271296
}
272297

273-
// If there were no workspace folders, or somehow they don't exist, use
274-
// the home directory.
275-
if (!cwd || !await utils.checkIfDirectoryExists(cwd)) {
276-
return os.homedir();
298+
// Just use the workspace path.
299+
if (await utils.checkIfDirectoryExists(workspacePath)) {
300+
return workspacePath;
277301
}
278302

279-
return cwd;
303+
// If all else fails, use the home directory.
304+
return os.homedir();
280305
}

test/core/settings.test.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,18 @@ describe("Settings E2E", function () {
8888
assert.strictEqual(await validateCwdSetting(undefined), os.homedir());
8989
});
9090

91-
it("Resolves relative paths", async function () {
91+
it("Accepts relative paths", async function () {
9292
// A different than default folder that definitely exists and is relative
9393
const cwd = path.join("~", "somewhere", "..");
94+
const expected = path.join(os.homedir(), "somewhere", "..");
9495
await changeCwdSetting(cwd);
95-
assert.strictEqual(await validateCwdSetting(undefined), os.homedir());
96+
assert.strictEqual(await validateCwdSetting(undefined), expected);
97+
});
98+
99+
it("Handles relative paths", async function () {
100+
await changeCwdSetting("./BinaryModule");
101+
const expected = path.join(workspace, "./BinaryModule");
102+
assert.strictEqual(await validateCwdSetting(undefined), expected);
96103
});
97104
});
98105
});

0 commit comments

Comments
 (0)