Skip to content

Commit

Permalink
Show possible IDs based on the action's shortcuts
Browse files Browse the repository at this point in the history
Fixes VIM-3499
  • Loading branch information
citizenmatt committed Jul 12, 2024
1 parent c0419d6 commit 0d2dce0
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 18 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<Action>` 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`).

<details>
<summary><strong>"Track action Ids" Details</strong> (click to see)</summary>
<summary><strong>"Track action IDs" Details</strong> (click to see)</summary>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/readme/track_action_dark.gif">
<img src="assets/readme/track_action_light.gif" alt="track action ids"/>
Expand Down
4 changes: 2 additions & 2 deletions doc/marketplace-plugin-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ Using actions from external plugins is the same, as tracking and reusing any IDE
1. Install the plugin via Marketplace
2. Enable action tracking. You can enable it by one of the following ways:
* Execute `:set trackactionids` ex command or just `:set tai`
* Open the "Find actions" window by pressing `Ctrl-Shift-A` and search for "Track Action Ids" to find the toggle that enables and disables action tracking
* Open the "Find actions" window by pressing `Ctrl-Shift-A` and search for "Track Action IDs" to find the toggle that enables and disables action tracking
3. Execute the plugin action the way intended by plugin author "See Edit menu or use ⇧ + ⌥ + U / Shift + Alt + U" or just find the `Toggle Camel Case` action in the "Find actions" window (`Ctrl-Shift-A`). If you action tracking is on, you will see this notification in your right bottom corner:

<img alt="Notification" src="images/action-id-notification.png"/>
4. Copy the action id from the notification to create the following mapping in your .ideavimrc
```map <leader>t <Action>(de.netnexus.CamelCasePlugin.ToggleCamelCase)```
```map <leader>t <Action>(de.netnexus.CamelCasePlugin.ToggleCamelCase)```
31 changes: 21 additions & 10 deletions src/main/java/com/maddyhome/idea/vim/group/NotificationService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ internal class NotificationService(private val project: Project?) {
).notify(project)
}

fun notifyActionId(id: String?) {
ActionIdNotifier.notifyActionId(id, project)
fun notifyActionId(id: String?, candidates: List<String>? = null) {
ActionIdNotifier.notifyActionId(id, project, candidates)
}

fun notifyKeymapIssues(issues: ArrayList<KeyMapIssue>) {
Expand Down Expand Up @@ -259,20 +259,31 @@ internal class NotificationService(private val project: Project?) {

object ActionIdNotifier {
private var notification: Notification? = null
private const val NO_ID = "<i>Cannot detect action id</i>"

fun notifyActionId(id: String?, project: Project?) {
fun notifyActionId(id: String?, project: Project?, candidates: List<String>? = null) {
notification?.expire()

val content = if (id != null) "Action id: $id" else NO_ID
Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).let {
notification = it
it.whenExpired { notification = null }
it.setContent(it.content + "<br><br><small>Use ${ActionCenter.getToolwindowName()} to see previous ids</small>")
val possibleIDs = candidates?.distinct()?.sorted()
val content = when {
id != null -> "Action ID: <code>$id</code><br><br>"
possibleIDs.isNullOrEmpty() -> "<i>Cannot detect action ID</i><br><br>"
possibleIDs.size == 1 -> "Possible action ID: <code>${possibleIDs[0]}</code><br><br>"
else -> {
buildString {
append("<p>Multiple possible action IDs. Candidates include:<ul>")
possibleIDs.forEach { append("<li><code>$it</code></li>") }
append("</ul></p>")
}
}
} + "<small>See the ${ActionCenter.getToolwindowName()} tool window for previous IDs</small>"

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)
}
Expand Down
21 changes: 20 additions & 1 deletion src/main/java/com/maddyhome/idea/vim/listener/IdeaSpecifics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/messages/IdeaVimBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down

0 comments on commit 0d2dce0

Please sign in to comment.