[terminal] IJPL-211122 Add an ability to provide actions that should be allowed to execute in terminal

Create the extension point that can be implemented on the plugins side.

GitOrigin-RevId: cdb890b21fbd980a5b06617037ecbf943865bf82
This commit is contained in:
Konstantin Hudyakov
2025-10-21 06:33:35 +00:00
committed by intellij-monorepo-bot
parent f56abee683
commit 800cdcae1f
3 changed files with 26 additions and 6 deletions
@@ -5,6 +5,8 @@
</dependencies>
<extensionPoints>
<extensionPoint qualifiedName="org.jetbrains.plugins.terminal.allowedActionsProvider"
interface="com.intellij.terminal.frontend.view.TerminalAllowedActionsProvider" dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.plugins.terminal.escapeHandler"
interface="com.intellij.terminal.frontend.action.TerminalEscapeHandler" dynamic="true"/>
</extensionPoints>
@@ -0,0 +1,13 @@
package com.intellij.terminal.frontend.view
import com.intellij.openapi.extensions.ExtensionPointName
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Experimental
interface TerminalAllowedActionsProvider {
fun getActionIds(): List<String>
companion object {
internal val EP_NAME = ExtensionPointName.create<TerminalAllowedActionsProvider>("org.jetbrains.plugins.terminal.allowedActionsProvider")
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.registry.Registry
import com.intellij.terminal.JBTerminalSystemSettingsProviderBase
import com.intellij.terminal.frontend.action.SendShortcutToTerminalAction
import com.intellij.terminal.frontend.view.TerminalAllowedActionsProvider
import com.intellij.util.concurrency.ThreadingAssertions
import com.jediterm.terminal.emulator.mouse.MouseMode
import org.intellij.lang.annotations.Language
@@ -98,16 +99,19 @@ private class TerminalEventDispatcher(
fun registerIfNeeded() {
ThreadingAssertions.assertEventDispatchThread()
if (!settings.overrideIdeShortcuts()) return // handled by the listener instead
this.allowedActions = getAllowedActions()
val actionManager = ActionManager.getInstance()
val actions = getAllowedActionIds().mapNotNull { actionManager.getAction(it) }
this.allowedActions = actions
if (!myRegistered) {
IdeEventQueue.getInstance().addDispatcher(this, parentDisposable)
sendShortcutAction.register(editor.contentComponent, getAllowedActions())
sendShortcutAction.register(editor.contentComponent, actions)
myRegistered = true
// The same reasoning as with the initialization:
// the terminal might have been activated with a shortcut that will be immediately followed by a "key typed" event.
// If that's the case, we should ignore that event. If not, the flag will be cleared when the next event is processed.
ignoreNextKeyTypedEvent = true
LOG.trace { "Dispatcher registered: start capturing key events" }
LOG.trace { "Dispatcher registered: start capturing key events. Allowed actions: ${actions.map { it.javaClass.name }}" }
}
}
@@ -140,9 +144,10 @@ private class TerminalEventDispatcher(
return false
}
private fun getAllowedActions(): List<AnAction> {
val actionManager = ActionManager.getInstance()
return ALLOWED_ACTION_IDS.mapNotNull { actionId -> actionManager.getAction(actionId) }
private fun getAllowedActionIds(): List<String> {
val actionIds = LinkedHashSet(ALLOWED_ACTION_IDS)
TerminalAllowedActionsProvider.EP_NAME.extensionList.flatMapTo(actionIds) { it.getActionIds() }
return actionIds.toList()
}
companion object {