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

Select preceding whitespace if no following (vaw)

Outer word/WORD text objects should select following whitespace, unless there isn't any, and then it should select preceding whitespace.
This commit is contained in:
Matt Ellis 2025-01-06 00:32:08 +00:00 committed by Alex Pláte
parent 76f7d81129
commit 4240c429ba
4 changed files with 72 additions and 104 deletions
src/test/java/org/jetbrains/plugins/ideavim/action
vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api

View File

@ -470,11 +470,13 @@ $c tw${c}o
@Test
fun testMotionOuterBigWordAction() {
// Careful with the trailing whitespace. If there isn't any, `vaW` will select leading whitespace and the carets
// will merge
typeTextInFile(
injector.parser.parseKeys("v" + "aW"),
" a${c}bcd${c}e.abcde.a${c}bcde a${c}bcde.abcde\n",
" a${c}bcd${c}e.abcde.a${c}bcde a${c}bcde.abcde \n",
)
assertState(" <selection>abcde.abcde.abcde </selection><selection>abcde.abcde</selection>\n")
assertState(" <selection>abcde.abcde.abcde </selection><selection>abcde.abcde</selection> \n")
}
@Test
@ -1069,11 +1071,13 @@ $c tw${c}o
@Test
fun testMergingSelections() {
// Careful of the trailing whitespace. Without it, `vaW` will select leading whitespace, and the carets will merge
// too soon. With it, the entire line is selected, but with two carets and the `l` and `h` merge into a single one
typeTextInFile(
injector.parser.parseKeys("v" + "aW" + "l" + "h"),
"a${c}bcde.abcde.abcde ab${c}cde.abcde\n",
"a${c}bcde.abcde.abcde ab${c}cde.abcde \n",
)
assertState("<selection>abcde.abcde.abcde abcde.abcde</selection>\n")
assertState("<selection>abcde.abcde.abcde abcde.abcde</selection> \n")
}
@Test

View File

@ -229,7 +229,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing ${s}elit
|consectetur adipiscing${s} elit
|Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
@ -237,17 +237,6 @@ class MotionOuterBigWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing${s} elit
| Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands over whitespace following new line`() {
doTest(
@ -264,7 +253,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing ${s}elit
|consectetur adipiscing${s} elit
| Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
@ -272,17 +261,6 @@ class MotionOuterBigWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem${s} Ipsum
|
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands to empty line`() {
doTest(
@ -296,7 +274,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
@ -334,7 +312,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|
|
@ -347,16 +325,6 @@ class MotionOuterBigWordActionTest : VimTestCase() {
)
}
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem${s} Ipsum
|........
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands to cover whitespace on following blank line`() {
doTest(
@ -370,7 +338,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin().dotToSpace(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|........
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
@ -409,7 +377,7 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin().dotToSpace(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|........
|
@ -462,13 +430,6 @@ class MotionOuterBigWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing${s} eli${c}t${se}
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test select outer WORD at end of line selects preceding whitespace`() {
doTest(
@ -478,13 +439,34 @@ class MotionOuterBigWordActionTest : VimTestCase() {
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing ${s}eli${c}t${se}
|Lorem ipsum dolor sit amet, consectetur adipiscing${s} eli${c}t${se}
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.VISUAL(SelectionType.CHARACTER_WISE),
)
}
@Test
fun `test select outer WORD at end of file selects preceding whitespace`() {
doTest(
"vaW",
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit
|Sed in orci mauris. Cras id tellus in ex imperdiet eg${c}estas
""".trimMargin(),
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit
|Sed in orci mauris. Cras id tellus in ex imperdiet${s} egesta${c}s${se}
""".trimMargin(),
Mode.VISUAL(SelectionType.CHARACTER_WISE),
)
}
@Test
fun `test select outer WORD on only word on line does not select leading whitespace`() {
doTest("vaW", " Lor${c}em", " ${s}Lore${c}m${se}", Mode.VISUAL(SelectionType.CHARACTER_WISE))
}
@Test
fun `test select outer WORD with existing left-to-right selection selects rest of word and following whitespace`() {
doTest(

View File

@ -12,7 +12,6 @@ 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.Disabled
import org.junit.jupiter.api.Test
@Suppress("SpellCheckingInspection", "RemoveCurlyBracesFromTemplate")
@ -228,7 +227,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing ${s}elit
|consectetur adipiscing${s} elit
|Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
@ -236,17 +235,6 @@ class MotionOuterWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing${s} elit
| Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands over whitespace following new line`() {
doTest(
@ -263,7 +251,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Lorem Ipsum
|
|Lorem ipsum dolor sit amet,
|consectetur adipiscing ${s}elit
|consectetur adipiscing${s} elit
| Se${c}d${se} in orci mauris.
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
@ -271,17 +259,6 @@ class MotionOuterWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem${s} Ipsum
|
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands to empty line`() {
doTest(
@ -295,7 +272,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
@ -333,7 +310,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|
|
@ -346,16 +323,6 @@ class MotionOuterWordActionTest : VimTestCase() {
)
}
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem${s} Ipsum
|........
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
|Sed in orci mauris.
|Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test repeated text object expands to cover whitespace on following blank line`() {
doTest(
@ -369,7 +336,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin().dotToSpace(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|........
|Lore${c}m${se} ipsum dolor sit amet,
|consectetur adipiscing elit
@ -408,7 +375,7 @@ class MotionOuterWordActionTest : VimTestCase() {
|Cras id tellus in ex imperdiet egestas.
""".trimMargin().dotToSpace(),
"""
|Lorem ${s}Ipsum
|Lorem${s} Ipsum
|
|........
|
@ -470,13 +437,6 @@ class MotionOuterWordActionTest : VimTestCase() {
)
}
// TODO: Fix this bug
@VimBehaviorDiffers(originalVimAfter =
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing${s} eli${c}t${se}
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
"""
)
@Test
fun `test select outer word at end of line selects preceding whitespace`() {
doTest(
@ -486,13 +446,34 @@ class MotionOuterWordActionTest : VimTestCase() {
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing ${s}eli${c}t${se}
|Lorem ipsum dolor sit amet, consectetur adipiscing${s} eli${c}t${se}
|Sed in orci mauris. Cras id tellus in ex imperdiet egestas.
""".trimMargin(),
Mode.VISUAL(SelectionType.CHARACTER_WISE),
)
}
@Test
fun `test select outer word at end of file selects preceding whitespace`() {
doTest(
"vaw",
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit
|Sed in orci mauris. Cras id tellus in ex imperdiet eg${c}estas
""".trimMargin(),
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit
|Sed in orci mauris. Cras id tellus in ex imperdiet${s} egesta${c}s${se}
""".trimMargin(),
Mode.VISUAL(SelectionType.CHARACTER_WISE),
)
}
@Test
fun `test select outer word on only word on line does not select leading whitespace`() {
doTest("vaw", " Lor${c}em", " ${s}Lore${c}m${se}", Mode.VISUAL(SelectionType.CHARACTER_WISE))
}
@Test
fun `test select outer word with existing left-to-right selection selects rest of word and following whitespace`() {
doTest(
@ -579,7 +560,6 @@ class MotionOuterWordActionTest : VimTestCase() {
)
}
@Disabled("Implementation bug")
@Test
fun `test select multiple outer words with no following whitespace selects preceding whitespace 2`() {
// Implementation bug: caret placed anywhere other than last character would not select preceding whitespace

View File

@ -1440,15 +1440,17 @@ abstract class VimSearchHelperBase : VimSearchHelper {
var goBack = (startSpace && !hasSelection) || (!startSpace && hasSelection && !onWordStart)
if (dir == 1 && isOuter) {
var firstEnd = end
if (count > 1) {
firstEnd = findNextWordEnd(editor, pos, 1, isBig, false)
}
if (firstEnd < max - 1) {
if (charType(editor, chars[firstEnd + 1], false) !== CharacterHelper.CharacterType.WHITESPACE) {
// If there's no whitespace after the end of the word/WORD to select, go back for the leading whitespace
// This behaviour isn't strictly documented, but you can see it mentioned in `:help v_a'`
if (end < max - 1) {
val c = chars[end + 1]
if (charType(editor, c, false) !== CharacterHelper.CharacterType.WHITESPACE || c == '\n') {
goBack = true
}
}
else {
goBack = true
}
}
if (dir == -1 && isOuter && startSpace) {
if (pos > 0) {