1
0
mirror of https://github.com/chylex/IntelliJ-Keyboard-Master.git synced 2024-10-17 07:42:48 +02:00

Compare commits

...

7 Commits

6 changed files with 86 additions and 41 deletions

View File

@ -8,7 +8,7 @@ plugins {
} }
group = "com.chylex.intellij.keyboardmaster" group = "com.chylex.intellij.keyboardmaster"
version = "0.5.1" version = "0.5.3"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -38,20 +38,11 @@ object VimNavigation {
val originalBindings = (UIManager.get("PopupMenu.selectedWindowInputMapBindings") as Array<*>).also { originalPopupBindings = it } val originalBindings = (UIManager.get("PopupMenu.selectedWindowInputMapBindings") as Array<*>).also { originalPopupBindings = it }
val updatedBindings = mutableListOf(*originalBindings) val updatedBindings = mutableListOf(*originalBindings)
updatedBindings.add(KeyStroke.getKeyStroke('h')) addBinding(updatedBindings, "selectParent", setOf('h', 'p', 'x'))
updatedBindings.add("selectParent") addBinding(updatedBindings, "selectNext", setOf('j'))
addBinding(updatedBindings, "selectPrevious", setOf('k'))
updatedBindings.add(KeyStroke.getKeyStroke('j')) addBinding(updatedBindings, "selectChild", setOf('l', 'o'))
updatedBindings.add("selectNext") addBinding(updatedBindings, "cancel", setOf('q'))
updatedBindings.add(KeyStroke.getKeyStroke('k'))
updatedBindings.add("selectPrevious")
updatedBindings.add(KeyStroke.getKeyStroke('l'))
updatedBindings.add("selectChild")
updatedBindings.add(KeyStroke.getKeyStroke('q'))
updatedBindings.add("cancel")
UIManager.put("PopupMenu.selectedWindowInputMapBindings", updatedBindings.toTypedArray()) UIManager.put("PopupMenu.selectedWindowInputMapBindings", updatedBindings.toTypedArray())
UISettings.getInstance().disableMnemonics = true UISettings.getInstance().disableMnemonics = true
@ -62,6 +53,13 @@ object VimNavigation {
} }
} }
private fun addBinding(bindings: MutableList<Any?>, action: String, chars: Set<Char>) {
for (char in chars) {
bindings.add(KeyStroke.getKeyStroke(char))
bindings.add(action)
}
}
private fun handleEvent(event: AWTEvent) { private fun handleEvent(event: AWTEvent) {
if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled.get()) { if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled.get()) {
when (val source = event.source) { when (val source = event.source) {

View File

@ -2,13 +2,18 @@ package com.chylex.intellij.keyboardmaster.feature.vimNavigation
import com.chylex.intellij.keyboardmaster.PluginDisposableService import com.chylex.intellij.keyboardmaster.PluginDisposableService
import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.KeyboardShortcut
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.project.DumbAwareAction
import com.intellij.toolWindow.InternalDecoratorImpl import com.intellij.toolWindow.InternalDecoratorImpl
import com.intellij.ui.SpeedSearchBase import com.intellij.ui.SpeedSearchBase
import com.intellij.ui.speedSearch.SpeedSearch import com.intellij.ui.speedSearch.SpeedSearch
import com.intellij.ui.speedSearch.SpeedSearchSupply import com.intellij.ui.speedSearch.SpeedSearchSupply
import com.intellij.util.containers.JBIterable
import java.awt.Container
import java.awt.event.ActionEvent import java.awt.event.ActionEvent
import java.awt.event.ActionListener import java.awt.event.ActionListener
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
@ -19,10 +24,29 @@ import javax.swing.KeyStroke
internal open class VimNavigationDispatcher<T : JComponent>(final override val component: T, private val rootNode: KeyStrokeNode.Parent<VimNavigationDispatcher<T>>) : DumbAwareAction(), ComponentHolder { internal open class VimNavigationDispatcher<T : JComponent>(final override val component: T, private val rootNode: KeyStrokeNode.Parent<VimNavigationDispatcher<T>>) : DumbAwareAction(), ComponentHolder {
companion object { companion object {
private val DISPOSABLE = ApplicationManager.getApplication().getService(PluginDisposableService::class.java) private val DISPOSABLE = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
private val EXTRA_SHORTCUTS = setOf( private val ENTER_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0) private fun findOriginalEnterAction(component: JComponent): WrappedAction? {
) var originalEnterAction: WrappedAction? = null
for (container in JBIterable.generate<Container>(component) { it.parent }) {
if (container !is JComponent) {
continue
}
container.getActionForKeyStroke(ENTER_KEY)?.let {
originalEnterAction = WrappedAction.ForActionListener(container, it)
}
for (action in ActionUtil.getActions(container)) {
if (action.shortcutSet.shortcuts.any { it is KeyboardShortcut && it.firstKeyStroke == ENTER_KEY && it.secondKeyStroke == null }) {
originalEnterAction = WrappedAction.ForAnAction(action)
}
}
}
return originalEnterAction
}
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
fun JComponent.getParentToolWindowId(): String? { fun JComponent.getParentToolWindowId(): String? {
@ -30,7 +54,7 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
} }
} }
private val originalEnterAction: ActionListener? = component.getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)) private val originalEnterAction = findOriginalEnterAction(component)
private var currentNode: KeyStrokeNode.Parent<VimNavigationDispatcher<T>> = rootNode private var currentNode: KeyStrokeNode.Parent<VimNavigationDispatcher<T>> = rootNode
var isSearching = AtomicBoolean(false) var isSearching = AtomicBoolean(false)
@ -41,19 +65,20 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
speedSearch?.addChangeListener { speedSearch?.addChangeListener {
if (it.propertyName == SpeedSearchSupply.ENTERED_PREFIX_PROPERTY_NAME && !speedSearch.isPopupActive) { if (it.propertyName == SpeedSearchSupply.ENTERED_PREFIX_PROPERTY_NAME && !speedSearch.isPopupActive) {
isSearching.set(false) isSearching.set(false)
currentNode = rootNode
} }
} }
} }
protected fun getAllKeyStrokes(): Set<KeyStroke> { protected fun getAllKeyStrokes(): Set<KeyStroke> {
return KeyStrokeNode.getAllKeyStrokes(rootNode, EXTRA_SHORTCUTS) return KeyStrokeNode.getAllKeyStrokes(rootNode, setOf(ENTER_KEY))
} }
final override fun actionPerformed(e: AnActionEvent) { final override fun actionPerformed(e: AnActionEvent) {
val keyEvent = e.inputEvent as? KeyEvent ?: return val keyEvent = e.inputEvent as? KeyEvent ?: return
if (keyEvent.id == KeyEvent.KEY_PRESSED && handleSpecialKeyPress(keyEvent)) { if (keyEvent.id == KeyEvent.KEY_PRESSED && keyEvent.keyCode == KeyEvent.VK_ENTER) {
currentNode = rootNode handleEnterKeyPress(e, keyEvent)
return return
} }
@ -66,20 +91,7 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
} }
} }
private fun handleSpecialKeyPress(keyEvent: KeyEvent): Boolean { private fun handleEnterKeyPress(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
if (keyEvent.keyCode == KeyEvent.VK_ESCAPE) {
return true
}
if (keyEvent.keyCode == KeyEvent.VK_ENTER) {
handleEnterKeyPress(ActionEvent(component, ActionEvent.ACTION_PERFORMED, "Enter", keyEvent.`when`, keyEvent.modifiersEx))
return true
}
return false
}
private fun handleEnterKeyPress(e: ActionEvent) {
if (isSearching.compareAndSet(true, false)) { if (isSearching.compareAndSet(true, false)) {
when (val supply = SpeedSearchSupply.getSupply(component)) { when (val supply = SpeedSearchSupply.getSupply(component)) {
is SpeedSearchBase<*> -> supply.hidePopup() is SpeedSearchBase<*> -> supply.hidePopup()
@ -87,7 +99,8 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
} }
} }
else { else {
originalEnterAction?.actionPerformed(e) currentNode = rootNode
originalEnterAction?.perform(actionEvent, keyEvent)
} }
} }
@ -98,4 +111,20 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
final override fun getActionUpdateThread(): ActionUpdateThread { final override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT return ActionUpdateThread.BGT
} }
private sealed interface WrappedAction {
fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent)
class ForActionListener(val component: JComponent, val listener: ActionListener) : WrappedAction {
override fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
listener.actionPerformed(ActionEvent(component, ActionEvent.ACTION_PERFORMED, "Enter", keyEvent.`when`, keyEvent.modifiersEx))
}
}
class ForAnAction(val action: AnAction) : WrappedAction {
override fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
action.actionPerformed(actionEvent)
}
}
}
} }

View File

@ -28,9 +28,21 @@ internal object VimListNavigation {
), ),
KeyStroke.getKeyStroke('G') to IdeaAction("List-selectLastRow"), KeyStroke.getKeyStroke('G') to IdeaAction("List-selectLastRow"),
KeyStroke.getKeyStroke('h') to IdeaAction("List-selectPreviousColumn"), KeyStroke.getKeyStroke('h') to IdeaAction("List-selectPreviousColumn"),
KeyStroke.getKeyStroke('H') to IdeaAction("List-selectPreviousColumnExtendSelection"),
KeyStroke.getKeyStroke('j') to IdeaAction("List-selectNextRow"), KeyStroke.getKeyStroke('j') to IdeaAction("List-selectNextRow"),
KeyStroke.getKeyStroke('J') to IdeaAction("List-selectNextRowExtendSelection"),
KeyStroke.getKeyStroke('k') to IdeaAction("List-selectPreviousRow"), KeyStroke.getKeyStroke('k') to IdeaAction("List-selectPreviousRow"),
KeyStroke.getKeyStroke('K') to IdeaAction("List-selectPreviousRowExtendSelection"),
KeyStroke.getKeyStroke('l') to IdeaAction("List-selectNextColumn"), KeyStroke.getKeyStroke('l') to IdeaAction("List-selectNextColumn"),
KeyStroke.getKeyStroke('L') to IdeaAction("List-selectNextColumnExtendSelection"),
)
)
private val POPUP_LIST_ROOT_NODE = ROOT_NODE + Parent(
mapOf(
KeyStroke.getKeyStroke('o') to IdeaAction("List-selectNextColumn"),
KeyStroke.getKeyStroke('p') to IdeaAction("List-selectPreviousColumn"),
KeyStroke.getKeyStroke('x') to IdeaAction("List-selectPreviousColumn"),
) )
) )
@ -47,7 +59,7 @@ internal object VimListNavigation {
} }
@Suppress("serial") @Suppress("serial")
private class VimPopupListNavigationDispatcher(component: JList<*>, override val popup: WizardPopup) : VimNavigationDispatcher<JList<*>>(component, ROOT_NODE) { private class VimPopupListNavigationDispatcher(component: JList<*>, override val popup: WizardPopup) : VimNavigationDispatcher<JList<*>>(component, POPUP_LIST_ROOT_NODE) {
init { init {
val speedSearch = SpeedSearchSupply.getSupply(component, true) as? SpeedSearch val speedSearch = SpeedSearchSupply.getSupply(component, true) as? SpeedSearch
if (speedSearch != null) { if (speedSearch != null) {

View File

@ -21,9 +21,13 @@ internal object VimTableNavigation {
), ),
KeyStroke.getKeyStroke('G') to IdeaAction("Table-selectLastRow"), KeyStroke.getKeyStroke('G') to IdeaAction("Table-selectLastRow"),
KeyStroke.getKeyStroke('h') to IdeaAction("Table-selectPreviousColumn"), KeyStroke.getKeyStroke('h') to IdeaAction("Table-selectPreviousColumn"),
KeyStroke.getKeyStroke('H') to IdeaAction("Table-selectPreviousColumnExtendSelection"),
KeyStroke.getKeyStroke('j') to IdeaAction("Table-selectNextRow"), KeyStroke.getKeyStroke('j') to IdeaAction("Table-selectNextRow"),
KeyStroke.getKeyStroke('J') to IdeaAction("Table-selectNextRowExtendSelection"),
KeyStroke.getKeyStroke('k') to IdeaAction("Table-selectPreviousRow"), KeyStroke.getKeyStroke('k') to IdeaAction("Table-selectPreviousRow"),
KeyStroke.getKeyStroke('K') to IdeaAction("Table-selectPreviousRowExtendSelection"),
KeyStroke.getKeyStroke('l') to IdeaAction("Table-selectNextColumn"), KeyStroke.getKeyStroke('l') to IdeaAction("Table-selectNextColumn"),
KeyStroke.getKeyStroke('L') to IdeaAction("Table-selectNextColumnExtendSelection"),
) )
) )

View File

@ -20,15 +20,17 @@ internal object VimTreeNavigation {
KeyStroke.getKeyStroke('g') to Parent( KeyStroke.getKeyStroke('g') to Parent(
mapOf( mapOf(
KeyStroke.getKeyStroke('g') to IdeaAction("Tree-selectFirst"), KeyStroke.getKeyStroke('g') to IdeaAction("Tree-selectFirst"),
KeyStroke.getKeyStroke('j') to SelectLastSibling,
KeyStroke.getKeyStroke('k') to SelectFirstSibling,
) )
), ),
KeyStroke.getKeyStroke('G') to IdeaAction("Tree-selectLast"), KeyStroke.getKeyStroke('G') to IdeaAction("Tree-selectLast"),
KeyStroke.getKeyStroke('j') to IdeaAction("Tree-selectNext"), KeyStroke.getKeyStroke('j') to IdeaAction("Tree-selectNext"),
KeyStroke.getKeyStroke('j', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectNextSibling"), KeyStroke.getKeyStroke('j', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectNextSibling"),
KeyStroke.getKeyStroke('J') to SelectLastSibling, KeyStroke.getKeyStroke('J') to IdeaAction("Tree-selectNextExtendSelection"),
KeyStroke.getKeyStroke('k') to IdeaAction("Tree-selectPrevious"), KeyStroke.getKeyStroke('k') to IdeaAction("Tree-selectPrevious"),
KeyStroke.getKeyStroke('k', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectPreviousSibling"), KeyStroke.getKeyStroke('k', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectPreviousSibling"),
KeyStroke.getKeyStroke('K') to SelectFirstSibling, KeyStroke.getKeyStroke('K') to IdeaAction("Tree-selectPreviousExtendSelection"),
KeyStroke.getKeyStroke('o') to ExpandOrCollapseTreeNode, KeyStroke.getKeyStroke('o') to ExpandOrCollapseTreeNode,
KeyStroke.getKeyStroke('O') to IdeaAction("FullyExpandTreeNode"), KeyStroke.getKeyStroke('O') to IdeaAction("FullyExpandTreeNode"),
KeyStroke.getKeyStroke('p') to IdeaAction("Tree-selectParentNoCollapse"), KeyStroke.getKeyStroke('p') to IdeaAction("Tree-selectParentNoCollapse"),