mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-03-07 21:32:52 +01:00
Support multicaret for entering visual mode with count
This commit is contained in:
parent
b3f3a307ba
commit
4237ce9b3c
src/com/maddyhome/idea/vim
ex
group
test/org/jetbrains/plugins/ideavim/action/motion/visual
@ -242,7 +242,7 @@ public class Ranges {
|
||||
endLine = range.getLine(editor, context, lastZero);
|
||||
if (range.isMove()) {
|
||||
MotionGroup.moveCaret(editor, editor.getCaretModel().getPrimaryCaret(),
|
||||
VimPlugin.getMotion().moveCaretToLine(editor, endLine));
|
||||
VimPlugin.getMotion().moveCaretToLine(editor, endLine, editor.getCaretModel().getPrimaryCaret()));
|
||||
}
|
||||
// Did that last range represent the start of the file?
|
||||
lastZero = (endLine < 0);
|
||||
@ -265,7 +265,7 @@ public class Ranges {
|
||||
startLine = endLine;
|
||||
endLine = range.getLine(editor, caret, context, lastZero);
|
||||
|
||||
if (range.isMove()) MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLine(editor, endLine));
|
||||
if (range.isMove()) MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLine(editor, endLine, editor.getCaretModel().getPrimaryCaret()));
|
||||
|
||||
lastZero = endLine < 0;
|
||||
++count;
|
||||
|
@ -41,7 +41,7 @@ class RepeatHandler : CommandHandler(commands("@"),
|
||||
lastArg = arg
|
||||
|
||||
val line = cmd.getLine(editor, caret, context)
|
||||
MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLine(editor, line))
|
||||
MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLine(editor, line, editor.caretModel.primaryCaret))
|
||||
|
||||
if (arg == ':') {
|
||||
return CommandParser.getInstance().processLastCommand(editor, context, 1)
|
||||
|
@ -1098,8 +1098,8 @@ public class MotionGroup {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int moveCaretToLine(@NotNull Editor editor, int logicalLine) {
|
||||
int col = CaretDataKt.getVimLastColumn(editor.getCaretModel().getPrimaryCaret());
|
||||
public int moveCaretToLine(@NotNull Editor editor, int logicalLine, @NotNull Caret caret) {
|
||||
int col = CaretDataKt.getVimLastColumn(caret);
|
||||
int line = logicalLine;
|
||||
if (logicalLine < 0) {
|
||||
line = 0;
|
||||
|
@ -129,17 +129,16 @@ class VisualMotionGroup {
|
||||
if (!CommandState.inVisualMode(editor)) {
|
||||
// Enable visual subMode
|
||||
if (rawCount > 0) {
|
||||
if (editor.caretModel.caretCount > 1) {
|
||||
// FIXME: 2019-03-05 Support multicaret
|
||||
return false
|
||||
}
|
||||
val range = editor.caretModel.primaryCaret.vimLastVisualOperatorRange ?: VisualChange.default(subMode)
|
||||
val end = VisualOperation.calculateRange(editor, range, count)
|
||||
val lastColumn = if (range.columns == MotionGroup.LAST_COLUMN) MotionGroup.LAST_COLUMN else editor.offsetToLogicalPosition(end).column
|
||||
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, range.type.toSubMode(), MappingMode.VISUAL)
|
||||
val primarySubMode = editor.caretModel.primaryCaret.vimLastVisualOperatorRange?.type?.toSubMode()
|
||||
?: subMode
|
||||
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, primarySubMode, MappingMode.VISUAL)
|
||||
|
||||
editor.vimForAllOrPrimaryCaret {
|
||||
val range = it.vimLastVisualOperatorRange ?: VisualChange.default(subMode)
|
||||
val end = VisualOperation.calculateRange(editor, range, count, it)
|
||||
val lastColumn = if (range.columns == MotionGroup.LAST_COLUMN) MotionGroup.LAST_COLUMN else editor.offsetToLogicalPosition(end).column
|
||||
it.vimLastColumn = lastColumn
|
||||
it.vimSetSelection(editor.caretModel.offset, end, true)
|
||||
it.vimSetSelection(it.offset, end, true)
|
||||
}
|
||||
} else {
|
||||
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, subMode, MappingMode.VISUAL)
|
||||
|
@ -79,7 +79,7 @@ class VisualOperation {
|
||||
/**
|
||||
* Calculate end offset of [VisualChange]
|
||||
*/
|
||||
fun calculateRange(editor: Editor, range: VisualChange, count: Int): Int {
|
||||
fun calculateRange(editor: Editor, range: VisualChange, count: Int, caret: Caret): Int {
|
||||
var (lines, chars, type) = range
|
||||
if (type == SelectionType.LINE_WISE || type == SelectionType.BLOCK_WISE || lines > 1) {
|
||||
lines *= count
|
||||
@ -87,16 +87,15 @@ class VisualOperation {
|
||||
if (type == SelectionType.CHARACTER_WISE && lines == 1 || type == SelectionType.BLOCK_WISE) {
|
||||
chars *= count
|
||||
}
|
||||
val start = editor.caretModel.offset
|
||||
val sp = editor.offsetToLogicalPosition(start)
|
||||
val sp = editor.offsetToLogicalPosition(caret.offset)
|
||||
val linesDiff = (lines - 1).coerceAtLeast(0)
|
||||
val endLine = (sp.line + linesDiff).coerceAtMost(editor.document.lineCount - 1)
|
||||
|
||||
return when (type) {
|
||||
SelectionType.LINE_WISE -> VimPlugin.getMotion().moveCaretToLine(editor, endLine)
|
||||
SelectionType.LINE_WISE -> VimPlugin.getMotion().moveCaretToLine(editor, endLine, caret)
|
||||
SelectionType.CHARACTER_WISE -> when {
|
||||
lines > 1 -> VimPlugin.getMotion().moveCaretToLineStart(editor, endLine) + min(EditorHelper.getLineLength(editor, endLine), chars)
|
||||
else -> EditorHelper.normalizeOffset(editor, sp.line, start + chars - 1, true)
|
||||
else -> EditorHelper.normalizeOffset(editor, sp.line, caret.offset + chars - 1, true)
|
||||
}
|
||||
SelectionType.BLOCK_WISE -> {
|
||||
val endColumn = min(EditorHelper.getLineLength(editor, endLine), sp.column + chars - 1)
|
||||
|
@ -47,7 +47,7 @@ fun SelectionModel.vimSetSystemBlockSelectionSilently(start: LogicalPosition, en
|
||||
fun Caret.vimSetSystemSelectionSilently(start: Int, end: Int) =
|
||||
SelectionVimListenerSuppressor.lock().use { setSelection(start, end) }
|
||||
|
||||
inline fun Editor.vimForAllOrPrimaryCaret(action: (caret: Caret) -> Unit) {
|
||||
fun Editor.vimForAllOrPrimaryCaret(action: (caret: Caret) -> Unit) {
|
||||
if (CommandState.inVisualBlockMode(this)) {
|
||||
action(this.caretModel.primaryCaret)
|
||||
} else {
|
||||
|
@ -130,6 +130,27 @@ class VisualToggleCharacterModeActionTest : VimTestCase() {
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_CHARACTER)
|
||||
}
|
||||
|
||||
fun `test enter visual with count multicaret`() {
|
||||
doTest(parseKeys("1v"),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${c}found it in a legendary land
|
||||
all rocks and ${c}lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${s}${c}f${se}ound it in a legendary land
|
||||
all rocks and ${s}${c}l${se}avender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_CHARACTER)
|
||||
}
|
||||
|
||||
fun `test enter visual with five count`() {
|
||||
doTest(parseKeys("5v"),
|
||||
"""
|
||||
@ -193,6 +214,27 @@ class VisualToggleCharacterModeActionTest : VimTestCase() {
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_CHARACTER)
|
||||
}
|
||||
|
||||
fun `test enter visual with count after visual operation multicaret`() {
|
||||
doTest(parseKeys("vedx", "1v"),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${c}found it in a legendary land
|
||||
all rocks and ${c}lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${s}it i${c}n${se} a legendary land
|
||||
all rocks and ${s}and tuf${c}t${se}ed grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_CHARACTER)
|
||||
}
|
||||
|
||||
fun `test enter visual with count after visual operation multiple time`() {
|
||||
doTest(parseKeys("vedx", "1v", "<ESC>bb", "1v"),
|
||||
"""
|
||||
@ -248,7 +290,7 @@ class VisualToggleCharacterModeActionTest : VimTestCase() {
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${s}it in a legendary lan${c}d${se}
|
||||
I ${s}it in a legendary land${c}${se}
|
||||
all rocks and lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
@ -330,7 +372,7 @@ class VisualToggleCharacterModeActionTest : VimTestCase() {
|
||||
A Discovery
|
||||
|
||||
I
|
||||
${s}all rocks and lavender and tufted grass${c},${se}
|
||||
${s}all rocks and lavender and tufted grass,${c}${se}
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
@ -378,6 +420,23 @@ class VisualToggleCharacterModeActionTest : VimTestCase() {
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_LINE)
|
||||
}
|
||||
|
||||
fun `test enter visual with count after line visual operation multicaret`() {
|
||||
doTest(parseKeys("Vd", "1v"),
|
||||
"""
|
||||
A ${c}Discovery
|
||||
|
||||
I found it in a legendary land
|
||||
all ${c}rocks and lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.""".trimIndent(),
|
||||
"""
|
||||
${s}${c}
|
||||
${se}I found it in a legendary land
|
||||
${s}${c}where it was settled on some sodden sand
|
||||
${se}hard by the torrent of a mountain pass.""".trimIndent(),
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_LINE)
|
||||
}
|
||||
|
||||
fun `test enter visual with double count after line visual operation`() {
|
||||
doTest(parseKeys("Vd", "2v"),
|
||||
"""
|
||||
|
@ -46,6 +46,27 @@ class VisualToggleLineModeActionTest : VimTestCase() {
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_LINE)
|
||||
}
|
||||
|
||||
fun `test enter visual with count multicaret`() {
|
||||
doTest(parseKeys("1V"),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
I ${c}found it in a legendary land
|
||||
all rocks and lavender and tufted grass,
|
||||
where it ${c}was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
"""
|
||||
A Discovery
|
||||
|
||||
${s}I ${c}found it in a legendary land
|
||||
${se}all rocks and lavender and tufted grass,
|
||||
${s}where it ${c}was settled on some sodden sand
|
||||
${se}hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_LINE)
|
||||
}
|
||||
|
||||
fun `test enter visual with 3 count`() {
|
||||
doTest(parseKeys("3V"),
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user