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

Match empty line as word/WORD

Unless moving to end of word/WORD, in which case, skip all whitespace to get to end of the next set of word/WORD characters.

Fixes VIM-1650
This commit is contained in:
Matt Ellis 2024-12-18 01:07:22 +01:00 committed by Alex Pláte
parent afd69eef95
commit 580764b30c
9 changed files with 1032 additions and 16 deletions

View File

@ -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(),
)
}
}

View File

@ -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()
)
}
}

View File

@ -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()
)
}
}

View File

@ -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()
)
}
}

View File

@ -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(),
)
}
}

View File

@ -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()
)
}
}

View File

@ -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()
)
}
}

View File

@ -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()
)
}
}

View File

@ -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