in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimMotionGroupBase.kt [335:421]
override fun getMotionRange(
editor: VimEditor,
caret: ImmutableVimCaret,
context: ExecutionContext,
argument: Argument,
operatorArguments: OperatorArguments,
): TextRange? {
if (argument !is Argument.Motion) {
throw RuntimeException("Unexpected argument passed to getMotionRange2: $argument")
}
var start: Int
var end: Int
val action = argument.motion
when (action) {
is MotionActionHandler -> {
// This is where we are now
start = caret.offset
// Execute the motion (without moving the cursor) and get where we end
val motion = action.getHandlerOffset(editor, caret, context, argument.argument, operatorArguments)
if (Motion.Error == motion || Motion.NoMotion == motion) return null
end = (motion as AbsoluteOffset).offset
// If inclusive, add the last character to the range
if (action.motionType === MotionType.INCLUSIVE) {
if (start > end) {
if (start < editor.fileSize()) start++
} else {
if (end < editor.fileSize()) end++
}
}
}
is TextObjectActionHandler -> {
val range: TextRange =
action.getRange(editor, caret, context, operatorArguments.count1, operatorArguments.count0)
?: return null
start = range.startOffset
end = range.endOffset
if (argument.isLinewiseMotion()) end--
}
is ExternalActionHandler -> {
val range: TextRange = action.getRange(caret) ?: return null
start = range.startOffset
end = range.endOffset
if (argument.isLinewiseMotion()) end--
}
else -> throw RuntimeException("Commands doesn't take " + action.javaClass.simpleName + " as an operator")
}
// Normalize the range
if (start > end) {
val t = start
start = end
end = t
}
// If we are a linewise motion we need to normalize the start and stop then move the start to the beginning
// of the line and move the end to the end of the line.
if (argument.isLinewiseMotion()) {
start = editor.getLineStartForOffset(start)
end = if (caret.getBufferPosition().line != editor.lineCount() - 1) {
min((editor.getLineEndForOffset(end) + 1).toLong(), editor.fileSize()).toInt()
} else {
editor.getLineEndForOffset(end)
}
}
// This is a kludge for dw, dW, and d[w. Without this kludge, an extra newline is operated when it shouldn't be.
val text = editor.text().subSequence(start, end).toString()
val lastNewLine = text.lastIndexOf('\n')
if (lastNewLine > 0) {
val id = action.id
if (id == "VimMotionWordRightAction" || id == "VimMotionBigWordRightAction" || id == "VimMotionCamelRightAction") {
if (!editor.anyNonWhitespace(end, -1)) {
end = start + lastNewLine
}
}
}
return TextRange(start, end)
}