1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-08-13 06:16:58 +02:00

Allow sneak plugin to be registered with the original mappings from the sneak plugin

This commit is contained in:
Alex Plate
2024-02-13 19:20:41 +02:00
parent 42ee78cd3d
commit 12d0d2613f
6 changed files with 78 additions and 11 deletions
src
main
java
com
maddyhome
idea
vim
test
java
org
jetbrains
plugins
ideavim
extension
vim-engine/src/main/kotlin/com/maddyhome/idea/vim

@@ -9,7 +9,6 @@
package com.maddyhome.idea.vim.extension.sneak
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.editor.colors.EditorColors
@@ -19,6 +18,7 @@ import com.intellij.openapi.editor.markup.HighlighterTargetArea
import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.util.Disposer
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.VimProjectService
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor
@@ -30,16 +30,16 @@ import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.extension.ExtensionHandler
import com.maddyhome.idea.vim.extension.VimExtension
import com.maddyhome.idea.vim.extension.VimExtensionFacade
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
import com.maddyhome.idea.vim.extension.VimExtensionHandler
import com.maddyhome.idea.vim.helper.StrictMode
import com.maddyhome.idea.vim.newapi.ij
import java.awt.Font
import java.awt.event.KeyEvent
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import javax.swing.Timer
private const val DEFAULT_HIGHLIGHT_DURATION_SNEAK: Long = 300
private const val DEFAULT_HIGHLIGHT_DURATION_SNEAK = 300
// By [Mikhail Levchenko](https://github.com/Mishkun)
// Original repository with the plugin: https://github.com/Mishkun/ideavim-sneak
@@ -250,11 +250,13 @@ internal class IdeaVimSneakExtension : VimExtension {
}
private fun setClearHighlightRangeTimer(highlighter: RangeHighlighter) {
Executors.newSingleThreadScheduledExecutor().schedule({
ApplicationManager.getApplication().invokeLater {
editor?.markupModel?.removeHighlighter(highlighter) ?: StrictMode.fail("Highlighters without an editor")
val timer = Timer(DEFAULT_HIGHLIGHT_DURATION_SNEAK) {
if (editor?.isDisposed != true) {
editor?.markupModel?.removeHighlighter(highlighter)
}
}, DEFAULT_HIGHLIGHT_DURATION_SNEAK, TimeUnit.MILLISECONDS)
}
timer.isRepeats = false
timer.start()
}
private fun getHighlightTextAttributes() = TextAttributes(
@@ -279,13 +281,41 @@ private fun VimExtension.mapToFunctionAndProvideKeys(keys: String, handler: Exte
handler,
false
)
VimExtensionFacade.putKeyMapping(
VimExtensionFacade.putExtensionHandlerMapping(
MappingMode.NXO,
injector.parser.parseKeys(keys),
injector.parser.parseKeys(commandFromOriginalPlugin(keys)),
owner,
injector.parser.parseKeys(command(keys)),
handler,
false
)
// This is a combination to meet the following requirements:
// - Now we should support mappings from sneak `Sneak_s` and mappings from the previous version of the plugin `(sneak-s)`
// - The shortcut should not be registered if any of these mappings is overridden in .ideavimrc
// - The shortcut should not be registered if some other shortcut for this key exists
val fromKeys = injector.parser.parseKeys(keys)
val filteredModes = MappingMode.NXO.filterNotTo(HashSet()) {
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(command(keys)))
}
val filteredModes2 = MappingMode.NXO.filterNotTo(HashSet()) {
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(commandFromOriginalPlugin(keys)))
}
val filteredFromModes = MappingMode.NXO.filterNotTo(HashSet()) {
injector.keyGroup.hasmapfrom(it, fromKeys)
}
val doubleFiltered = MappingMode.NXO
.filter { it in filteredModes2 && it in filteredModes && it in filteredFromModes }
.toSet()
putKeyMapping(doubleFiltered, fromKeys, owner, injector.parser.parseKeys(command(keys)), true)
putKeyMapping(
doubleFiltered,
fromKeys,
owner,
injector.parser.parseKeys(commandFromOriginalPlugin(keys)),
true
)
}
private fun command(keys: String) = "<Plug>(sneak-$keys)"
private fun commandFromOriginalPlugin(keys: String) = "<Plug>Sneak_$keys"

@@ -8,6 +8,7 @@
package org.jetbrains.plugins.ideavim.extension.sneak
import com.maddyhome.idea.vim.api.keys
import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
@@ -162,4 +163,26 @@ class IdeaVimSneakTest : VimTestCase() {
doTest("sa<ESC>sdw", before, after, Mode.NORMAL())
}
@Test
fun testSneakForwardFromMapping() {
val before = "som${c}e text"
val after = "some te${c}xt"
doTest("fxt", before, after, Mode.NORMAL()) {
// This should be fixed, but now we process `<Plug>` as a single key
typeText(keys(":map f <") + keys("Plug>Sneak_s<CR>"))
}
}
@Test
fun testSneakForwardFromMappingWithOldMappings() {
val before = "som${c}e text"
val after = "some te${c}xt"
doTest("fxt", before, after, Mode.NORMAL()) {
// This should be fixed, but now we process `<Plug>` as a single key
typeText(keys(":map f <") + keys("Plug>(sneak-s)<CR>"))
}
}
}

@@ -62,6 +62,7 @@ public interface VimKeyGroup {
public fun unregisterCommandActions()
public fun resetKeyMappings()
public fun hasmapto(mode: MappingMode, toKeys: List<KeyStroke>): Boolean
public fun hasmapfrom(mode: MappingMode, fromKeys: List<KeyStroke>): Boolean
public val shortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>
public val savedShortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>

@@ -48,6 +48,10 @@ public abstract class VimKeyGroupBase : VimKeyGroup {
return this.getKeyMapping(mode).hasmapto(toKeys)
}
override fun hasmapfrom(mode: MappingMode, fromKeys: List<KeyStroke>): Boolean {
return this.getKeyMapping(mode).hasmapfrom(fromKeys)
}
override fun getKeyMapping(mode: MappingMode): KeyMapping {
return keyMappings.getOrPut(mode) { KeyMapping() }
}

@@ -163,6 +163,11 @@ public class KeyMapping : Iterable<List<KeyStroke?>?>, KeyMappingLayer {
.anyMatch { o: MappingInfo? -> o is ToKeysMappingInfo && o.toKeys == toKeys }
}
public fun hasmapfrom(fromKeys: List<KeyStroke?>): Boolean {
return myKeys.values.stream()
.anyMatch { o: MappingInfo? -> o is ToKeysMappingInfo && o.fromKeys == fromKeys }
}
public fun getMapTo(toKeys: List<KeyStroke?>): List<Pair<List<KeyStroke>, MappingInfo>> {
return myKeys.entries.stream()
.filter { (_, value): Map.Entry<List<KeyStroke>, MappingInfo> -> value is ToKeysMappingInfo && value.toKeys == toKeys }

@@ -106,6 +106,10 @@ public class ToKeysMappingInfo(
}
}
override fun toString(): String {
return "Mapping[$fromKeys -> $toKeys]"
}
public companion object {
private val LOG = vimLogger<ToKeysMappingInfo>()
}