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

Make yank motion respect exclusive-linewise

I used the code in VimChangeGroupBase.getDeleteRangeAndType to do the check.

For an example of what this fixes, with the document:
```
    ${c}Hello!
```
executing "y}llp" before this change yields
```
    HelHello!
    lo!
```
but doing it with this change yields
```
    Hello!
    Hello!
````
This commit is contained in:
Nath Tumlin 2025-02-27 17:17:28 -06:00 committed by Alex Pláte
parent cda85ae534
commit 156fbcd60d
2 changed files with 69 additions and 1 deletions
src/test/java/org/jetbrains/plugins/ideavim/action/copy
vim-engine/src/main/kotlin/com/maddyhome/idea/vim/yank

View File

@ -10,6 +10,7 @@ package org.jetbrains.plugins.ideavim.action.copy
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
@ -193,4 +194,52 @@ class YankMotionActionTest : VimTestCase() {
kotlin.test.assertEquals("hard by the torrent of a mountain pass.\n", text)
}
@Test
fun `test yank block works linewise if at start of line`() {
val file = """
Lorem Ipsum
${c}dolor sit amet
I found it in a legendary land
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
typeTextInFile("y}", file)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)
val text = register?.text ?: kotlin.test.fail()
val type = register.type
kotlin.test.assertEquals("dolor sit amet\n", text)
kotlin.test.assertEquals(SelectionType.LINE_WISE, type)
}
@Test
fun `test yank block works charwise if not at start of line`() {
val file = """
Lorem Ipsum
d${c}olor sit amet
I found it in a legendary land
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
typeTextInFile("y}", file)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)
val text = register?.text ?: kotlin.test.fail()
val type = register.type
kotlin.test.assertEquals("olor sit amet\n", text)
kotlin.test.assertEquals(SelectionType.CHARACTER_WISE, type)
}
}

View File

@ -13,12 +13,19 @@ import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.anyNonWhitespace
import com.maddyhome.idea.vim.api.getLineEndForOffset
import com.maddyhome.idea.vim.api.getLineStartForOffset
import com.maddyhome.idea.vim.api.getText
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.normalizeColumn
import com.maddyhome.idea.vim.api.normalizeLine
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.MotionType
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
import com.maddyhome.idea.vim.handler.MotionActionHandler
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.annotations.Contract
import kotlin.math.min
@ -82,7 +89,7 @@ open class YankGroupBase : VimYankGroup {
operatorArguments: OperatorArguments,
): Boolean {
val motion = argument as? Argument.Motion ?: return false
val motionType = motion.getMotionType()
var motionType = motion.getMotionType()
val nativeCaretCount = editor.nativeCarets().size
if (nativeCaretCount <= 0) return false
@ -98,6 +105,7 @@ open class YankGroupBase : VimYankGroup {
HashMap<VimCaret, Int>(nativeCaretCount)
}
for (caret in editor.nativeCarets()) {
val motionRange = injector.motion.getMotionRange(editor, caret, context, argument, operatorArguments)
?: continue
@ -106,6 +114,17 @@ open class YankGroupBase : VimYankGroup {
ranges.add(motionRange.startOffset to motionRange.endOffset)
startOffsets?.put(caret, motionRange.normalize().startOffset)
caretToRange[caret] = TextRange(motionRange.startOffset, motionRange.endOffset)
if (caret.isPrimary && argument.motion is MotionActionHandler && argument.motion.motionType == MotionType.EXCLUSIVE) {
val start = editor.offsetToBufferPosition(motionRange.startOffset)
val end = editor.offsetToBufferPosition(motionRange.endOffset)
if (start.line != end.line
&& !editor.anyNonWhitespace(motionRange.startOffset, -1)
&& !editor.anyNonWhitespace(motionRange.endOffset, 1)
) {
motionType = SelectionType.LINE_WISE
}
}
}
val range = getTextRange(ranges, motionType) ?: return false