diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerBigWordActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerBigWordActionTest.kt index a3a0b5c8e..26aeac448 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerBigWordActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerBigWordActionTest.kt @@ -9,10 +9,630 @@ package org.jetbrains.plugins.ideavim.action.motion.`object` 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("RemoveCurlyBracesFromTemplate", "SpellCheckingInspection") class MotionInnerBigWordActionTest : VimTestCase() { + @Test + fun `test select WORD from beginning of word`() { + doTest( + "viW", + "${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD from middle of word`() { + doTest( + "viW", + "Lo${c}rem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD from end of word`() { + doTest( + "viW", + "Lore${c}m ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD from inside whitespace selects whitespace`() { + doTest( + "viW", + "Lorem ${c} ...ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ${c} ${se}...ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD from whitespace at start of line`() { + doTest( + "viW", + " ${c} ...Lorem ipsum", + "${s} ${c} ${se}...Lorem ipsum", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD from whitespace at end of line`() { + doTest( + "viW", + "Lorem ipsum... ${c} ", + "Lorem ipsum...${s} ${c} ${se}", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD ignores punctuation`() { + doTest( + "viW", + "Lorem ipsum dolor sit a${c}met,consectetur adipiscing elit", + "Lorem ipsum dolor sit ${s}amet,consectetu${c}r${se} adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD with existing left-to-right selection selects rest of word`() { + doTest( + listOf("v", "l", "iW"), + "Lorem ipsum dolor sit amet, con${c}sectetur adipiscing elit", + "Lorem ipsum dolor sit amet, con${s}sectetu${c}r${se} adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD with existing left-to-right selection in whitespace selects rest of whitespace`() { + doTest( + listOf("v", "l", "iW"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem ${s} ${c} ${se}ipsum dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = "Lorem ipsum dolor sit amet, ${s}${c}consectet${se}ur adipiscing elit") + @Test + fun `test select WORD with existing right-to-left selection selects start of word`() { + doTest( + listOf("v", "h", "iW"), + "Lorem ipsum dolor sit amet, consecte${c}tur adipiscing elit", + "Lorem ipsum dolor sit amet,${s}${c} consectet${se}ur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select WORD with existing right-to-left selection in whitespace selects rest of whitespace`() { + doTest( + listOf("v", "h", "iW"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem${s}${c} ${se} ipsum dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers( + originalVimAfter = "${s}Lorem${c}${se} ipsum dolor sit amet, consectetur adipiscing elit", + description = "Text objects are implicitly inclusive, because they set the selection." + + "Vim modifies the caret offset of inclusive motions when in exclusive selection mode. " + + "Fix this when IdeaVim also handles inclusive motions in exclusive selection mode." + ) + @Test + fun `test select WORD with exclusive selection`() { + doTest( + "viW", + "Lo${c}rem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}${se}m ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) { + enterCommand("set selection=exclusive") + } + } + + @Test + fun `test repeated text object expands selection to following whitespace`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur${c} ${se}adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to WORD following whitespace`() { + doTest( + listOf("viW", "iW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscin${c}g${se} elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count expands selection`() { + doTest( + "v3iW", + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscin${c}g${se} elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object does not expand selection from single character selection`() { + // Surprisingly, this is correct Vim behaviour! It does not expand selection from a single character selection + doTest( + listOf("viW", "iW"), + """ + |Lorem Ipsum + | + |Lore ${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lore ${s}${c}m${se} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object does not expand selection from current single whitespace`() { + // Surprisingly, this is correct Vim behaviour! It does not expand selection from a single whitespace selection + doTest( + listOf("viW", "iW"), + """ + |Lorem Ipsum + | + |Lorem${c} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem${s}${c} ${se}ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count will expand selection from current single whitespace`() { + // `viwiw` on a single character doesn't expand selection, but `v2iw` does. Go figure + doTest( + listOf("v3iW"), + """ + |Lorem Ipsum + | + |Lore ${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lore ${s}m ipsu${c}m${se} dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to end of line`() { + doTest( + listOf("v2iW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adi${c}piscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing eli${c}t${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing elit.......${c}.${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Caret placement is incorrect, but the selection is correct - it should not select the final newline char" + ) + @Test + fun `test repeated text object expands selection to whitespace at end of line`() { + doTest( + listOf("v3iW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adi${c}piscing elit........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing elit........${c}${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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. + """, + description = "IdeaVim expands to include newline character" + ) + @Test + fun `test repeated text object expands across new line`() { + doTest( + listOf("viW", "iW", "iW"), // TODO: This should be just listOf("viW", "iW") + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing e${c}lit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands to whitespace following new line`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing e${c}lit + | Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing ${s}elit + | ${c} ${se}Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c}L${se}orem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Vim's behaviour is weird. Makes no sense that it selects the first character of the word. " + + "Possibly a bug in Vim: https://github.com/vim/vim/issues/16514 " + + "Unclear what the correct behaviour should be", + shouldBeFixed = false + ) + @Test + fun `test repeated text object expands to empty line`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ip${c}sum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ${s}Ipsum + |${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c} + |${se}Lorem ipsum dolor sit amet, + """, + description = "Off by one because IdeaVim does not allow selecting a newline char" + ) + @Test + fun `test repeated text object expands to multiple empty lines`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ip${c}sum + | + | + |Lorem ipsum dolor sit amet, + """.trimMargin(), + """ + |Lorem ${s}Ipsum + | + |${c}${se} + |Lorem ipsum dolor sit amet, + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + |.......${c}.${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Caret placement is incorrect, but selection is correct. It should not select trailing new line char" + ) + @Test + fun `test repeated text object expands to whitespace on following blank line`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ip${c}sum + |........ + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem ${s}Ipsum + |........${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c}.${se}....... + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Vim's behaviour is weird. Makes no sense that it selects the first character of the word. " + + "Possibly a bug in Vim: https://github.com/vim/vim/issues/16514 " + + "Unclear what the correct behaviour should be", + shouldBeFixed = false + ) + @Test + fun `test repeated text object expands to whitespace on following blank lines`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ip${c}sum + | + |........ + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem ${s}Ipsum + | + |........ + |${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands to include whitespace after non-word character`() { + doTest( + listOf("viW", "iW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit ${s}amet,${c} ${se}consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple WORDs selects includes whitespace between words in count`() { + doTest( + "v2iW", + "...Lo${c}rem... ipsum dolor sit amet, consectetur adipiscing elit", + "${s}...Lorem...${c} ${se}ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple WORDs selects includes whitespace between words in count 2`() { + doTest( + "v3iW", + "...L${c}orem... ipsum... dolor sit amet, consectetur adipiscing elit", + "${s}...Lorem... ipsum..${c}.${se} dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple WORDs starting in whitespace`() { + doTest( + "v3iW", + "Lorem ${c} ...ipsum... dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ...ipsum...${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Sed${c} ${se}in orci mauris. Cras id tellus in ex imperdiet egestas. + """, + description = "Unclear why this fails. IdeaVim seems to treat the new line char as a word" + ) + @Test + fun `test select multiple words wraps to next line`() { + doTest( + "v3iw", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Se${c}d${se} in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + @Test fun `test at last dot`() { doTest( diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerWordActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerWordActionTest.kt index e4f4ad3c2..6c81a3582 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerWordActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionInnerWordActionTest.kt @@ -10,10 +10,649 @@ package org.jetbrains.plugins.ideavim.action.motion.`object` 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", "RemoveCurlyBracesFromTemplate") class MotionInnerWordActionTest : VimTestCase() { + @Test + fun `test select word from beginning of word`() { + doTest( + "viw", + "${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word from middle of word`() { + doTest( + "viw", + "Lo${c}rem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word from end of word`() { + doTest( + "viw", + "Lore${c}m ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}m${se} ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word from inside whitespace selects whitespace`() { + doTest( + "viw", + "Lorem ${c} ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ${c} ${se}ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word from whitespace at start of line`() { + doTest( + "viw", + " ${c} Lorem ipsum", + "${s} ${c} ${se}Lorem ipsum", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word from whitespace at end of line`() { + doTest( + "viw", + "Lorem ipsum ${c} ", + "Lorem ipsum${s} ${c} ${se}", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word selects up to punctuation`() { + doTest( + "viw", + "Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit", + "Lorem ipsum dolor sit ${s}ame${c}t${se}, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word with existing left-to-right selection selects rest of word`() { + doTest( + listOf("v", "l", "iw"), + "Lorem ipsum dolor sit amet, con${c}sectetur adipiscing elit", + "Lorem ipsum dolor sit amet, con${s}sectetu${c}r${se} adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word with existing left-to-right selection in whitespace selects rest of whitespace`() { + doTest( + listOf("v", "l", "iw"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem ${s} ${c} ${se}ipsum dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = "Lorem ipsum dolor sit amet, ${s}${c}consectet${se}ur adipiscing elit") + @Test + fun `test select word with existing right-to-left selection selects start of word`() { + doTest( + listOf("v", "h", "iw"), + "Lorem ipsum dolor sit amet, consecte${c}tur adipiscing elit", + "Lorem ipsum dolor sit amet,${s}${c} consectet${se}ur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select word with existing right-to-left selection in whitespace selects rest of whitespace`() { + doTest( + listOf("v", "h", "iw"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem${s}${c} ${se} ipsum dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers( + originalVimAfter = "${s}Lorem${c}${se} ipsum dolor sit amet, consectetur adipiscing elit", + description = "Text objects are implicitly inclusive, because they set the selection." + + "Vim modifies the caret offset of inclusive motions when in exclusive selection mode. " + + "Fix this when IdeaVim also handles inclusive motions in exclusive selection mode." + ) + @Test + fun `test select word with exclusive selection`() { + doTest( + "viw", + "Lo${c}rem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lore${c}${se}m ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) { + enterCommand("set selection=exclusive") + } + } + + @Test + fun `test repeated text object expands selection to following whitespace`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur${c} ${se}adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to word following whitespace`() { + doTest( + listOf("viw", "iw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscin${c}g${se} elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count expands selection`() { + doTest( + "v3iw", + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscin${c}g${se} elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object does not expand selection from single character selection`() { + // Surprisingly, this is correct Vim behaviour! It does not expand selection from a single character selection + doTest( + listOf("viw", "iw"), + """ + |Lorem Ipsum + | + |Lore ${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lore ${s}${c}m${se} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object does not expand selection from current single whitespace`() { + // Surprisingly, this is correct Vim behaviour! It does not expand selection from a single whitespace selection + doTest( + listOf("viw", "iw"), + """ + |Lorem Ipsum + | + |Lorem${c} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem${s}${c} ${se}ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count will expand selection from current single whitespace`() { + // `viwiw` on a single character doesn't expand selection, but `v2iw` does. Go figure + doTest( + listOf("v3iw"), + """ + |Lorem Ipsum + | + |Lore ${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lore ${s}m ipsu${c}m${se} dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to end of line`() { + doTest( + listOf("v2iw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adi${c}piscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing eli${c}t${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing elit.......${c}.${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Caret placement is incorrect, but the selection is correct - it should not select the final newline char" + ) + @Test + fun `test repeated text object expands selection to whitespace at end of line`() { + doTest( + listOf("v3iw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adi${c}piscing elit........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur ${s}adipiscing elit........${c}${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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. + """, + description = "IdeaVim expands to include newline character" + ) + @Test + fun `test repeated text object expands across new line`() { + doTest( + listOf("viw", "iw", "iw"), // TODO: This should be just listOf("viw", "iw") + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing e${c}lit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands to whitespace following new line`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing e${c}lit + | Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing ${s}elit + | ${c} ${se}Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c}L${se}orem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Vim's behaviour is weird. Makes no sense that it selects the first character of the word. " + + "Possibly a bug in Vim: https://github.com/vim/vim/issues/16514 " + + "Unclear what the correct behaviour should be", + shouldBeFixed = false + ) + @Test + fun `test repeated text object expands to empty line`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ip${c}sum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ${s}Ipsum + |${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c} + |${se}Lorem ipsum dolor sit amet, + """, + description = "Off by one because IdeaVim does not allow selecting a newline char" + ) + @Test + fun `test repeated text object expands to multiple empty lines`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ip${c}sum + | + | + |Lorem ipsum dolor sit amet, + """.trimMargin(), + """ + |Lorem ${s}Ipsum + | + |${c}${se} + |Lorem ipsum dolor sit amet, + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + |.......${c}.${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Caret placement is incorrect, but selection is correct. It should not select trailing new line char" + ) + @Test + fun `test repeated text object expands to whitespace on following blank line`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ip${c}sum + |........ + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem ${s}Ipsum + |........${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ${s}Ipsum + | + |${c}.${se}....... + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """, + description = "Vim's behaviour is weird. Makes no sense that it selects the first character of the word. " + + "Possibly a bug in Vim: https://github.com/vim/vim/issues/16514 " + + "Unclear what the correct behaviour should be", + shouldBeFixed = false + ) + @Test + fun `test repeated text object expands to whitespace on following blank lines`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ip${c}sum + | + |........ + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem ${s}Ipsum + | + |........ + |${c}${se} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands to include non-word character`() { + doTest( + listOf("viw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit ${s}amet${c},${se} consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands to include whitespace after non-word character`() { + doTest( + listOf("viw", "iw", "iw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit ${s}amet,${c} ${se}consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple words selects includes whitespace between words in count`() { + doTest( + "v2iw", + "${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lorem${c} ${se}ipsum dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple words selects includes whitespace between words in count 2`() { + doTest( + "v3iw", + "${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit", + "${s}Lorem ipsu${c}m${se} dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple words starting in whitespace`() { + doTest( + "v3iw", + "Lorem ${c} ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Sed${c} ${se}in orci mauris. Cras id tellus in ex imperdiet egestas. + """, + description = "Unclear why this fails. IdeaVim seems to treat the new line char as a word" + ) + @Test + fun `test select multiple words wraps to next line`() { + doTest( + "v3iw", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Se${c}d${se} in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + @Test fun `test empty text`() { doTest( diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterBigWordActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterBigWordActionTest.kt index 03efd8ba1..4a347abaf 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterBigWordActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterBigWordActionTest.kt @@ -12,10 +12,575 @@ import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.SelectionType import org.jetbrains.plugins.ideavim.SkipNeovimReason import org.jetbrains.plugins.ideavim.TestWithoutNeovim +import org.jetbrains.plugins.ideavim.VimBehaviorDiffers import org.jetbrains.plugins.ideavim.VimTestCase import org.junit.jupiter.api.Test +@Suppress("RemoveCurlyBracesFromTemplate", "SpellCheckingInspection") class MotionOuterBigWordActionTest : VimTestCase() { + @Test + fun `test select outer WORD selects word and following whitespace`() { + doTest( + "vaW", + "Lorem ip${c}sum dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD from beginning of word`() { + doTest( + "vaW", + "Lorem ${c}ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD from end of word`() { + doTest( + "vaW", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD from inside whitespace selects word and not following whitespace`() { + doTest( + "vaW", + "Lorem ${c} ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsu${c}m${se} dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers( + originalVimAfter = "Lorem ${s}ipsum ${c}${se}dolor sit amet, consectetur adipiscing elit", + description = "Text objects are implicitly inclusive. Vim adjusts the caret location for inclusive motions" + ) + @Test + fun `test select outer WORD with exclusive selection`() { + doTest( + "vaW", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to whitespace after next WORD`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing${c} ${se}elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object starting from whitespace expands selection`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ipsum + | + |Lorem${c} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem${s} ipsum dolo${c}r${se} sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count expands selection`() { + doTest( + "v2aW", + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing${c} ${se}elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to end of line`() { + doTest( + listOf("v2aW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing eli${c}t${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing elit.......${c}.${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """ + ) + @Test + fun `test repeated text object expands selection to whitespace at end of line`() { + doTest( + listOf("v2aW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing eli${c}t${se}........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing${s} elit + |Sed${c} ${se}in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """ + ) + @Test + fun `test repeated text object expands across new line`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing el${c}it + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + listOf("vaW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing el${c}it + | Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + listOf("vaW", "aW"), + """ + |Lorem Ip${c}sum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem${s} Ipsum + | + |${c}${se} + | + |Lorem 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 multiple empty lines`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ip${c}sum + | + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @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( + listOf("vaW", "aW"), + """ + |Lorem Ip${c}sum + |........ + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |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. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem${s} Ipsum + | + |........ + |${c} + |${se}Lorem 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 lines`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ip${c}sum + | + |........ + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |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. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands over non-word character`() { + doTest( + listOf("vaW", "aW"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit ${s}amet, consectetur${c} ${se}adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD selects following whitespace up to punctuation`() { + doTest( + "vaW", + "Lorem ipsu${c}m ...dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum ${c} ${se}...dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD with following non-word characters selects following WORD characters`() { + doTest( + "vaW", + "Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit", + "Lorem ipsum dolor sit ${s}amet,${c} ${se}consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + "vaW", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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 with existing left-to-right selection selects rest of word and following whitespace`() { + doTest( + listOf("v", "l", "aW"), + "Lo${c}rem ipsum", + "Lo${s}rem ${c} ${se}ipsum", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD with existing left-to-right selection in whitespace selects rest of whitespace and following word`() { + doTest( + listOf("v", "l", "aW"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem ${s} ipsu${c}m${se} dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD with existing right-to-left selection selects rest of word and preceding whitespace`() { + doTest( + listOf("v", "h", "aW"), + "Lorem ip${c}sum dolor sit amet", + "Lorem${s}${c} ips${se}um dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer WORD with existing right-to-left selection in whitespace selects rest of whitespace and preceding word`() { + doTest( + listOf("v", "h", "aW"), + "Lorem ipsum ${c} dolor sit amet", + "Lorem ${s}${c}ipsum ${se} dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer WORDs selects following whitespace`() { + doTest( + "v2aW", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum dolor${c} ${se}sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer WORDs with non-word characters`() { + doTest( + "v2aW", + "Lorem ipsu${c}m -- dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum --${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer WORDs with non-word characters 2`() { + doTest( + "v2aW", + "Lorem ipsu${c}m --dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum --dolor${c} ${se}sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer words starting in whitespace`() { + doTest( + "v3aW", + "Lorem ${c} ipsum --dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsum --dolor si${c}t${se} amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer WORDs crosses end of line`() { + doTest( + "v2aW", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Sed${c} ${se}in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + @TestWithoutNeovim(SkipNeovimReason.UNCLEAR, description = "Wrong caret position, but in real neovim works fine") @Test fun `test on last dot`() { diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterWordActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterWordActionTest.kt new file mode 100644 index 000000000..fe2d51014 --- /dev/null +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/object/MotionOuterWordActionTest.kt @@ -0,0 +1,609 @@ +/* + * 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.`object` + +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") +class MotionOuterWordActionTest : VimTestCase() { + @Test + fun `test select outer word selects word and following whitespace`() { + doTest( + "vaw", + "Lorem ip${c}sum dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word from beginning of word`() { + doTest( + "vaw", + "Lorem ${c}ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word from end of word`() { + doTest( + "vaw", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word from inside whitespace selects word and not following whitespace`() { + doTest( + "vaw", + "Lorem ${c} ipsum dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsu${c}m${se} dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers( + originalVimAfter = "Lorem ${s}ipsum ${c}${se}dolor sit amet, consectetur adipiscing elit", + description = "Text objects are implicitly inclusive. Vim adjusts the caret location for inclusive motions" + ) + @Test + fun `test select outer word with exclusive selection`() { + doTest( + "vaw", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to whitespace after next word`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing${c} ${se}elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object starting from whitespace expands selection`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ipsum + | + |Lorem${c} ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem${s} ipsum dolo${c}r${se} sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test text object with count expands selection`() { + doTest( + "v2aw", + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing${c} ${se}elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test repeated text object expands selection to end of line`() { + doTest( + listOf("v2aw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing eli${c}t${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing elit.......${c}.${se} + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """ + ) + @Test + fun `test repeated text object expands selection to whitespace at end of line`() { + doTest( + listOf("v2aw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |con${c}sectetur adipiscing elit........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |${s}consectetur adipiscing eli${c}t${se}........ + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing${s} elit + |Sed${c} ${se}in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """ + ) + @Test + fun `test repeated text object expands across new line`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing el${c}it + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + listOf("vaw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing el${c}it + | Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + listOf("vaw", "aw"), + """ + |Lorem Ip${c}sum + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem${s} Ipsum + | + |${c}${se} + | + |Lorem 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 multiple empty lines`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ip${c}sum + | + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @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( + listOf("vaw", "aw"), + """ + |Lorem Ip${c}sum + |........ + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |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. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem${s} Ipsum + | + |........ + |${c} + |${se}Lorem 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 lines`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ip${c}sum + | + |........ + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |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. + """.trimMargin().dotToSpace(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // TODO: Fix this bug + @VimBehaviorDiffers(originalVimAfter = + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit${s} amet,${c} ${se}consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """ + ) + @Test + fun `test repeated text object expands over non-word character`() { + doTest( + listOf("vaw", "aw"), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem Ipsum + | + |Lorem ipsum dolor sit${s} amet${c},${se} consectetur adipiscing elit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word selects following whitespace up to punctuation`() { + doTest( + "vaw", + "Lorem ipsu${c}m ...dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum ${c} ${se}...dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word with following non-word characters selects preceding whitespace`() { + doTest( + "vaw", + "Lorem ipsum dolor sit a${c}met, consectetur adipiscing elit", + "Lorem ipsum dolor sit${s} ame${c}t${se}, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + // 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( + "vaw", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |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 with existing left-to-right selection selects rest of word and following whitespace`() { + doTest( + listOf("v", "l", "aw"), + "Lo${c}rem ipsum", + "Lo${s}rem ${c} ${se}ipsum", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word with existing left-to-right selection in whitespace selects rest of whitespace and following word`() { + doTest( + listOf("v", "l", "aw"), + "Lorem ${c} ipsum dolor sit amet", + "Lorem ${s} ipsu${c}m${se} dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word with existing right-to-left selection selects rest of word and preceding whitespace`() { + doTest( + listOf("v", "h", "aw"), + "Lorem ip${c}sum dolor sit amet", + "Lorem${s}${c} ips${se}um dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select outer word with existing right-to-left selection in whitespace selects rest of whitespace and preceding word`() { + doTest( + listOf("v", "h", "aw"), + "Lorem ipsum ${c} dolor sit amet", + "Lorem ${s}${c}ipsum ${se} dolor sit amet", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer words selects following whitespace`() { + doTest( + "v2aw", + "Lorem ipsu${c}m dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum dolor${c} ${se}sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer words with non-word characters`() { + doTest( + "v2aw", + "Lorem ipsu${c}m -- dolor sit amet, consectetur adipiscing elit", + "Lorem ${s}ipsum --${c} ${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer words with no following whitespace selects preceding whitespace`() { + doTest( + "v2aw", + "Lorem ipsu${c}m --dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsum -${c}-${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @VimBehaviorDiffers(originalVimAfter = + "Lorem${s} ipsum --dolor${c} ${se}sit amet, consectetur adipiscing elit", + description = "First aw should select whitespace+'ipsum' " + + "second should select whitespace+'--' " + + "third should select 'dolor' and following whitespace", + ) + @Test + fun `test select multiple outer words starting in whitespace`() { + doTest( + "v3aw", + "Lorem ${c} ipsum --dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsum --dolo${c}r${se} sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @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 + doTest( + "v2aw", + "Lorem ip${c}sum --dolor sit amet, consectetur adipiscing elit", + "Lorem${s} ipsum -${c}-${se}dolor sit amet, consectetur adipiscing elit", + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } + + @Test + fun `test select multiple outer words crosses end of line`() { + doTest( + "v2aw", + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing e${c}lit + |Sed in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, consectetur adipiscing ${s}elit + |Sed${c} ${se}in orci mauris. Cras id tellus in ex imperdiet egestas. + """.trimMargin(), + Mode.VISUAL(SelectionType.CHARACTER_WISE), + ) + } +}