From 4025d5d1d32330174c528d63d13bb98f1de237f0 Mon Sep 17 00:00:00 2001 From: Konstantin Hudyakov Date: Thu, 30 Oct 2025 10:09:53 +0200 Subject: [PATCH] [terminal] IJPL-215801 Disable terminal command completion action in Unix PowerShell Make it enabled only for Bash and Zsh. (cherry picked from commit 0d7baf6a13c5dc4d9b5c72176000155dc9591133) IJ-CR-180793 GitOrigin-RevId: fe4a78ea7a1cbf99081c3dc4168bea023e13d1c2 --- .../action/TerminalCommandCompletionActionGen2.kt | 6 +++++- .../frontend/view/impl/TerminalEventsHandlerImpl.kt | 5 +++++ .../terminal/frontend/view/impl/TerminalViewImpl.kt | 2 ++ .../terminal/block/reworked/TerminalCommandCompletion.kt | 5 +++++ .../frontend/completion/TerminalCompletionFixture.kt | 9 +++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/action/TerminalCommandCompletionActionGen2.kt b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/action/TerminalCommandCompletionActionGen2.kt index 1b8edffba9bd..a86fa151eeb0 100644 --- a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/action/TerminalCommandCompletionActionGen2.kt +++ b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/action/TerminalCommandCompletionActionGen2.kt @@ -16,6 +16,7 @@ import org.jetbrains.plugins.terminal.block.reworked.TerminalCommandCompletion import org.jetbrains.plugins.terminal.block.util.TerminalDataContextUtils.isOutputModelEditor import org.jetbrains.plugins.terminal.block.util.TerminalDataContextUtils.isSuppressCompletion import org.jetbrains.plugins.terminal.block.util.TerminalDataContextUtils.terminalEditor +import org.jetbrains.plugins.terminal.session.guessShellName import org.jetbrains.plugins.terminal.util.getNow import org.jetbrains.plugins.terminal.view.shellIntegration.TerminalOutputStatus.TypingCommand @@ -36,9 +37,12 @@ internal class TerminalCommandCompletionActionGen2 : BaseCodeCompletionAction(), override fun update(e: AnActionEvent) { super.update(e) val project = e.project - val isCommandTypingMode = e.terminalView?.shellIntegrationDeferred?.getNow()?.outputStatus?.value == TypingCommand + val terminalView = e.terminalView + val shellName = terminalView?.startupOptionsDeferred?.getNow()?.guessShellName() + val isCommandTypingMode = terminalView?.shellIntegrationDeferred?.getNow()?.outputStatus?.value == TypingCommand e.presentation.isEnabledAndVisible = e.terminalEditor?.isOutputModelEditor == true && project != null && TerminalCommandCompletion.isEnabled(project) + && shellName != null && TerminalCommandCompletion.isSupportedForShell(shellName) && isCommandTypingMode } diff --git a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalEventsHandlerImpl.kt b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalEventsHandlerImpl.kt index 7883e065a09d..aec2cf8fa064 100644 --- a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalEventsHandlerImpl.kt +++ b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalEventsHandlerImpl.kt @@ -20,6 +20,8 @@ import org.jetbrains.plugins.terminal.block.reworked.TerminalCommandCompletion import org.jetbrains.plugins.terminal.block.reworked.TerminalSessionModel import org.jetbrains.plugins.terminal.block.reworked.TerminalUsageLocalStorage import org.jetbrains.plugins.terminal.block.util.TerminalDataContextUtils.isOutputModelEditor +import org.jetbrains.plugins.terminal.session.TerminalStartupOptions +import org.jetbrains.plugins.terminal.session.guessShellName import org.jetbrains.plugins.terminal.session.impl.TerminalState import org.jetbrains.plugins.terminal.util.getNow import org.jetbrains.plugins.terminal.view.TerminalOutputModel @@ -48,6 +50,7 @@ internal open class TerminalEventsHandlerImpl( private val scrollingModel: TerminalOutputScrollingModel?, private val outputModel: TerminalOutputModel, private val shellIntegrationDeferred: Deferred?, + private val startupOptionsDeferred: Deferred?, private val typeAhead: TerminalTypeAhead?, ) : TerminalEventsHandler { private var ignoreNextKeyTypedEvent: Boolean = false @@ -408,9 +411,11 @@ internal open class TerminalEventsHandlerImpl( private fun scheduleCompletionPopupIfNeeded(charTyped: Char) { val project = editor.project ?: return + val shellName = startupOptionsDeferred?.getNow()?.guessShellName() ?: return val shellIntegration = shellIntegrationDeferred?.getNow() ?: return if (editor.isOutputModelEditor && TerminalCommandCompletion.isEnabled(project) + && TerminalCommandCompletion.isSupportedForShell(shellName) && TerminalOptionsProvider.instance.showCompletionPopupAutomatically && shellIntegration.outputStatus.value == TerminalOutputStatus.TypingCommand && canTriggerCompletion(charTyped) diff --git a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt index 948c4bcb93e0..5d8ee1ab78a8 100644 --- a/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt +++ b/plugins/terminal/frontend/src/com/intellij/terminal/frontend/view/impl/TerminalViewImpl.kt @@ -170,6 +170,7 @@ class TerminalViewImpl( scrollingModel = null, alternateBufferModel, shellIntegrationDeferred = null, + startupOptionsDeferred = null, typeAhead = null, ) configureOutputEditor( @@ -217,6 +218,7 @@ class TerminalViewImpl( scrollingModel, outputModel, shellIntegrationDeferred, + startupOptionsDeferred, typeAhead = outputModelController ) diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/block/reworked/TerminalCommandCompletion.kt b/plugins/terminal/src/org/jetbrains/plugins/terminal/block/reworked/TerminalCommandCompletion.kt index 3aa74b563b23..390a76a34b6d 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/block/reworked/TerminalCommandCompletion.kt +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/block/reworked/TerminalCommandCompletion.kt @@ -10,6 +10,7 @@ import com.intellij.platform.eel.provider.getEelDescriptor import com.intellij.util.system.OS import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.TestOnly +import org.jetbrains.plugins.terminal.session.ShellName @ApiStatus.Internal object TerminalCommandCompletion { @@ -22,6 +23,10 @@ object TerminalCommandCompletion { && project.getEelDescriptor() == LocalEelDescriptor // Disable in non-local projects for now as it requires additional support } + fun isSupportedForShell(name: ShellName): Boolean { + return name == ShellName.ZSH || name == ShellName.BASH + } + @TestOnly fun enableForTests(parentDisposable: Disposable) { Registry.get(REGISTRY_KEY).setValue(true, parentDisposable) diff --git a/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/completion/TerminalCompletionFixture.kt b/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/completion/TerminalCompletionFixture.kt index 5604eeafac6b..d7ac1308fb8c 100644 --- a/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/completion/TerminalCompletionFixture.kt +++ b/plugins/terminal/tests/src/com/intellij/terminal/tests/reworked/frontend/completion/TerminalCompletionFixture.kt @@ -28,6 +28,7 @@ import org.jetbrains.plugins.terminal.block.completion.spec.ShellCommandSpecConf import org.jetbrains.plugins.terminal.block.completion.spec.ShellCommandSpecInfo import org.jetbrains.plugins.terminal.block.completion.spec.ShellCommandSpecsProvider import org.jetbrains.plugins.terminal.block.reworked.TerminalCommandCompletion +import org.jetbrains.plugins.terminal.session.impl.TerminalStartupOptionsImpl import org.jetbrains.plugins.terminal.util.terminalProjectScope import org.jetbrains.plugins.terminal.view.TerminalOffset import org.jetbrains.plugins.terminal.view.TerminalOutputModel @@ -56,6 +57,14 @@ class TerminalCompletionFixture(val project: Project, val testRootDisposable: Di val shellIntegration = TerminalShellIntegrationImpl(outputModel, view.sessionModel, terminalScope.childScope("TerminalShellIntegration")) view.shellIntegrationDeferred.complete(shellIntegration) + // Need to specify some options to make `TerminalCommandCompletion.isSupportedForShell` pass. + val startupOptions = TerminalStartupOptionsImpl( + shellCommand = listOf("/bin/zsh", "--login", "-i"), + workingDirectory = project.basePath!!, + envVariables = emptyMap(), + ) + view.startupOptionsDeferred.complete(startupOptions) + shellIntegration.onPromptFinished(TerminalOffset.ZERO) // To make TerminalOutputStatus = TypingCommand assertEquals(TerminalOutputStatus.TypingCommand, shellIntegration.outputStatus.value)