Skip to content
This repository was archived by the owner on Oct 23, 2025. It is now read-only.

Commit f04c87f

Browse files
authored
feat: add back button to all necessary flows in UI (#856)
fixes microsoft/vscode-python-environments#523 and microsoft/vscode-python-environments#855
1 parent 82ad744 commit f04c87f

File tree

7 files changed

+929
-257
lines changed

7 files changed

+929
-257
lines changed

src/common/pickers/managers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export async function pickCreator(creators: PythonProjectCreator[]): Promise<Pyt
181181
const selected = await showQuickPickWithButtons(items, {
182182
placeHolder: Pickers.Managers.selectProjectCreator,
183183
ignoreFocusOut: true,
184+
showBackButton: true,
184185
});
185186

186187
if (!selected) {

src/extension.ts

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { EventNames } from './common/telemetry/constants';
1010
import { sendManagerSelectionTelemetry } from './common/telemetry/helpers';
1111
import { sendTelemetryEvent } from './common/telemetry/sender';
1212
import { createDeferred } from './common/utils/deferred';
13-
import { isWindows } from './common/utils/platformUtils';
13+
1414
import {
1515
activeTerminal,
1616
createLogOutputChannel,
17-
createTerminal,
1817
onDidChangeActiveTerminal,
1918
onDidChangeTerminalShellIntegration,
2019
} from './common/window.apis';
@@ -71,15 +70,12 @@ import {
7170
collectEnvironmentInfo,
7271
getEnvManagerAndPackageManagerConfigLevels,
7372
resolveDefaultInterpreter,
73+
runPetInTerminalImpl,
7474
} from './helpers';
7575
import { EnvironmentManagers, ProjectCreators, PythonProjectManager } from './internal.api';
7676
import { registerSystemPythonFeatures } from './managers/builtin/main';
7777
import { SysPythonManager } from './managers/builtin/sysPythonManager';
78-
import {
79-
createNativePythonFinder,
80-
getNativePythonToolsPath,
81-
NativePythonFinder,
82-
} from './managers/common/nativePythonFinder';
78+
import { createNativePythonFinder, NativePythonFinder } from './managers/common/nativePythonFinder';
8379
import { IDisposable } from './managers/common/types';
8480
import { registerCondaFeatures } from './managers/conda/main';
8581
import { registerPipenvFeatures } from './managers/pipenv/main';
@@ -365,64 +361,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
365361
}),
366362
commands.registerCommand('python-envs.runPetInTerminal', async () => {
367363
try {
368-
const petPath = await getNativePythonToolsPath();
369-
370-
// Show quick pick menu for PET operation selection
371-
const selectedOption = await window.showQuickPick(
372-
[
373-
{
374-
label: 'Find All Environments',
375-
description: 'Finds all environments and reports them to the standard output',
376-
detail: 'Runs: pet find --verbose',
377-
},
378-
{
379-
label: 'Resolve Environment...',
380-
description: 'Resolves & reports the details of the environment to the standard output',
381-
detail: 'Runs: pet resolve <path>',
382-
},
383-
],
384-
{
385-
placeHolder: 'Select a Python Environment Tool (PET) operation',
386-
ignoreFocusOut: true,
387-
},
388-
);
389-
390-
if (!selectedOption) {
391-
return; // User cancelled
392-
}
393-
394-
const terminal = createTerminal({
395-
name: 'Python Environment Tool (PET)',
396-
});
397-
terminal.show();
398-
399-
if (selectedOption.label === 'Find All Environments') {
400-
// Run pet find --verbose
401-
terminal.sendText(`"${petPath}" find --verbose`, true);
402-
traceInfo(`Running PET find command: ${petPath} find --verbose`);
403-
} else if (selectedOption.label === 'Resolve Environment...') {
404-
// Show input box for path
405-
const placeholder = isWindows() ? 'C:\\path\\to\\python\\executable' : '/path/to/python/executable';
406-
const inputPath = await window.showInputBox({
407-
prompt: 'Enter the path to the Python executable to resolve',
408-
placeHolder: placeholder,
409-
ignoreFocusOut: true,
410-
validateInput: (value) => {
411-
if (!value || value.trim().length === 0) {
412-
return 'Please enter a valid path';
413-
}
414-
return null;
415-
},
416-
});
417-
418-
if (!inputPath) {
419-
return; // User cancelled
420-
}
421-
422-
// Run pet resolve with the provided path
423-
terminal.sendText(`"${petPath}" resolve "${inputPath.trim()}"`, true);
424-
traceInfo(`Running PET resolve command: ${petPath} resolve "${inputPath.trim()}"`);
425-
}
364+
await runPetInTerminalImpl();
426365
} catch (error) {
427366
traceError('Error running PET in terminal', error);
428367
window.showErrorMessage(`Failed to run Python Environment Tool: ${error}`);

src/helpers.ts

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import { ExtensionContext, extensions, Uri, workspace } from 'vscode';
1+
import { ExtensionContext, extensions, QuickInputButtons, Uri, window, workspace } from 'vscode';
22
import { PythonEnvironment, PythonEnvironmentApi } from './api';
33
import { traceError, traceInfo, traceWarn } from './common/logging';
44
import { normalizePath } from './common/utils/pathUtils';
5+
import { isWindows } from './common/utils/platformUtils';
6+
import { createTerminal, showInputBoxWithButtons } from './common/window.apis';
57
import { getConfiguration } from './common/workspace.apis';
68
import { getAutoActivationType } from './features/terminal/utils';
79
import { EnvironmentManagers, PythonProjectManager } from './internal.api';
8-
import { NativeEnvInfo, NativePythonFinder } from './managers/common/nativePythonFinder';
10+
import { getNativePythonToolsPath, NativeEnvInfo, NativePythonFinder } from './managers/common/nativePythonFinder';
911

1012
/**
1113
* Collects relevant Python environment information for issue reporting
@@ -137,6 +139,90 @@ export function getUserConfiguredSetting<T>(section: string, key: string): T | u
137139
return undefined;
138140
}
139141

142+
/**
143+
* Runs the Python Environment Tool (PET) in a terminal window, allowing users to
144+
* execute various PET commands like finding all Python environments or resolving
145+
* the details of a specific environment.
146+
*
147+
*
148+
* @returns A Promise that resolves when the PET command has been executed or cancelled
149+
*/
150+
export async function runPetInTerminalImpl(): Promise<void> {
151+
const petPath = await getNativePythonToolsPath();
152+
153+
// Show quick pick menu for PET operation selection
154+
const selectedOption = await window.showQuickPick(
155+
[
156+
{
157+
label: 'Find All Environments',
158+
description: 'Finds all environments and reports them to the standard output',
159+
detail: 'Runs: pet find --verbose',
160+
},
161+
{
162+
label: 'Resolve Environment...',
163+
description: 'Resolves & reports the details of the environment to the standard output',
164+
detail: 'Runs: pet resolve <path>',
165+
},
166+
],
167+
{
168+
placeHolder: 'Select a Python Environment Tool (PET) operation',
169+
ignoreFocusOut: true,
170+
},
171+
);
172+
173+
if (!selectedOption) {
174+
return; // User cancelled
175+
}
176+
177+
if (selectedOption.label === 'Find All Environments') {
178+
// Create and show terminal immediately for 'Find All Environments' option
179+
const terminal = createTerminal({
180+
name: 'Python Environment Tool (PET)',
181+
});
182+
terminal.show();
183+
184+
// Run pet find --verbose
185+
terminal.sendText(`"${petPath}" find --verbose`, true);
186+
traceInfo(`Running PET find command: ${petPath} find --verbose`);
187+
} else if (selectedOption.label === 'Resolve Environment...') {
188+
try {
189+
// Show input box for path with back button
190+
const placeholder = isWindows() ? 'C:\\path\\to\\python\\executable' : '/path/to/python/executable';
191+
const inputPath = await showInputBoxWithButtons({
192+
prompt: 'Enter the path to the Python executable to resolve',
193+
placeHolder: placeholder,
194+
ignoreFocusOut: true,
195+
showBackButton: true,
196+
validateInput: (value) => {
197+
if (!value || value.trim().length === 0) {
198+
return 'Please enter a valid path';
199+
}
200+
return null;
201+
},
202+
});
203+
204+
if (inputPath) {
205+
// Only create and show terminal after path has been entered
206+
const terminal = createTerminal({
207+
name: 'Python Environment Tool (PET)',
208+
});
209+
terminal.show();
210+
211+
// Run pet resolve with the provided path
212+
terminal.sendText(`"${petPath}" resolve "${inputPath.trim()}"`, true);
213+
traceInfo(`Running PET resolve command: ${petPath} resolve "${inputPath.trim()}"`);
214+
}
215+
} catch (ex) {
216+
if (ex === QuickInputButtons.Back) {
217+
// If back button was clicked, restart the flow
218+
await runPetInTerminalImpl();
219+
return;
220+
}
221+
throw ex; // Re-throw other errors
222+
}
223+
}
224+
}
225+
140226
/**
141227
* Sets the default Python interpreter for the workspace if the user has not explicitly set 'defaultEnvManager'.
142228
* @param nativeFinder - used to resolve interpreter paths.

0 commit comments

Comments
 (0)