mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-06-01 01:34:07 +02:00
fix: calculation to find the closest delimited range
This commit is contained in:
parent
01d776957a
commit
7b16deb3e3
src
main/java/com/maddyhome/idea/vim/extension/miniai
test/java/org/jetbrains/plugins/ideavim/extension/miniai
@ -194,42 +194,60 @@ private fun addAction(action: TextObjectActionHandler) {
|
|||||||
keyHandlerState.commandBuilder.addAction(action)
|
keyHandlerState.commandBuilder.addAction(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findClosestDelimitedRange(
|
||||||
|
caret: ImmutableVimCaret,
|
||||||
|
delimiters: List<Char>,
|
||||||
|
findRange: (Char) -> TextRange?
|
||||||
|
): TextRange? {
|
||||||
|
val allRanges = delimiters.mapNotNull { char ->
|
||||||
|
findRange(char)?.let { range ->
|
||||||
|
DelimitedRange(range, char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, find all ranges that contain the caret
|
||||||
|
val containingRanges = allRanges.filter {
|
||||||
|
caret.offset in it.range.startOffset..it.range.endOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have containing ranges, return the smallest one
|
||||||
|
if (containingRanges.isNotEmpty()) {
|
||||||
|
return containingRanges.minBy {
|
||||||
|
it.range.endOffset - it.range.startOffset
|
||||||
|
}.range
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no containing ranges, find the closest one
|
||||||
|
return allRanges
|
||||||
|
.minByOrNull { range ->
|
||||||
|
kotlin.math.abs(caret.offset - range.range.startOffset)
|
||||||
|
}?.range
|
||||||
|
}
|
||||||
|
|
||||||
private fun findClosestBracketRange(
|
private fun findClosestBracketRange(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
caret: ImmutableVimCaret,
|
caret: ImmutableVimCaret,
|
||||||
count: Int,
|
count: Int,
|
||||||
isOuter: Boolean,
|
isOuter: Boolean
|
||||||
): TextRange? {
|
): TextRange? {
|
||||||
return listOf('(', '[', '{')
|
val brackets = listOf('(', '[', '{')
|
||||||
.mapNotNull { char ->
|
return findClosestDelimitedRange(caret, brackets) { char ->
|
||||||
findBlockRange(editor, caret, char, count, isOuter)?.let { range -> range to char }
|
findBlockRange(editor, caret, char, count, isOuter)
|
||||||
}
|
}
|
||||||
.minByOrNull { it.first.distanceTo(caret.offset) }?.first
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findClosestQuoteRange(
|
private fun findClosestQuoteRange(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
caret: ImmutableVimCaret,
|
caret: ImmutableVimCaret,
|
||||||
isOuter: Boolean,
|
isOuter: Boolean
|
||||||
): TextRange? {
|
): TextRange? {
|
||||||
return listOf('`', '"', '\'')
|
val quotes = listOf('`', '"', '\'')
|
||||||
.mapNotNull { char ->
|
return findClosestDelimitedRange(caret, quotes) { char ->
|
||||||
injector.searchHelper.findBlockQuoteInLineRange(editor, caret, char, isOuter)?.let { range -> range to char }
|
injector.searchHelper.findBlockQuoteInLineRange(editor, caret, char, isOuter)
|
||||||
}
|
|
||||||
.minByOrNull { it.first.distanceTo(caret.offset) }?.first
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun TextRange.distanceTo(caretOffset: Int): Int {
|
|
||||||
val rangeLength = endOffset - startOffset
|
|
||||||
|
|
||||||
// If caret is inside the range
|
|
||||||
if (caretOffset in startOffset..endOffset) {
|
|
||||||
// Return the length of the range - smaller ranges get priority
|
|
||||||
return rangeLength
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If caret is outside, make the distance much larger
|
|
||||||
val startDistance = kotlin.math.abs(caretOffset - startOffset)
|
|
||||||
val endDistance = kotlin.math.abs(caretOffset - endOffset)
|
|
||||||
return (startDistance + endDistance) * 1000 + rangeLength
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class DelimitedRange(
|
||||||
|
val range: TextRange,
|
||||||
|
val char: Char
|
||||||
|
)
|
||||||
|
@ -10,19 +10,60 @@ package org.jetbrains.plugins.ideavim.extension.miniai
|
|||||||
|
|
||||||
import com.intellij.ide.highlighter.JavaFileType
|
import com.intellij.ide.highlighter.JavaFileType
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import org.jetbrains.plugins.ideavim.VimJavaTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInfo
|
import org.junit.jupiter.api.TestInfo
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
class MiniAIExtensionTest : VimJavaTestCase() {
|
class MiniAIExtensionTest : VimTestCase() {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
override fun setUp(testInfo: TestInfo) {
|
override fun setUp(testInfo: TestInfo) {
|
||||||
super.setUp(testInfo)
|
super.setUp(testInfo)
|
||||||
enableExtensions("mini-ai")
|
enableExtensions("mini-ai")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFromAlex() {
|
||||||
|
doTest(
|
||||||
|
"ciq",
|
||||||
|
"<caret>This is a \"'simple'\" test",
|
||||||
|
"This is a \"<caret>\" test",
|
||||||
|
Mode.INSERT,
|
||||||
|
JavaFileType.INSTANCE,
|
||||||
|
)
|
||||||
|
assertSelection(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// To make sure the order in list is not relevant
|
||||||
|
@Test
|
||||||
|
fun testChangeInsideBackQuoteWithNestedSingleQuote() {
|
||||||
|
doTest(
|
||||||
|
"ciq",
|
||||||
|
"<caret>This is a `'simple'` test",
|
||||||
|
"This is a `<caret>` test",
|
||||||
|
Mode.INSERT,
|
||||||
|
JavaFileType.INSTANCE,
|
||||||
|
)
|
||||||
|
assertSelection(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// To make sure the order in list is not relevant
|
||||||
|
@Test
|
||||||
|
fun testChangeInsideSingleQuoteWithNestedDoubleQuote() {
|
||||||
|
doTest(
|
||||||
|
"ciq",
|
||||||
|
"<caret>This is a '\"simple\"' test",
|
||||||
|
"This is a '<caret>' test",
|
||||||
|
Mode.INSERT,
|
||||||
|
JavaFileType.INSTANCE,
|
||||||
|
)
|
||||||
|
assertSelection(null)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testChangeInsideNestedQuotes() {
|
fun testChangeInsideNestedQuotes() {
|
||||||
doTest(
|
doTest(
|
Loading…
Reference in New Issue
Block a user