Skip to content

Commit 1f62303

Browse files
committed
fix: Do not activate on pseudoterminals
Currently the extension gets activated on pseudoterminals as the current check for not user-facing terminals does not catch this case. These terminals should be skipped during activation as to avoid unexpected commands and behavior.
1 parent 5118a17 commit 1f62303

3 files changed

Lines changed: 36 additions & 11 deletions

File tree

src/features/terminal/terminalActivationState.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { PythonEnvironment } from '../../api';
1111
import { traceError, traceInfo, traceVerbose } from '../../common/logging';
1212
import { onDidEndTerminalShellExecution, onDidStartTerminalShellExecution } from '../../common/window.apis';
1313
import { getActivationCommand, getDeactivationCommand } from '../common/activation';
14-
import { getShellIntegrationTimeout, isTaskTerminal } from './utils';
14+
import { getShellIntegrationTimeout, isTaskTerminal, shouldSkipTerminalActivation } from './utils';
1515

1616
export interface DidChangeTerminalActivationStateEvent {
1717
terminal: Terminal;
@@ -86,6 +86,11 @@ export class TerminalActivationImpl implements TerminalActivationInternal {
8686
}
8787

8888
async activate(terminal: Terminal, environment: PythonEnvironment): Promise<void> {
89+
if (shouldSkipTerminalActivation(terminal)) {
90+
traceVerbose('Skipping activation for this terminal');
91+
return;
92+
}
93+
8994
if (isTaskTerminal(terminal)) {
9095
traceVerbose('Cannot activate environment in a task terminal');
9196
return;

src/features/terminal/terminalManager.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as fsapi from 'fs-extra';
22
import * as path from 'path';
3-
import { Disposable, EventEmitter, ProgressLocation, Terminal, TerminalOptions, Uri } from 'vscode';
3+
import { Disposable, EventEmitter, ProgressLocation, Terminal, Uri } from 'vscode';
44
import { PythonEnvironment, PythonEnvironmentApi, PythonProject, PythonTerminalCreateOptions } from '../../api';
55
import { ActivationStrings } from '../../common/localize';
66
import { traceInfo, traceVerbose } from '../../common/logging';
@@ -34,6 +34,7 @@ import {
3434
getAutoActivationType,
3535
getEnvironmentForTerminal,
3636
shouldActivateInCurrentTerminal,
37+
shouldSkipTerminalActivation,
3738
waitForShellIntegration,
3839
} from './utils';
3940

@@ -94,7 +95,7 @@ export class TerminalManagerImpl implements TerminalManager {
9495
this.onTerminalClosedEmitter.fire(t);
9596
}),
9697
this.onTerminalOpened(async (t) => {
97-
if (this.skipActivationOnOpen.has(t) || (t.creationOptions as TerminalOptions)?.hideFromUser) {
98+
if (this.skipActivationOnOpen.has(t) || shouldSkipTerminalActivation(t)) {
9899
return;
99100
}
100101
let env = this.ta.getEnvironment(t);
@@ -419,7 +420,11 @@ export class TerminalManagerImpl implements TerminalManager {
419420

420421
if (actType === ACT_TYPE_COMMAND) {
421422
if (!skipPreExistingTerminals) {
422-
await Promise.all(terminals().map(async (t) => this.activateUsingCommand(api, t)));
423+
await Promise.all(
424+
terminals()
425+
.filter((t) => !shouldSkipTerminalActivation(t))
426+
.map(async (t) => this.activateUsingCommand(api, t)),
427+
);
423428
}
424429
} else if (actType === ACT_TYPE_SHELL) {
425430
const shells = new Set(
@@ -431,12 +436,14 @@ export class TerminalManagerImpl implements TerminalManager {
431436
await this.handleSetupCheck(shells);
432437
if (!skipPreExistingTerminals) {
433438
await Promise.all(
434-
terminals().map(async (t) => {
435-
// If the shell is not set up, we activate using command fallback.
436-
if (this.shellSetup.get(identifyTerminalShell(t)) === false) {
437-
await this.activateUsingCommand(api, t);
438-
}
439-
}),
439+
terminals()
440+
.filter((t) => !shouldSkipTerminalActivation(t))
441+
.map(async (t) => {
442+
// If the shell is not set up, we activate using command fallback.
443+
if (this.shellSetup.get(identifyTerminalShell(t)) === false) {
444+
await this.activateUsingCommand(api, t);
445+
}
446+
}),
440447
);
441448
}
442449
}

src/features/terminal/utils.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from 'path';
2-
import { Disposable, env, tasks, Terminal, TerminalOptions, Uri } from 'vscode';
2+
import { Disposable, env, ExtensionTerminalOptions, tasks, Terminal, TerminalOptions, Uri } from 'vscode';
33
import { PythonEnvironment, PythonProject, PythonProjectEnvironmentApi, PythonProjectGetterApi } from '../../api';
44
import { timeout } from '../../common/utils/asyncUtils';
55
import { createSimpleDebounce } from '../../common/utils/debounce';
@@ -355,3 +355,16 @@ export function removeAnsiEscapeCodes(str: string): string {
355355

356356
return str;
357357
}
358+
359+
/**
360+
* Determines if a terminal should be skipped for environment activation based on its creation options.
361+
* Terminals that are hidden from the user or are PTY-based extension terminals are skipped.
362+
* @param terminal The terminal to check.
363+
* @returns `true` if the terminal should be skipped; `false` otherwise.
364+
*/
365+
export function shouldSkipTerminalActivation(terminal: Terminal): boolean {
366+
return (
367+
!!(terminal.creationOptions as TerminalOptions)?.hideFromUser ||
368+
!!(terminal.creationOptions as ExtensionTerminalOptions)?.pty
369+
);
370+
}

0 commit comments

Comments
 (0)