From 0d2dce03e4b72a90af3af843e333a55041f8fb24 Mon Sep 17 00:00:00 2001
From: Matt Ellis
Date: Fri, 12 Jul 2024 08:54:25 +0100
Subject: [PATCH] Show possible IDs based on the action's shortcuts
Fixes VIM-3499
---
README.md | 6 ++--
doc/marketplace-plugin-example.md | 4 +--
.../idea/vim/group/NotificationService.kt | 31 +++++++++++++------
.../idea/vim/listener/IdeaSpecifics.kt | 21 ++++++++++++-
.../messages/IdeaVimBundle.properties | 4 +--
5 files changed, 48 insertions(+), 18 deletions(-)
diff --git a/README.md b/README.md
index 214013c9a8..b2963169d9 100644
--- a/README.md
+++ b/README.md
@@ -222,13 +222,13 @@ Ex commands or via `:map` command mappings:
* Execute an action by `{action_id}`. Works from Ex command line.
* Please don't use `:action` in mappings. Use `` instead.
-### Finding action ids:
+### Finding action IDs:
-* IJ provides `IdeaVim: track action Ids` command to show the id of the executed actions.
+* IJ provides `IdeaVim: track action IDs` command to show the id of the executed actions.
This command can be found in "Search everywhere" (double `shift`).
- "Track action Ids" Details (click to see)
+ "Track action IDs" Details (click to see)
")
+ }
+ }
+ } + "See the ${ActionCenter.getToolwindowName()} tool window for previous IDs"
+ notification = Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).also {
+ it.whenExpired { notification = null }
it.addAction(StopTracking())
- if (id != null) it.addAction(CopyActionId(id, project))
+ if (id != null || possibleIDs?.size == 1) {
+ it.addAction(CopyActionId(id ?: possibleIDs?.get(0), project))
+ }
it.notify(project)
}
diff --git a/src/main/java/com/maddyhome/idea/vim/listener/IdeaSpecifics.kt b/src/main/java/com/maddyhome/idea/vim/listener/IdeaSpecifics.kt
index 74278c214a..f21d0c1b32 100644
--- a/src/main/java/com/maddyhome/idea/vim/listener/IdeaSpecifics.kt
+++ b/src/main/java/com/maddyhome/idea/vim/listener/IdeaSpecifics.kt
@@ -28,6 +28,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.ex.AnActionListener
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.keymap.KeymapManager
import com.intellij.openapi.project.DumbAwareToggleAction
import com.intellij.openapi.util.TextRange
import com.maddyhome.idea.vim.KeyHandler
@@ -58,6 +59,7 @@ internal object IdeaSpecifics {
private var editor: Editor? = null
private var completionPrevDocumentLength: Int? = null
private var completionPrevDocumentOffset: Int? = null
+
override fun beforeActionPerformed(action: AnAction, event: AnActionEvent) {
if (VimPlugin.isNotEnabled()) return
@@ -70,7 +72,24 @@ internal object IdeaSpecifics {
if (!isVimAction && injector.globalIjOptions().trackactionids) {
if (action !is NotificationService.ActionIdNotifier.CopyActionId && action !is NotificationService.ActionIdNotifier.StopTracking) {
val id: String? = ActionManager.getInstance().getId(action) ?: (action.shortcutSet as? ProxyShortcutSet)?.actionId
- VimPlugin.getNotifications(event.dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id)
+ val candidates = if (id == null) {
+ // Some actions are specific to the component they're registered for, and are copies of a global action,
+ // reusing the action ID and shortcuts (e.g. `NextTab` is different for editor tabs and tool window tabs).
+ // Unfortunately, ActionManager doesn't know about these "local" actions, so can't return the action ID.
+ // However, the new "local" action does copy the shortcuts of the global template action, so we can look up
+ // all actions with matching shortcuts. We might return more action IDs than expected, so this is a list of
+ // candidates, not a definite match of the action being executed, but the list should include our target
+ // action. Note that we might return duplicate IDs because the keymap might have multiple shortcuts mapped
+ // to the same action. The notifier will handle de-duplication and sorting as a presentation detail.
+ action.shortcutSet.shortcuts.flatMap { KeymapManager.getInstance().activeKeymap.getActionIdList(it) }
+ }
+ else {
+ emptyList()
+ }
+
+ // We can still get empty ID and empty candidates. Notably, for the tool window toggle buttons on the new UI.
+ // We could filter out action events with `place == ActionPlaces.TOOLWINDOW_TOOLBAR_BAR`
+ VimPlugin.getNotifications(event.dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id, candidates)
}
}
diff --git a/src/main/resources/messages/IdeaVimBundle.properties b/src/main/resources/messages/IdeaVimBundle.properties
index c17e91b3d7..c847b750c5 100644
--- a/src/main/resources/messages/IdeaVimBundle.properties
+++ b/src/main/resources/messages/IdeaVimBundle.properties
@@ -100,8 +100,8 @@ action.not.found.0=Action not found: {0}
action.CustomizeModeWidget.text=Mode Widget Settings
-action.VimFindActionIdAction.text=IdeaVim: Track Action Ids
-action.VimFindActionIdAction.description=Starts tracking ids of executed actions
+action.VimFindActionIdAction.text=IdeaVim: Track Action IDs
+action.VimFindActionIdAction.description=Starts tracking IDs of executed actions
ex.show.all.actions.0.1=--- Actions ---{0}{1}