diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndLeftActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndLeftActionTest.kt index debfd78e0..2bcff0cee 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndLeftActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndLeftActionTest.kt @@ -127,4 +127,136 @@ class MotionBigWordEndLeftActionTest : VimTestCase() { doTest("100gE", "Lorem ip${c}sum", "${c}Lorem ipsum") assertPluginError(false) } + + @Test + fun `test move to previous WORD end should treat empty lines as WORD`() { + doTest( + "gE", + """ + |Lorem ipsum dolor sit amet, + | + |${c}consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + |${c} + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous WORD end should treat empty lines as WORD 2`() { + doTest( + "gE", + """ + |Lorem ipsum dolor sit amet, + | + | + | + |${c} + | + |consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + | + | + |${c} + | + | + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous WORD end with count across empty lines`() { + doTest( + "3gE", + """ + |Lorem ipsum dolor sit amet, + | + | + | + | + |${c} + |consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + | + |${c} + | + | + | + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous WORD end with count includes empty lines`() { + doTest( + "5gE", + """ + |Lorem ipsum + | + |Lorem ipsum + | + |${c} + |Lorem ipsum + """.trimMargin(), + """ + |Lorem ipsu${c}m + | + |Lorem ipsum + | + | + |Lorem ipsum + """.trimMargin(), + ) + } + + @Test + fun `test move to previous WORD end should ignore blank lines`() { + doTest( + "gE", + """ + |Lorem ipsum dolor sit amet, + | + |.......... + |${c} + |consectetur adipiscing elit + """.trimMargin().dotToSpace(), + """ + |Lorem ipsum dolor sit amet, + |${c} + |.......... + | + |consectetur adipiscing elit + """.trimMargin().dotToSpace(), + ) + } + + @Test + fun `test move to previous WORD end should ignore blank lines in count`() { + doTest( + "3gE", + """ + |Lorem ipsum + | + |.......... + |${c} + |Lorem ipsum + """.trimMargin().dotToSpace(), + """ + |Lore${c}m ipsum + | + |.......... + | + |Lorem ipsum + """.trimMargin().dotToSpace(), + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndRightActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndRightActionTest.kt index 86fa5dc2f..4ad94238f 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndRightActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordEndRightActionTest.kt @@ -119,4 +119,85 @@ class MotionBigWordEndRightActionTest : VimTestCase() { doTest("300E", "${c}Lorem ipsum", "Lorem ipsu${c}m") assertPluginError(false) } + + @Test + fun `test move to WORD end does not treat empty line as WORD`() { + doTest( + "E", + """ + |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 Ipsum + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test move to WORD end does not treat empty line as WORD 2`() { + doTest( + "E", + """ + |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 Ipsum + | + | + | + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test move to WORD end does not treat blank line as WORD`() { + doTest( + "E", + """ + |Lorem Ipsu${c}m + | + |.......... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |.......... + | + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordLeftActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordLeftActionTest.kt index 4206ff737..257aad787 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordLeftActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordLeftActionTest.kt @@ -195,4 +195,149 @@ class MotionBigWordLeftActionTest : VimTestCase() { doTest("B", "${c}Lorem Ipsum", "${c}Lorem Ipsum") assertPluginError(true) } + + @Test + fun `test empty line is treated as WORD`() { + doTest( + "<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 + |${c} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as WORD 2`() { + doTest( + "B", + """ + |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 + | + |${c} + | + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as WORD 3`() { + doTest( + "3<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 + | + | + |${c} + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test blank line is not treated as WORD`() { + doTest( + "B", + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } + + @Test + fun `test blank line is not treated as WORD 2`() { + doTest( + "<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().dotToSpace(), + """ + |Lorem Ipsum + | + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordRightActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordRightActionTest.kt index f77a9f410..6d807efb2 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordRightActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionBigWordRightActionTest.kt @@ -134,4 +134,143 @@ class MotionBigWordRightActionTest : VimTestCase() { doTest("100W", "L${c}orem Ipsum", "Lorem Ipsu${c}m") assertPluginError(false) } + + @Test + fun `test empty line is treated as WORD`() { + doTest( + "W", + """ + |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 Ipsum + |${c} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as WORD 2`() { + doTest( + "<C-Right>", + """ + |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 + | + | + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as WORD 3`() { + doTest( + "3<C-Right>", + """ + |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 Ipsum + | + | + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test blank line is not treated as WORD`() { + doTest( + "W", + """ + |Lorem Ipsum + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } + + @Test + fun `test blank line is not treated as WORD 2`() { + doTest( + "<C-Right>", + """ + |Lorem Ipsum + | + |.${c}.. + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndLeftActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndLeftActionTest.kt index 82b5734b4..4234f691c 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndLeftActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndLeftActionTest.kt @@ -127,4 +127,136 @@ class MotionWordEndLeftActionTest : VimTestCase() { doTest("100ge", "Lorem ip${c}sum", "${c}Lorem ipsum") assertPluginError(false) } + + @Test + fun `test move to previous word end should treat empty lines as word`() { + doTest( + "ge", + """ + |Lorem ipsum dolor sit amet, + | + |${c}consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + |${c} + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous word end should treat empty lines as word 2`() { + doTest( + "ge", + """ + |Lorem ipsum dolor sit amet, + | + | + | + |${c} + | + |consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + | + | + |${c} + | + | + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous word end with count across empty lines`() { + doTest( + "3ge", + """ + |Lorem ipsum dolor sit amet, + | + | + | + | + |${c} + |consectetur adipiscing elit + """.trimMargin(), + """ + |Lorem ipsum dolor sit amet, + | + |${c} + | + | + | + |consectetur adipiscing elit + """.trimMargin(), + ) + } + + @Test + fun `test move to previous word end with count includes empty lines`() { + doTest( + "5ge", + """ + |Lorem ipsum + | + |Lorem ipsum + | + |${c} + |Lorem ipsum + """.trimMargin(), + """ + |Lorem ipsu${c}m + | + |Lorem ipsum + | + | + |Lorem ipsum + """.trimMargin(), + ) + } + + @Test + fun `test move to previous word end should ignore blank lines`() { + doTest( + "ge", + """ + |Lorem ipsum dolor sit amet, + | + |.......... + |${c} + |consectetur adipiscing elit + """.trimMargin().dotToSpace(), + """ + |Lorem ipsum dolor sit amet, + |${c} + |.......... + | + |consectetur adipiscing elit + """.trimMargin().dotToSpace(), + ) + } + + @Test + fun `test move to previous word end should ignore blank lines in count`() { + doTest( + "3ge", + """ + |Lorem ipsum + | + |.......... + |${c} + |Lorem ipsum + """.trimMargin().dotToSpace(), + """ + |Lore${c}m ipsum + | + |.......... + | + |Lorem ipsum + """.trimMargin().dotToSpace(), + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndRightActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndRightActionTest.kt index df4ca0ae4..cc9459222 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndRightActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordEndRightActionTest.kt @@ -119,4 +119,85 @@ class MotionWordEndRightActionTest : VimTestCase() { doTest("300e", "${c}Lorem ipsum", "Lorem ipsu${c}m") assertPluginError(false) } + + @Test + fun `test move to word end does not treat empty line as word`() { + doTest( + "e", + """ + |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 Ipsum + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test move to word end does not treat empty line as word 2`() { + doTest( + "e", + """ + |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 Ipsum + | + | + | + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test move to word end does not treat blank line as word`() { + doTest( + "e", + """ + |Lorem Ipsu${c}m + | + |.......... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |.......... + | + | + |Lore${c}m ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordLeftActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordLeftActionTest.kt index 7034607c4..44ef41f78 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordLeftActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordLeftActionTest.kt @@ -195,4 +195,149 @@ class MotionWordLeftActionTest : VimTestCase() { doTest("b", "${c}Lorem Ipsum", "${c}Lorem Ipsum") assertPluginError(true) } + + @Test + fun `test empty line is treated as word`() { + doTest( + "<S-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 + |${c} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as word 2`() { + doTest( + "b", + """ + |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 + | + |${c} + | + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as word 3`() { + doTest( + "3<S-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 + | + | + |${c} + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test blank line is not treated as word`() { + doTest( + "b", + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } + + @Test + fun `test blank line is not treated as word 2`() { + doTest( + "<S-Left>", + """ + |Lorem Ipsum + | + | + |.${c}.. + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordRightActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordRightActionTest.kt index d9008c8aa..c1d1ecc52 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordRightActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/motion/text/MotionWordRightActionTest.kt @@ -134,4 +134,143 @@ class MotionWordRightActionTest : VimTestCase() { doTest("100w", "L${c}orem Ipsum", "Lorem Ipsu${c}m") assertPluginError(false) } + + @Test + fun `test empty line is treated as word`() { + doTest( + "w", + """ + |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 Ipsum + |${c} + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as word 2`() { + doTest( + "<S-Right>", + """ + |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 + | + | + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test empty line is treated as word 3`() { + doTest( + "3<S-Right>", + """ + |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 Ipsum + | + | + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin() + ) + } + + @Test + fun `test blank line is not treated as word`() { + doTest( + "w", + """ + |Lorem Ipsum + |${c} + |... + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } + + @Test + fun `test blank line is not treated as word 2`() { + doTest( + "<S-Right>", + """ + |Lorem Ipsum + | + |.${c}.. + | + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace(), + """ + |Lorem Ipsum + | + |... + |${c} + | + |Lorem ipsum dolor sit amet, + |consectetur adipiscing elit + |Sed in orci mauris. + |Cras id tellus in ex imperdiet egestas. + """.trimMargin().dotToSpace() + ) + } } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimSearchHelperBase.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimSearchHelperBase.kt index 4892c16d8..426002535 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimSearchHelperBase.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimSearchHelperBase.kt @@ -321,7 +321,7 @@ abstract class VimSearchHelperBase : VimSearchHelper { // For back searches, skip any current whitespace so we start at the end of a word if (step < 0 && _pos > 0) { if (charType(editor, chars[_pos - 1], bigWord) === CharacterHelper.CharacterType.WHITESPACE && !spaceWords) { - _pos = skipSpace(editor, chars, pos - 1, step, size) + 1 + _pos = skipSpace(editor, chars, pos - 1, step, size, true) + 1 } // _pos might be at the end of file. Handle this so we don't try to walk backwards based on incorrect char type if (_pos == size || (_pos > 0 && charType(editor, chars[_pos], bigWord) !== charType(editor, chars[_pos - 1], bigWord))) { @@ -332,16 +332,19 @@ abstract class VimSearchHelperBase : VimSearchHelper { if (_pos < 0 || _pos >= size) { return _pos } - var type = charType(editor, chars[_pos], bigWord) + var char = chars[_pos] + var lineLength = 0 + var type = charType(editor, char, bigWord) if (type === CharacterHelper.CharacterType.WHITESPACE && step < 0 && _pos > 0 && !spaceWords) { type = charType(editor, chars[_pos - 1], bigWord) } _pos += step while (_pos in 0 until size && !found) { + val newChar = chars[_pos] val newType = charType(editor, chars[_pos], bigWord) if (newType !== type) { if (newType === CharacterHelper.CharacterType.WHITESPACE && step >= 0 && !spaceWords) { - _pos = skipSpace(editor, chars, _pos, step, size) + _pos = skipSpace(editor, chars, _pos, step, size, true) res = _pos } else if (step < 0) { res = _pos + 1 @@ -351,6 +354,14 @@ abstract class VimSearchHelperBase : VimSearchHelper { type = charType(editor, chars[res], bigWord) found = true } + else if (newChar == '\n' && lineLength == 0) { + // An empty line is considered a word/WORD + res = if (step < 0) _pos + 1 else _pos + found = true + } + + if (newChar == '\n') lineLength = 0 else lineLength++ + _pos += step } if (found) { @@ -380,15 +391,10 @@ abstract class VimSearchHelperBase : VimSearchHelper { var found = false // For forward searches, skip any current whitespace so we start at the start of a word if (step > 0 && pos < size - 1) { - if (charType(editor, chars[pos + 1], bigWord) === CharacterHelper.CharacterType.WHITESPACE && - !spaceWords - ) { - pos = skipSpace(editor, chars, pos + 1, step, size) - 1 + if (charType(editor, chars[pos + 1], bigWord) === CharacterHelper.CharacterType.WHITESPACE && !spaceWords) { + pos = skipSpace(editor, chars, pos + 1, step, size, false) - 1 } - if (pos < size - 1 && - charType(editor, chars[pos], bigWord) !== - charType(editor, chars[pos + 1], bigWord) - ) { + if (pos < size - 1 && charType(editor, chars[pos], bigWord) !== charType(editor, chars[pos + 1], bigWord)) { pos += step } } @@ -400,20 +406,29 @@ abstract class VimSearchHelperBase : VimSearchHelper { if (type === CharacterHelper.CharacterType.WHITESPACE && step >= 0 && pos < size - 1 && !spaceWords) { type = charType(editor, chars[pos + 1], bigWord) } + var lastChar = 0.toChar() pos += step while (pos >= 0 && pos < size && !found) { - val newType = charType(editor, chars[pos], bigWord) + var newChar = chars[pos] + val newType = charType(editor, newChar, bigWord) if (newType !== type) { if (step >= 0) { res = pos - 1 } else if (newType === CharacterHelper.CharacterType.WHITESPACE && step < 0 && !spaceWords) { - pos = skipSpace(editor, chars, pos, step, size) - res = pos + // `e` does not match empty lines, but `ge` does. + // This change in behaviour might be surprising to callers! + pos = skipSpace(editor, chars, pos, step, size, matchEmptyLine = step < 0) + res = if (pos >= 0 && chars[pos] == '\n') pos + 1 else pos } else { res = pos } found = true } + else if (newChar == '\n' && newChar == lastChar) { + res = if (step < 0) pos + 1 else pos + found = true + } + lastChar = newChar pos += step } if (found) { @@ -430,12 +445,19 @@ abstract class VimSearchHelperBase : VimSearchHelper { return res } - private fun skipSpace(editor: VimEditor, chars: CharSequence, offset: Int, step: Int, size: Int): Int { + private fun skipSpace( + editor: VimEditor, + chars: CharSequence, + offset: Int, + step: Int, + size: Int, + matchEmptyLine: Boolean, + ): Int { var _offset = offset var prev = 0.toChar() while (_offset in 0 until size) { val c = chars[_offset] - if (c == '\n' && c == prev) break + if (c == '\n' && c == prev && matchEmptyLine) break if (charType(editor, c, false) !== CharacterHelper.CharacterType.WHITESPACE) break prev = c _offset += step