1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-04-22 01:15:48 +02:00

Show possible IDs based on the action's shortcuts

Fixes VIM-3499
This commit is contained in:
Matt Ellis 2024-07-12 08:54:25 +01:00 committed by Alex Pláte
parent 64f7532510
commit e07a16863e
5 changed files with 48 additions and 18 deletions
README.md
doc
src/main
java/com/maddyhome/idea/vim
resources/messages

View File

@ -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"/>

View File

@ -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)```

View File

@ -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>) {
@ -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)
}

View File

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

View File

@ -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}