Skip to content

Commit 42af186

Browse files
committed
Add a setting to activate environment in the current open terminal
1 parent 9315191 commit 42af186

File tree

8 files changed

+82
-7
lines changed

8 files changed

+82
-7
lines changed

news/1 Enhancements/7665.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added excension option `activateEnvInCurrentTerminal` to detect if environment should be activated in the current open terminal.

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,12 @@
22892289
"description": "Python launch arguments to use when executing a file in the terminal.",
22902290
"scope": "resource"
22912291
},
2292+
"python.terminal.activateEnvInCurrentTerminal": {
2293+
"type": "boolean",
2294+
"default": false,
2295+
"description": "Activate Python Environment in the current Terminal on load of the Extension.",
2296+
"scope": "resource"
2297+
},
22922298
"python.testing.cwd": {
22932299
"type": "string",
22942300
"default": null,

src/client/common/configSettings.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ export class PythonSettings implements IPythonSettings {
354354
this.terminal = this.terminal ? this.terminal : {
355355
executeInFileDir: true,
356356
launchArgs: [],
357-
activateEnvironment: true
357+
activateEnvironment: true,
358+
activateEnvInCurrentTerminal: false
358359
};
359360

360361
const experiments = systemVariables.resolveAny(pythonSettings.get<IExperiments>('experiments'))!;

src/client/common/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ export interface ITerminalSettings {
276276
readonly executeInFileDir: boolean;
277277
readonly launchArgs: string[];
278278
readonly activateEnvironment: boolean;
279+
readonly activateEnvInCurrentTerminal: boolean;
279280
}
280281

281282
export interface IExperiments {

src/client/extension.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ async function activateUnsafe(context: ExtensionContext): Promise<IExtensionApi>
183183
context.subscriptions.push(deprecationMgr);
184184

185185
context.subscriptions.push(new ReplProvider(serviceContainer));
186-
context.subscriptions.push(new TerminalProvider(serviceContainer));
186+
187+
const terminalProvider = new TerminalProvider(serviceContainer);
188+
await terminalProvider.initialize(window.activeTerminal);
189+
context.subscriptions.push(terminalProvider);
187190

188191
context.subscriptions.push(languages.registerCodeActionsProvider(PYTHON, new PythonCodeActionProvider(), { providedCodeActionKinds: [CodeActionKind.SourceOrganizeImports] }));
189192

src/client/providers/terminalProvider.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
import { Disposable, Uri } from 'vscode';
4+
import { Disposable, Terminal, Uri } from 'vscode';
55
import { ICommandManager, IDocumentManager, IWorkspaceService } from '../common/application/types';
66
import { Commands } from '../common/constants';
7-
import { ITerminalServiceFactory } from '../common/terminal/types';
7+
import { ITerminalActivator, ITerminalServiceFactory } from '../common/terminal/types';
8+
import { IConfigurationService } from '../common/types';
89
import { IServiceContainer } from '../ioc/types';
910
import { captureTelemetry } from '../telemetry';
1011
import { EventName } from '../telemetry/constants';
@@ -14,6 +15,15 @@ export class TerminalProvider implements Disposable {
1415
constructor(private serviceContainer: IServiceContainer) {
1516
this.registerCommands();
1617
}
18+
public async initialize(currentTerminal: Terminal | undefined) {
19+
const configuration = this.serviceContainer.get<IConfigurationService>(IConfigurationService);
20+
const pythonSettings = configuration.getSettings();
21+
22+
if (pythonSettings.terminal.activateEnvInCurrentTerminal && currentTerminal) {
23+
const terminalActivator = this.serviceContainer.get<ITerminalActivator>(ITerminalActivator);
24+
await terminalActivator.activateEnvironmentInTerminal(currentTerminal, undefined, true);
25+
}
26+
}
1727
public dispose() {
1828
this.disposables.forEach(disposable => disposable.dispose());
1929
}

src/test/datascience/dataScienceIocContainer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,8 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
510510
this.pythonSettings.terminal = {
511511
executeInFileDir: false,
512512
launchArgs: [],
513-
activateEnvironment: true
513+
activateEnvironment: true,
514+
activateEnvInCurrentTerminal: false
514515
};
515516

516517
condaService.setup(c => c.isCondaAvailable()).returns(() => Promise.resolve(false));

src/test/providers/terminal.unit.test.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
import { expect } from 'chai';
55
import * as TypeMoq from 'typemoq';
6-
import { Disposable, TextDocument, TextEditor, Uri, WorkspaceFolder } from 'vscode';
6+
import { Disposable, Terminal, TextDocument, TextEditor, Uri, WorkspaceFolder } from 'vscode';
77
import { ICommandManager, IDocumentManager, IWorkspaceService } from '../../client/common/application/types';
88
import { Commands } from '../../client/common/constants';
99
import { TerminalService } from '../../client/common/terminal/service';
10-
import { ITerminalServiceFactory } from '../../client/common/terminal/types';
10+
import { ITerminalActivator, ITerminalServiceFactory } from '../../client/common/terminal/types';
11+
import { IConfigurationService, IPythonSettings, ITerminalSettings } from '../../client/common/types';
1112
import { IServiceContainer } from '../../client/ioc/types';
1213
import { TerminalProvider } from '../../client/providers/terminalProvider';
1314

@@ -149,4 +150,55 @@ suite('Terminal Provider', () => {
149150
commandHandler!.call(terminalProvider);
150151
terminalService.verify(t => t.show(false), TypeMoq.Times.once());
151152
});
153+
154+
suite('terminal.activateCurrentTerminal setting', () => {
155+
156+
let pythonSettings: TypeMoq.IMock<IPythonSettings>;
157+
let terminalSettings: TypeMoq.IMock<ITerminalSettings>;
158+
let configService: TypeMoq.IMock<IConfigurationService>;
159+
let terminalActivator: TypeMoq.IMock<ITerminalActivator>;
160+
let terminal: TypeMoq.IMock<Terminal>;
161+
162+
setup(() => {
163+
configService = TypeMoq.Mock.ofType<IConfigurationService>();
164+
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IConfigurationService))).returns(() => configService.object);
165+
pythonSettings = TypeMoq.Mock.ofType<IPythonSettings>();
166+
configService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => pythonSettings.object);
167+
168+
terminalSettings = TypeMoq.Mock.ofType<ITerminalSettings>();
169+
pythonSettings.setup(s => s.terminal).returns(() => terminalSettings.object);
170+
171+
terminalActivator = TypeMoq.Mock.ofType<ITerminalActivator>();
172+
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ITerminalActivator))).returns(() => terminalActivator.object);
173+
174+
terminal = TypeMoq.Mock.ofType<Terminal>();
175+
});
176+
177+
test('If terminal.activateCurrentTerminal setting is set, provided terminal should be activated', async () => {
178+
terminalSettings.setup(t => t.activateEnvInCurrentTerminal).returns(() => true);
179+
180+
terminalProvider = new TerminalProvider(serviceContainer.object);
181+
await terminalProvider.initialize(terminal.object);
182+
183+
terminalActivator.verify(a => a.activateEnvironmentInTerminal(terminal.object, undefined, true), TypeMoq.Times.once());
184+
});
185+
186+
test('If terminal.activateCurrentTerminal setting is not set, provided terminal should not be activated', async () => {
187+
terminalSettings.setup(t => t.activateEnvInCurrentTerminal).returns(() => false);
188+
189+
terminalProvider = new TerminalProvider(serviceContainer.object);
190+
await terminalProvider.initialize(terminal.object);
191+
192+
terminalActivator.verify(a => a.activateEnvironmentInTerminal(TypeMoq.It.isAny(), undefined, true), TypeMoq.Times.never());
193+
});
194+
195+
test('terminal.activateCurrentTerminal setting is set but provided terminal is undefined', async () => {
196+
terminalSettings.setup(t => t.activateEnvInCurrentTerminal).returns(() => true);
197+
198+
terminalProvider = new TerminalProvider(serviceContainer.object);
199+
await terminalProvider.initialize(undefined);
200+
201+
terminalActivator.verify(a => a.activateEnvironmentInTerminal(TypeMoq.It.isAny(), undefined, true), TypeMoq.Times.never());
202+
});
203+
});
152204
});

0 commit comments

Comments
 (0)