mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-05-29 01:34:10 +02:00
Fix Del and BS not working in Select mode
Fixes VIM-3618
This commit is contained in:
parent
f30e376e11
commit
1d5fc01d65
src
main/java/com/maddyhome/idea/vim/group
test/java/org/jetbrains/plugins/ideavim/action/motion/select
vim-engine/src/main
kotlin/com/maddyhome/idea/vim/action/motion/select
resources/ksp-generated
@ -314,7 +314,7 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
if (c instanceof JComponent) {
|
if (c instanceof JComponent) {
|
||||||
final List<AnAction> actions = ActionUtil.getActions((JComponent)c);
|
final List<AnAction> actions = ActionUtil.getActions((JComponent)c);
|
||||||
for (AnAction action : actions) {
|
for (AnAction action : actions) {
|
||||||
if (action instanceof VimShortcutKeyAction) {
|
if (action instanceof VimShortcutKeyAction || action == VimShortcutKeyAction.getInstance()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final Shortcut[] shortcuts = action.getShortcutSet().getShortcuts();
|
final Shortcut[] shortcuts = action.getShortcutSet().getShortcuts();
|
||||||
@ -334,7 +334,11 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||||
for (String id : keymap.getActionIds(keyStroke)) {
|
for (String id : keymap.getActionIds(keyStroke)) {
|
||||||
final AnAction action = ActionManager.getInstance().getAction(id);
|
final AnAction action = ActionManager.getInstance().getAction(id);
|
||||||
if (action != null) {
|
|
||||||
|
// EmptyAction is used to reserve a shortcut, but can't be executed. Code can ask for an action by ID and
|
||||||
|
// use its shortcut(s) to dynamically register a new action on a component in the UI hierarchy. It's not
|
||||||
|
// useful for our needs here - we'll pick up the real action when we get local actions.
|
||||||
|
if (action != null && !(action instanceof EmptyAction)) {
|
||||||
results.add(action);
|
results.add(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2025 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.plugins.ideavim.action.motion.select
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class SelectDeleteActionTest : VimTestCase() {
|
||||||
|
@Test
|
||||||
|
fun `test Delete removes text and returns to Normal mode`() {
|
||||||
|
doTest(
|
||||||
|
listOf("ve", "<C-G>", "<Del>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.NORMAL()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test Delete removes text and returns to Insert mode when invoked from Insert Select`() {
|
||||||
|
doTest(
|
||||||
|
listOf("i", "<S-Right>".repeat(5), "<Del>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.INSERT
|
||||||
|
) {
|
||||||
|
enterCommand("set selectmode=key keymodel=startsel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test Delete removes text and returns to Replace mode when invoked from Select with pending Replace mode`() {
|
||||||
|
doTest(
|
||||||
|
listOf("R", "<S-Right>".repeat(5), "<Del>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.REPLACE
|
||||||
|
) {
|
||||||
|
enterCommand("set selectmode=key keymodel=startsel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test Backspace deletes text and returns to Normal mode`() {
|
||||||
|
doTest(
|
||||||
|
listOf("ve", "<C-G>", "<Del>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.NORMAL()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test Backspace removes text and returns to Insert mode when invoked from Insert Select`() {
|
||||||
|
doTest(
|
||||||
|
listOf("i", "<S-Right>".repeat(5), "<BS>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.INSERT
|
||||||
|
) {
|
||||||
|
enterCommand("set selectmode=key keymodel=startsel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test Backspace removes text and returns to Replace mode when invoked from Select with pending Replace mode`() {
|
||||||
|
doTest(
|
||||||
|
listOf("R", "<S-Right>".repeat(5), "<BS>"),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I ${c}found it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
"""
|
||||||
|
|Lorem Ipsum
|
||||||
|
|
|
||||||
|
|I $c it in a legendary land
|
||||||
|
|consectetur adipiscing elit
|
||||||
|
|Sed in orci mauris.
|
||||||
|
|Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimMargin(),
|
||||||
|
Mode.REPLACE
|
||||||
|
) {
|
||||||
|
enterCommand("set selectmode=key keymodel=startsel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,30 +19,45 @@ import com.maddyhome.idea.vim.handler.VimActionHandler
|
|||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
/**
|
@CommandOrMotion(keys = ["<DEL>"], modes = [Mode.SELECT])
|
||||||
* @author Alex Plate
|
class SelectDeleteAction : SelectDeleteBackspaceActionBase() {
|
||||||
*/
|
override val keyStroke: KeyStroke
|
||||||
|
get() = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)
|
||||||
|
}
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["<BS>", "<DEL>"], modes = [Mode.SELECT])
|
@CommandOrMotion(keys = ["<BS>"], modes = [Mode.SELECT])
|
||||||
class SelectDeleteAction : VimActionHandler.SingleExecution() {
|
class SelectBackspaceAction : SelectDeleteBackspaceActionBase() {
|
||||||
|
override val keyStroke: KeyStroke
|
||||||
|
get() = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SelectDeleteBackspaceActionBase : VimActionHandler.SingleExecution() {
|
||||||
override val type: Command.Type = Command.Type.INSERT
|
override val type: Command.Type = Command.Type.INSERT
|
||||||
|
|
||||||
|
abstract val keyStroke: KeyStroke
|
||||||
|
|
||||||
override fun execute(
|
override fun execute(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
operatorArguments: OperatorArguments,
|
operatorArguments: OperatorArguments,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0)
|
// TODO: It would be nice to know _why_ we use native actions for Delete/Backspace
|
||||||
val actions = injector.keyGroup.getActions(editor, enterKeyStroke)
|
// If there's some kind of additional native editor action bound to Delete or Backspace (e.g. cancelling something,
|
||||||
|
// etc.) then we should of course invoke it, like we do with Escape or Enter. But if we do, we should reconsider
|
||||||
|
// unconditionally exiting Select mode. If the additional native editor action doesn't delete the text, then we're
|
||||||
|
// exiting Select mode incorrectly. If there isn't an additional native editor action, then would it just be simpler
|
||||||
|
// to delete the selected text using editor APIs?
|
||||||
|
val actions = injector.keyGroup.getActions(editor, keyStroke)
|
||||||
for (action in actions) {
|
for (action in actions) {
|
||||||
if (injector.actionExecutor.executeAction(editor, action, context)) {
|
if (injector.actionExecutor.executeAction(editor, action, context)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that Vim returns to the pending mode. I.e., when starting Select from Normal/Visual, it will return to
|
||||||
|
// Normal. When returning from Insert or Replace pending Select (via shifted keys), it will return to Insert/Replace
|
||||||
editor.exitSelectModeNative(true)
|
editor.exitSelectModeNative(true)
|
||||||
injector.changeGroup.insertBeforeCursor(editor, context)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keys": "<BS>",
|
"keys": "<BS>",
|
||||||
"class": "com.maddyhome.idea.vim.action.motion.select.SelectDeleteAction",
|
"class": "com.maddyhome.idea.vim.action.motion.select.SelectBackspaceAction",
|
||||||
"modes": "S"
|
"modes": "S"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user