diff --git a/src/client/common/application/commands.ts b/src/client/common/application/commands.ts index 41bbe8b4f4ea..69ae15cceb93 100644 --- a/src/client/common/application/commands.ts +++ b/src/client/common/application/commands.ts @@ -8,6 +8,7 @@ import { Commands as LSCommands } from '../../activation/commands'; import { TensorBoardEntrypoint, TensorBoardEntrypointTrigger } from '../../tensorBoard/constants'; import { Channel, Commands, CommandSource } from '../constants'; import { CreateEnvironmentOptions } from '../../pythonEnvironments/creation/proposed.createEnvApis'; +import { EnvsExtensionCommands, TerminalPythonExecutionOptions } from '../../envsExt/commands'; export type CommandsWithoutArgs = keyof ICommandNameWithoutArgumentTypeMapping; @@ -115,4 +116,5 @@ export interface ICommandNameArgumentTypeMapping extends ICommandNameWithoutArgu }, ]; ['cursorEnd']: []; + [EnvsExtensionCommands.RUN_IN_TERMINAL]: [Uri | TerminalPythonExecutionOptions]; } diff --git a/src/client/envsExt/commands.ts b/src/client/envsExt/commands.ts new file mode 100644 index 000000000000..1e630c6c5d56 --- /dev/null +++ b/src/client/envsExt/commands.ts @@ -0,0 +1,15 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import { Uri } from 'vscode'; +import { PythonEnvironment, PythonProject } from './types'; + +export namespace EnvsExtensionCommands { + export const RUN_IN_TERMINAL = 'python-envs.runInTerminal'; +} + +export interface TerminalPythonExecutionOptions { + project: PythonProject; + args: string[]; + useDedicatedTerminal?: Uri; + environment?: PythonEnvironment; +} diff --git a/src/client/envsExt/envsExtension.ts b/src/client/envsExt/envsExtension.ts index 640b66f95beb..ac5b4fb455b0 100644 --- a/src/client/envsExt/envsExtension.ts +++ b/src/client/envsExt/envsExtension.ts @@ -1,5 +1,7 @@ +import { Uri } from 'vscode'; import { getExtension } from '../common/vscodeApis/extensionsApi'; -import { PythonEnvironmentApi } from './types'; +import { PythonEnvironmentApi, PythonProject } from './types'; +import { TerminalPythonExecutionOptions } from './commands'; export const ENVS_EXTENSION_ID = 'ms-python.vscode-python-envs'; @@ -8,14 +10,42 @@ export async function getEnvsApi(): Promise { if (api) { return api; } - const extension = getExtension(ENVS_EXTENSION_ID); if (extension) { if (!extension.isActive) { await extension.activate(); - api = extension.exports; - return api; } + api = extension.exports; + return api; } return undefined; } + +let isInstalled: boolean | undefined; +export function isEnvsExtensionInstalled(): boolean { + if (isInstalled !== undefined) { + return !!isInstalled; + } + + const extension = getExtension(ENVS_EXTENSION_ID); + isInstalled = extension && extension.isActive; + return !!isInstalled; +} + +export function getPythonProject(uri: Uri): PythonProject | undefined { + return api?.getPythonProject(uri); +} + +export function getRunInTerminalOptions(uri: Uri, useDedicated: boolean): Uri | TerminalPythonExecutionOptions { + if (useDedicated) { + const pr = getPythonProject(uri); + if (pr) { + return { + project: pr, + args: [uri.fsPath], + useDedicatedTerminal: uri, + }; + } + } + return uri; +} diff --git a/src/client/extensionActivation.ts b/src/client/extensionActivation.ts index 429004e951cb..292d3bc3dbce 100644 --- a/src/client/extensionActivation.ts +++ b/src/client/extensionActivation.ts @@ -55,6 +55,7 @@ import { StopWatch } from './common/utils/stopWatch'; import { registerReplCommands, registerReplExecuteOnEnter, registerStartNativeReplCommand } from './repl/replCommands'; import { registerTriggerForTerminalREPL } from './terminals/codeExecution/terminalReplWatcher'; import { registerPythonStartup } from './terminals/pythonStartup'; +import { getEnvsApi } from './envsExt/envsExtension'; export async function activateComponents( // `ext` is passed to any extra activation funcs. @@ -167,6 +168,9 @@ async function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): const interpreterManager = serviceContainer.get(IInterpreterService); interpreterManager.initialize(); if (!workspaceService.isVirtualWorkspace) { + setImmediate(async () => { + await getEnvsApi(); + }); const handlers = serviceManager.getAll(IDebugSessionEventHandlers); const dispatcher = new DebugSessionEventDispatcher(handlers, DebugService.instance, disposables); dispatcher.registerEventHandlers(); diff --git a/src/client/terminals/codeExecution/codeExecutionManager.ts b/src/client/terminals/codeExecution/codeExecutionManager.ts index 061918b7a74a..ebd9bdb0099d 100644 --- a/src/client/terminals/codeExecution/codeExecutionManager.ts +++ b/src/client/terminals/codeExecution/codeExecutionManager.ts @@ -22,6 +22,8 @@ import { CreateEnvironmentCheckKind, triggerCreateEnvironmentCheckNonBlocking, } from '../../pythonEnvironments/creation/createEnvironmentTrigger'; +import { EnvsExtensionCommands } from '../../envsExt/commands'; +import { getPythonProject, getRunInTerminalOptions, isEnvsExtensionInstalled } from '../../envsExt/envsExtension'; @injectable() export class CodeExecutionManager implements ICodeExecutionManager { @@ -45,6 +47,17 @@ export class CodeExecutionManager implements ICodeExecutionManager { this.disposableRegistry.push( this.commandManager.registerCommand(cmd as any, async (file: Resource) => { traceVerbose(`Attempting to run Python file`, file?.fsPath); + + if (file && isEnvsExtensionInstalled()) { + this.commandManager + .executeCommand( + EnvsExtensionCommands.RUN_IN_TERMINAL, + getRunInTerminalOptions(file, cmd === Commands.Exec_In_Separate_Terminal), + ) + .then(noop, noop); + return; + } + const interpreterService = this.serviceContainer.get(IInterpreterService); const interpreter = await interpreterService.getActiveInterpreter(file); if (!interpreter) {