1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-05-10 12:34:06 +02:00

Add missing shortcuts for WORD left/right in Select

This commit is contained in:
Matt Ellis 2025-01-04 23:51:00 +00:00 committed by Alex Pláte
parent 75dadc9610
commit ca4de6f317
5 changed files with 385 additions and 0 deletions
src/test/java/org/jetbrains/plugins/ideavim/action/motion/select/motion
vim-engine/src/main
kotlin/com/maddyhome/idea/vim/action/motion/select/motion
resources/ksp-generated

View File

@ -0,0 +1,161 @@
/*
* 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.motion
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
@Suppress("SpellCheckingInspection")
class SelectMotionBigWordLeftActionTest : VimTestCase() {
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem ${s}${c}Ipsu${se}m
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""",
description = "Vim uses 'selection', with a default value of inclusive." +
"IdeaVim treats Select as exclusive, because it's more intuitive"
)
@Test
fun `test big word left in Select mode`() {
doTest(
listOf("gh", "<C-Left>"),
"""
|Lorem Ips${c}um
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}${c}Ips${se}um
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
)
}
@Test
fun `test big word left in Select mode with exclusive selection`() {
doTest(
listOf("gh", "<C-Left>"),
"""
|Lorem Ips${c}um
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}${c}Ips${se}um
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
) {
enterCommand("set selection=exclusive")
}
}
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem Ipsum
|${s}${c}
|L${se}orem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""",
description = "Vim uses 'selection', with a default value of inclusive." +
"IdeaVim treats Select as exclusive, because it's more intuitive." +
"Also, IdeaVim moves the caret when entering Select, Vim does not"
)
@Test
fun `test motion at start of line`() {
doTest(
// TODO: This should only be one <C-Left> to get the behaviour above
// IdeaVim moves the caret one character right when entering Select mode. So the first <C-Left> moves it to where
// it should be if that was working correctly. The second <C-Left> should select the same range as Vim, except
// IdeaVim is always exclusive, while Vim's range is inclusive
listOf("gh", "<C-Left>", "<C-Left>"),
"""
|Lorem Ipsum
|
|${c}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem Ipsum
|${s}${c}
|${se}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
)
}
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem Ipsum
|${s}${c}
|${se}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""",
description = "IdeaVim moves the caret when entering Select"
)
@Test
fun `test motion at start of line with exclusive selection`() {
doTest(
// TODO: This should only be one <C-Left> to get the behaviour above
// IdeaVim moves the caret one character right when entering Select mode. So the first <C-Left> moves it to where
// it should be if that was working correctly. The second <C-Left> should select the same range as Vim.
listOf("gh", "<C-Left>", "<C-Left>"),
"""
|Lorem Ipsum
|
|${c}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem Ipsum
|${s}${c}
|${se}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
) {
enterCommand("set selection=exclusive")
}
}
}

View File

@ -0,0 +1,142 @@
/*
* 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.motion
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
@Suppress("SpellCheckingInspection")
class SelectMotionBigWordRightActionTest : VimTestCase() {
@VimBehaviorDiffers(originalVimAfter =
"""
|${s}Lorem ${c}I${se}psum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""",
description = "Vim uses 'selection', with a default value of inclusive." +
"IdeaVim treats Select as exclusive, because it's more intuitive"
)
@Test
fun `test big word right in Select mode`() {
doTest(
listOf("gh", "<C-Right>"),
"""
|${c}Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|${s}Lorem ${c}${se}Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
)
}
@Test
fun `test big word right in Select mode with exclusive selection`() {
doTest(
listOf("gh", "<C-Right>"),
"""
|${c}Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|${s}Lorem ${c}${se}Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
) {
enterCommand("set selection=exclusive")
}
}
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem Ipsu${s}m
|${c}
|${se}Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""",
description = "Vim uses 'selection', with a default value of inclusive." +
"IdeaVim treats Select as exclusive, because it's more intuitive"
)
@Test
fun `test motion at end of line`() {
doTest(
listOf("gh", "<C-Right>"),
"""
|Lorem Ipsu${c}m
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem Ipsu${s}m
|${c}${se}
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
)
}
@Test
fun `test motion at end of line with exclusive selection`() {
doTest(
listOf("gh", "<C-Right>"),
"""
|Lorem Ipsu${c}m
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem Ipsu${s}m
|${c}${se}
|Lorem ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.SELECT(SelectionType.CHARACTER_WISE)
) {
enterCommand("set selection=exclusive")
}
}
}

View File

@ -0,0 +1,36 @@
/*
* 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 com.maddyhome.idea.vim.action.motion.select.motion
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.MotionType
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.Motion
import com.maddyhome.idea.vim.handler.MotionActionHandler
@CommandOrMotion(keys = ["<C-Left>"], modes = [Mode.SELECT])
class SelectMotionBigWordLeftAction : MotionActionHandler.ForEachCaret() {
override fun getOffset(
editor: VimEditor,
caret: ImmutableVimCaret,
context: ExecutionContext,
argument: Argument?,
operatorArguments: OperatorArguments,
): Motion {
return injector.motion.findOffsetOfNextWord(editor, caret.offset, -operatorArguments.count1, bigWord = true)
}
override val motionType: MotionType = MotionType.EXCLUSIVE
}

View File

@ -0,0 +1,36 @@
/*
* 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 com.maddyhome.idea.vim.action.motion.select.motion
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.MotionType
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.Motion
import com.maddyhome.idea.vim.handler.MotionActionHandler
@CommandOrMotion(keys = ["<C-Right>"], modes = [Mode.SELECT])
class SelectMotionBigWordRightAction : MotionActionHandler.ForEachCaret() {
override fun getOffset(
editor: VimEditor,
caret: ImmutableVimCaret,
context: ExecutionContext,
argument: Argument?,
operatorArguments: OperatorArguments,
): Motion {
return injector.motion.findOffsetOfNextWord(editor, caret.offset, operatorArguments.count1, bigWord = true)
}
override val motionType: MotionType = MotionType.EXCLUSIVE
}

View File

@ -309,6 +309,11 @@
"class": "com.maddyhome.idea.vim.action.ex.MoveToPreviousWordAction",
"modes": "C"
},
{
"keys": "<C-Left>",
"class": "com.maddyhome.idea.vim.action.motion.select.motion.SelectMotionBigWordLeftAction",
"modes": "S"
},
{
"keys": "<C-Left>",
"class": "com.maddyhome.idea.vim.action.motion.text.MotionBigWordLeftAction",
@ -429,6 +434,11 @@
"class": "com.maddyhome.idea.vim.action.ex.MoveToNextWordAction",
"modes": "C"
},
{
"keys": "<C-Right>",
"class": "com.maddyhome.idea.vim.action.motion.select.motion.SelectMotionBigWordRightAction",
"modes": "S"
},
{
"keys": "<C-Right>",
"class": "com.maddyhome.idea.vim.action.motion.text.MotionBigWordRightAction",