Skip to content

Commit daa14b2

Browse files
committed
fix: add markers to extract shell profile path
1 parent 444bc12 commit daa14b2

File tree

3 files changed

+105
-5
lines changed

3 files changed

+105
-5
lines changed

src/features/terminal/shells/common/shellUtils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,17 @@ export function getShellDeactivationCommand(
7878

7979
return deactivation;
8080
}
81+
82+
export const PROFILE_TAG_START = '###VSCODE_PROFILE_PATH_START###';
83+
export const PROFILE_TAG_END = '###VSCODE_PROFILE_PATH_END###';
84+
export function extractProfilePath(content: string): string | undefined {
85+
// Extract only the part between the tags
86+
const profilePathRegex = new RegExp(`${PROFILE_TAG_START}\\r?\\n(.*?)\\r?\\n${PROFILE_TAG_END}`, 's');
87+
const match = content?.match(profilePathRegex);
88+
89+
if (match && match[1]) {
90+
const extractedPath = match[1].trim();
91+
return extractedPath;
92+
}
93+
return undefined;
94+
}

src/features/terminal/shells/pwsh/pwshStartup.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { runCommand } from '../utils';
99

1010
import { ShellConstants } from '../../../common/shellConstants';
1111
import { hasStartupCode, insertStartupCode, removeStartupCode } from '../common/editUtils';
12+
import { extractProfilePath, PROFILE_TAG_END, PROFILE_TAG_START } from '../common/shellUtils';
1213
import { POWERSHELL_ENV_KEY } from './pwshConstants';
1314

1415
async function isPowerShellInstalled(shell: string): Promise<boolean> {
@@ -23,13 +24,18 @@ async function isPowerShellInstalled(shell: string): Promise<boolean> {
2324

2425
async function getProfileForShell(shell: 'powershell' | 'pwsh'): Promise<string> {
2526
try {
26-
const profilePath = await runCommand(
27-
isWindows() ? `${shell} -Command $profile` : `${shell} -Command \\$profile`,
27+
const content = await runCommand(
28+
isWindows()
29+
? `${shell} -Command "Write-Output '${PROFILE_TAG_START}'; Write-Output $profile; Write-Output '${PROFILE_TAG_END}'"`
30+
: `${shell} -Command "Write-Output '${PROFILE_TAG_START}'; Write-Output \\$profile; Write-Output '${PROFILE_TAG_END}'"`,
2831
);
29-
traceInfo(`SHELL: ${shell} profile found at: ${profilePath}`);
3032

31-
if (profilePath) {
32-
return profilePath.trim();
33+
if (content) {
34+
const profilePath = extractProfilePath(content);
35+
if (profilePath) {
36+
traceInfo(`SHELL: ${shell} profile found at: ${profilePath}`);
37+
return profilePath;
38+
}
3339
}
3440
} catch (err) {
3541
traceError(`${shell} failed to get profile path`, err);
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as assert from 'assert';
2+
import {
3+
extractProfilePath,
4+
PROFILE_TAG_END,
5+
PROFILE_TAG_START,
6+
} from '../../../../../features/terminal/shells/common/shellUtils';
7+
8+
suite('Shell Utils', () => {
9+
suite('extractProfilePath', () => {
10+
test('should return undefined when content is empty', () => {
11+
const content = '';
12+
const result = extractProfilePath(content);
13+
assert.strictEqual(result, undefined);
14+
});
15+
16+
test('should return undefined when content does not have tags', () => {
17+
const content = 'sample content without tags';
18+
const result = extractProfilePath(content);
19+
assert.strictEqual(result, undefined);
20+
});
21+
22+
test('should return undefined when only start tag exists', () => {
23+
const content = `content\n${PROFILE_TAG_START}\nsome path`;
24+
const result = extractProfilePath(content);
25+
assert.strictEqual(result, undefined);
26+
});
27+
28+
test('should return undefined when only end tag exists', () => {
29+
const content = `content\nsome path\n${PROFILE_TAG_END}`;
30+
const result = extractProfilePath(content);
31+
assert.strictEqual(result, undefined);
32+
});
33+
34+
test('should return undefined when tags are in wrong order', () => {
35+
const content = `content\n${PROFILE_TAG_END}\nsome path\n${PROFILE_TAG_START}`;
36+
const result = extractProfilePath(content);
37+
assert.strictEqual(result, undefined);
38+
});
39+
test('should return undefined when content between tags is empty', () => {
40+
const content = `content\n${PROFILE_TAG_START}\n\n${PROFILE_TAG_END}\nmore content`;
41+
const result = extractProfilePath(content);
42+
assert.strictEqual(result, undefined);
43+
});
44+
45+
test('should extract path when found between tags', () => {
46+
const expectedPath = '/usr/local/bin/python';
47+
const content = `content\n${PROFILE_TAG_START}\n${expectedPath}\n${PROFILE_TAG_END}\nmore content`;
48+
const result = extractProfilePath(content);
49+
assert.strictEqual(result, expectedPath);
50+
});
51+
52+
test('should trim whitespace from extracted path', () => {
53+
const expectedPath = '/usr/local/bin/python';
54+
const content = `content\n${PROFILE_TAG_START}\n ${expectedPath} \n${PROFILE_TAG_END}\nmore content`;
55+
const result = extractProfilePath(content);
56+
assert.strictEqual(result, expectedPath);
57+
});
58+
59+
test('should handle Windows-style line endings', () => {
60+
const expectedPath = 'C:\\Python\\python.exe';
61+
const content = `content\r\n${PROFILE_TAG_START}\r\n${expectedPath}\r\n${PROFILE_TAG_END}\r\nmore content`;
62+
const result = extractProfilePath(content);
63+
assert.strictEqual(result, expectedPath);
64+
});
65+
66+
test('should extract path with special characters', () => {
67+
const expectedPath = '/path with spaces/and (parentheses)/python';
68+
const content = `${PROFILE_TAG_START}\n${expectedPath}\n${PROFILE_TAG_END}`;
69+
const result = extractProfilePath(content);
70+
assert.strictEqual(result, expectedPath);
71+
});
72+
73+
test('should extract multiline content correctly', () => {
74+
const expectedPath = 'line1\nline2\nline3';
75+
const content = `${PROFILE_TAG_START}\n${expectedPath}\n${PROFILE_TAG_END}`;
76+
const result = extractProfilePath(content);
77+
assert.strictEqual(result, expectedPath);
78+
});
79+
});
80+
});

0 commit comments

Comments
 (0)