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

Write most of multicaret leftright actions.

MotionColumnAction, MotionFirstColumnAction, MotionFirstNonSpaceAction, MotionLastColumnAction, MostionLastMatchCharAction, MotionLastMatchCharReverseAction, MotionLastNonSpaceAction, MotionLeftAction, MotionLeftMatchCharAction, MotionLeftTillMatchCharAction, MotionRightAction, MotionRightMatchCharAction, MotionRightTillMatchCharAction now have their own native multi-caret implementations.
This commit is contained in:
Vasily Alferov 2018-03-29 10:18:35 +05:30
parent 56ad6b4c0d
commit 4d46000ec6
18 changed files with 321 additions and 117 deletions

View File

@ -2,14 +2,7 @@
<code_scheme name="Project" version="173">
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="false" />
<option name="SMART_TABS" value="false" />
<option name="LABEL_INDENT_SIZE" value="0" />
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
<option name="USE_RELATIVE_INDENTS" value="false" />
</value>
</option>
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
@ -70,7 +63,6 @@
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="ECMA Script Level 4">
<option name="KEEP_LINE_BREAKS" value="false" />
@ -96,7 +88,6 @@
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="GSP">
<indentOptions>
@ -130,7 +121,6 @@
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
</indentOptions>
@ -176,7 +166,6 @@
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
@ -185,7 +174,6 @@
</codeStyleSettings>
<codeStyleSettings language="JSON">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="JSP">
<indentOptions>
@ -215,15 +203,11 @@
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="Python">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="SQL">
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -36,10 +37,17 @@ public class MotionColumnAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToColumn(editor, count - 1, false);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToColumn(editor, caret, count - 1, false);
}
@Override
protected void postMove(@NotNull Editor editor, DataContext context, @NotNull Command cmd) {
EditorData.setLastColumn(editor, cmd.getCount() - 1);
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -34,8 +35,14 @@ public class MotionFirstColumnAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineStart(editor);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineStart(editor, caret);
}
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -34,8 +35,14 @@ public class MotionFirstNonSpaceAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor, caret);
}
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -40,7 +41,13 @@ public class MotionLastColumnAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
boolean allow = false;
if (CommandState.inInsertMode(editor)) {
allow = true;
@ -52,7 +59,7 @@ public class MotionLastColumnAction extends MotionEditorAction {
}
}
return VimPlugin.getMotion().moveCaretToLineEndOffset(editor, count - 1, allow);
return VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret,count - 1, allow);
}
protected void postMove(@NotNull Editor editor, DataContext context, Command cmd) {

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -34,8 +35,14 @@ public class MotionLastMatchCharAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().repeatLastMatchChar(editor, count);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().repeatLastMatchChar(editor, caret, count);
}
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -34,8 +35,14 @@ public class MotionLastMatchCharReverseAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().repeatLastMatchChar(editor, -count);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().repeatLastMatchChar(editor, caret, -count);
}
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -34,8 +35,14 @@ public class MotionLastNonSpaceAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineEndSkipLeadingOffset(editor, count - 1);
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, Argument argument) {
return VimPlugin.getMotion().moveCaretToLineEndSkipLeadingOffset(editor, caret, count - 1);
}
}
}

View File

@ -24,6 +24,7 @@ import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
import com.maddyhome.idea.vim.command.Argument;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.handler.MotionEditorActionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -40,9 +41,19 @@ public class MotionLeftAction extends MotionEditorAction {
super(true);
}
public int getOffset(@NotNull Editor editor, @Nullable Caret caret, @NotNull DataContext context, int count,
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context, int count,
int rawCount, @Nullable Argument argument) {
if (CommandState.inVisualBlockMode(editor)) {
// In visual block mode, ideavim creates multiple carets to make a selection on each line.
// Only the primary caret of the selection should be moved though. This temporary hack
// prevents the additional carets from being moved.
if (caret != editor.getCaretModel().getPrimaryCaret()) {
count = 0;
}
}
return VimPlugin.getMotion().moveCaretHorizontal(editor, caret, -count, false);
}
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -35,8 +36,14 @@ public class MotionLeftMatchCharAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToNextCharacterOnLine(editor, -count, argument.getCharacter());
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToNextCharacterOnLine(editor, caret, -count, argument.getCharacter());
VimPlugin.getMotion().setLastFTCmd(MotionGroup.LAST_F, argument.getCharacter());
return res;
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -35,8 +36,14 @@ public class MotionLeftTillMatchCharAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToBeforeNextCharacterOnLine(editor, -count, argument.getCharacter());
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToBeforeNextCharacterOnLine(editor, caret, -count, argument.getCharacter());
VimPlugin.getMotion().setLastFTCmd(MotionGroup.LAST_T, argument.getCharacter());
return res;
}

View File

@ -24,6 +24,7 @@ import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
import com.maddyhome.idea.vim.command.Argument;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.handler.MotionEditorActionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -40,8 +41,17 @@ public class MotionRightAction extends MotionEditorAction {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @Nullable Caret caret, @NotNull DataContext context, int count,
int rawCount, @Nullable Argument argument) {
if (CommandState.inVisualBlockMode(editor)) {
// In visual block mode, ideavim creates multiple carets to make a selection on each line.
// Only the primary caret of the selection should be moved though. This temporary hack
// prevents the additional carets from being moved.
if (caret != editor.getCaretModel().getPrimaryCaret()) {
count = 0;
}
}
return VimPlugin.getMotion().moveCaretHorizontal(editor, caret, count, true);
}
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -35,8 +36,14 @@ public class MotionRightMatchCharAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToNextCharacterOnLine(editor, count, argument.getCharacter());
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToNextCharacterOnLine(editor, caret, count, argument.getCharacter());
VimPlugin.getMotion().setLastFTCmd(MotionGroup.LAST_f, argument.getCharacter());
return res;
}

View File

@ -19,6 +19,7 @@
package com.maddyhome.idea.vim.action.motion.leftright;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
@ -35,8 +36,14 @@ public class MotionRightTillMatchCharAction extends MotionEditorAction {
}
private static class Handler extends MotionEditorActionHandler {
public int getOffset(@NotNull Editor editor, DataContext context, int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToBeforeNextCharacterOnLine(editor, count, argument.getCharacter());
public Handler() {
super(true);
}
@Override
public int getOffset(@NotNull Editor editor, @NotNull Caret caret, @NotNull DataContext context,
int count, int rawCount, @NotNull Argument argument) {
int res = VimPlugin.getMotion().moveCaretToBeforeNextCharacterOnLine(editor, caret, count, argument.getCharacter());
VimPlugin.getMotion().setLastFTCmd(MotionGroup.LAST_t, argument.getCharacter());
return res;
}

View File

@ -700,26 +700,26 @@ public class MotionGroup {
this.lastFTChar = lastChar;
}
public int repeatLastMatchChar(@NotNull Editor editor, int count) {
public int repeatLastMatchChar(@NotNull Editor editor, @NotNull Caret caret, int count) {
int res = -1;
int startPos = editor.getCaretModel().getOffset();
switch (lastFTCmd) {
case LAST_F:
res = moveCaretToNextCharacterOnLine(editor, -count, lastFTChar);
res = moveCaretToNextCharacterOnLine(editor, caret, -count, lastFTChar);
break;
case LAST_f:
res = moveCaretToNextCharacterOnLine(editor, count, lastFTChar);
res = moveCaretToNextCharacterOnLine(editor, caret, count, lastFTChar);
break;
case LAST_T:
res = moveCaretToBeforeNextCharacterOnLine(editor, -count, lastFTChar);
res = moveCaretToBeforeNextCharacterOnLine(editor, caret, -count, lastFTChar);
if (res == startPos && Math.abs(count) == 1) {
res = moveCaretToBeforeNextCharacterOnLine(editor, 2 * count, lastFTChar);
res = moveCaretToBeforeNextCharacterOnLine(editor, caret, 2 * count, lastFTChar);
}
break;
case LAST_t:
res = moveCaretToBeforeNextCharacterOnLine(editor, count, lastFTChar);
res = moveCaretToBeforeNextCharacterOnLine(editor, caret, count, lastFTChar);
if (res == startPos && Math.abs(count) == 1) {
res = moveCaretToBeforeNextCharacterOnLine(editor, 2 * count, lastFTChar);
res = moveCaretToBeforeNextCharacterOnLine(editor, caret, 2 * count, lastFTChar);
}
break;
}
@ -730,13 +730,14 @@ public class MotionGroup {
/**
* This moves the caret to the next/previous matching character on the current line
*
* @param caret The caret to be moved
* @param count The number of occurrences to move to
* @param ch The character to search for
* @param editor The editor to search in
* @return True if [count] character matches were found, false if not
*/
public int moveCaretToNextCharacterOnLine(@NotNull Editor editor, int count, char ch) {
int pos = SearchHelper.findNextCharacterOnLine(editor, count, ch);
public int moveCaretToNextCharacterOnLine(@NotNull Editor editor, @NotNull Caret caret, int count, char ch) {
int pos = SearchHelper.findNextCharacterOnLine(editor, caret, count, ch);
if (pos >= 0) {
return pos;
@ -749,13 +750,14 @@ public class MotionGroup {
/**
* This moves the caret next to the next/previous matching character on the current line
*
* @param caret The caret to be moved
* @param count The number of occurrences to move to
* @param ch The character to search for
* @param editor The editor to search in
* @return True if [count] character matches were found, false if not
*/
public int moveCaretToBeforeNextCharacterOnLine(@NotNull Editor editor, int count, char ch) {
int pos = SearchHelper.findNextCharacterOnLine(editor, count, ch);
public int moveCaretToBeforeNextCharacterOnLine(@NotNull Editor editor, @NotNull Caret caret, int count, char ch) {
int pos = SearchHelper.findNextCharacterOnLine(editor, caret, count, ch);
if (pos >= 0) {
int step = count >= 0 ? 1 : -1;
@ -1046,18 +1048,32 @@ public class MotionGroup {
return moveCaretToColumn(editor, Math.max(0, Math.min(len - 1, width)), false);
}
public int moveCaretToColumn(@NotNull Editor editor, int count, boolean allowEnd) {
int line = editor.getCaretModel().getLogicalPosition().line;
public int moveCaretToColumn(@NotNull Editor editor, @NotNull Caret caret, int count, boolean allowEnd) {
int line = caret.getLogicalPosition().line;
int pos = EditorHelper.normalizeColumn(editor, line, count, allowEnd);
return editor.logicalPositionToOffset(new LogicalPosition(line, pos));
}
public int moveCaretToLineStartSkipLeading(@NotNull Editor editor) {
int logicalLine = editor.getCaretModel().getLogicalPosition().line;
/**
* @deprecated To move the caret, use {@link #moveCaretToColumn(Editor, Caret, int, boolean)}
*/
public int moveCaretToColumn(@NotNull Editor editor, int count, boolean allowEnd) {
return moveCaretToColumn(editor, editor.getCaretModel().getPrimaryCaret(), count, allowEnd);
}
public int moveCaretToLineStartSkipLeading(@NotNull Editor editor, @NotNull Caret caret) {
int logicalLine = caret.getLogicalPosition().line;
return moveCaretToLineStartSkipLeading(editor, logicalLine);
}
/**
* @deprecated To move the caret, use {@link #moveCaretToLineStartSkipLeading(Editor, Caret)}
*/
public int moveCaretToLineStartSkipLeading(@NotNull Editor editor) {
return moveCaretToLineStartSkipLeading(editor, editor.getCaretModel().getPrimaryCaret());
}
public int moveCaretToLineStartSkipLeadingOffset(@NotNull Editor editor, int linesOffset) {
int line = EditorHelper.normalizeVisualLine(editor, editor.getCaretModel().getVisualPosition().line + linesOffset);
return moveCaretToLineStartSkipLeading(editor, EditorHelper.visualLineToLogicalLine(editor, line));
@ -1072,8 +1088,8 @@ public class MotionGroup {
return moveCaretToLineEndSkipLeading(editor, logicalLine);
}
public int moveCaretToLineEndSkipLeadingOffset(@NotNull Editor editor, int linesOffset) {
int line = EditorHelper.normalizeVisualLine(editor, editor.getCaretModel().getVisualPosition().line + linesOffset);
public int moveCaretToLineEndSkipLeadingOffset(@NotNull Editor editor, @NotNull Caret caret, int linesOffset) {
int line = EditorHelper.normalizeVisualLine(editor, caret.getVisualPosition().line + linesOffset);
return moveCaretToLineEndSkipLeading(editor, EditorHelper.visualLineToLogicalLine(editor, line));
}
@ -1108,22 +1124,36 @@ public class MotionGroup {
allowPastEnd);
}
public int moveCaretToLineEndOffset(@NotNull Editor editor, int cntForward, boolean allowPastEnd) {
int line = EditorHelper.normalizeVisualLine(editor, editor.getCaretModel().getVisualPosition().line + cntForward);
public int moveCaretToLineEndOffset(@NotNull Editor editor, @NotNull Caret caret, int cntForward, boolean allowPastEnd) {
int line = EditorHelper.normalizeVisualLine(editor, caret.getVisualPosition().line + cntForward);
if (line < 0) {
return 0;
}
else {
return moveCaretToLineEnd(editor, EditorHelper.visualLineToLogicalLine(editor, line), allowPastEnd);
return moveCaretToLineEnd(editor, EditorHelper.visualLineToLogicalLine(editor, line), allowPastEnd);
}
}
public int moveCaretToLineStart(@NotNull Editor editor) {
int logicalLine = editor.getCaretModel().getLogicalPosition().line;
/**
* @deprecated To move the caret, use {@link #moveCaretToLineEndOffset(Editor, Caret, int, boolean)}
*/
public int moveCaretToLineEndOffset(@NotNull Editor editor, int cntForward, boolean allowPastEnd) {
return moveCaretToLineEndOffset(editor, editor.getCaretModel().getPrimaryCaret(), cntForward, allowPastEnd);
}
public int moveCaretToLineStart(@NotNull Editor editor, @NotNull Caret caret) {
int logicalLine = caret.getLogicalPosition().line;
return moveCaretToLineStart(editor, logicalLine);
}
/**
* @deprecated To move the caret, use {@link #moveCaretToLineStart(Editor, Caret)}
*/
public int moveCaretToLineStart(@NotNull Editor editor) {
return moveCaretToLineStart(editor, editor.getCaretModel().getPrimaryCaret());
}
public int moveCaretToLineStart(@NotNull Editor editor, int line) {
if (line >= EditorHelper.getLineCount(editor)) {
return EditorHelper.getFileSize(editor);

View File

@ -24,6 +24,7 @@ import com.intellij.lang.Commenter;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageCommenters;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
@ -1183,18 +1184,19 @@ public class SearchHelper {
* This locates the position with the document of the count-th occurrence of ch on the current line
*
* @param editor The editor to search in
* @param caret The caret to be searched starting from
* @param count The number of occurrences of ch to locate. Negative for backward searches
* @param ch The character on the line to find
* @return The document offset of the matching character match, -1
*/
public static int findNextCharacterOnLine(@NotNull Editor editor, int count, char ch) {
int line = editor.getCaretModel().getLogicalPosition().line;
public static int findNextCharacterOnLine(@NotNull Editor editor, @NotNull Caret caret, int count, char ch) {
int line = caret.getLogicalPosition().line;
int start = EditorHelper.getLineStartOffset(editor, line);
int end = EditorHelper.getLineEndOffset(editor, line, true);
CharSequence chars = editor.getDocument().getCharsSequence();
int found = 0;
int step = count >= 0 ? 1 : -1;
int pos = editor.getCaretModel().getOffset() + step;
int pos = caret.getOffset() + step;
while (pos >= start && pos < end && pos >= 0 && pos < chars.length()) {
if (chars.charAt(pos) == ch) {
found++;

View File

@ -1,53 +0,0 @@
package org.jetbrains.plugins.ideavim.action;
import com.intellij.openapi.editor.Editor;
import org.jetbrains.plugins.ideavim.VimTestCase;
import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
public class MultiCaretTest extends VimTestCase {
public void testMultipleCaretsInsert() {
Editor editor = typeTextInFile(parseKeys("ix"),
"a<caret>b<caret>c<caret>d");
myFixture.checkResult("ax<caret>bx<caret>cx<caret>d");
}
public void testMultipleCaretsLeftMove() {
Editor editor = typeTextInFile(parseKeys("3h"),
"abc<caret>de<caret>");
myFixture.checkResult("<caret>ab<caret>cde");
}
public void testMultipleCaretsRightMove() {
Editor editor = typeTextInFile(parseKeys("l"),
"ab<caret>cd<caret>ef");
myFixture.checkResult("abc<caret>de<caret>f");
}
public void testMutlipleCaretsUpMove() {
Editor editor = typeTextInFile(parseKeys("2k"),
"one two\n" +
"three four\n" +
"fi<caret>ve<caret> six<caret> seven\n");
myFixture.checkResult("on<caret>e <caret>two<caret>\n" +
"three four\n" +
"five six seven\n");
}
public void testMultipleCaretsDownMove() {
Editor editor = typeTextInFile(parseKeys("2j"),
"on<caret>e <caret>two<caret>\n" +
"three four\n" +
"five six seven\n");
myFixture.checkResult("one two\n" +
"three four\n" +
"fi<caret>ve<caret> si<caret>x seven");
}
public void testMultipleCaretsMovementMerging() {
Editor editor = typeTextInFile(parseKeys("2h"),
"o<caret>n<caret>e");
assertEquals(1, editor.getCaretModel().getCaretCount());
myFixture.checkResult("<caret>one");
}
}

View File

@ -0,0 +1,142 @@
package org.jetbrains.plugins.ideavim.action;
import com.intellij.openapi.editor.Editor;
import org.jetbrains.plugins.ideavim.VimTestCase;
import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
/**
* @author Vasily Alferov
*/
public class MultipleCaretsTest extends VimTestCase {
// com.maddyhome.idea.vim.action.motion.leftright
public void testMotionLeftAction() {
typeTextInFile(parseKeys("3h"),
"abc<caret>de<caret>");
myFixture.checkResult("<caret>ab<caret>cde");
}
public void testMotionRightAction() {
typeTextInFile(parseKeys("l"),
"ab<caret>cd<caret>ef");
myFixture.checkResult("abc<caret>de<caret>f");
}
public void testMovementMerging() {
Editor editor = typeTextInFile(parseKeys("2h"),
"o<caret>n<caret>e");
assertEquals(1, editor.getCaretModel().getCaretCount());
myFixture.checkResult("<caret>one");
}
public void testMotionColumnAction() {
typeTextInFile(parseKeys("4|"),
"one<caret> two\n" +
"three four fiv<caret>e\n" +
"si<caret>x seven<caret>\n" +
"<caret>eig<caret>ht nine ten<caret>");
myFixture.checkResult("one<caret> two\n" +
"thr<caret>ee four five\n" +
"six<caret> seven\n" +
"eig<caret>ht nine ten");
}
public void testMotionFirstColumnAction() {
typeTextInFile(parseKeys("0"),
"one<caret> two\n" +
"three four fiv<caret>e\n" +
"si<caret>x seven<caret>\n" +
"<caret>eig<caret>ht nine te<caret>n");
myFixture.checkResult("<caret>one two\n" +
"<caret>three four five\n" +
"<caret>six seven\n" +
"<caret>eight nine ten");
}
public void testMotionFirstNonSpaceAction() {
typeTextInFile(parseKeys("^"),
" one<caret> two\n" +
"three<caret> four\n" +
" five<caret> six\n" +
" <caret> seven eight");
myFixture.checkResult(" <caret>one two\n" +
"<caret>three four\n" +
" <caret>five six\n" +
" <caret>seven eight");
}
public void testMotionLastNonSpaceAction() {
typeTextInFile(parseKeys("g_"),
"one<caret> two \n" +
"three<caret> four \n" +
" five si<caret>x\n" +
"seven eight <caret> \n");
myFixture.checkResult("one tw<caret>o \n" +
"three fou<caret>r \n" +
" five si<caret>x\n" +
"seven eigh<caret>t \n");
}
public void testMotionLastColumnAction() {
typeTextInFile(parseKeys("$"),
"one <caret>two\n" +
"three fou<caret>r");
myFixture.checkResult("one tw<caret>o\n" +
"three fou<caret>r");
}
public void testMotionLeftMatchCharAction() {
typeTextInFile(parseKeys("2Fa"),
"a<caret>a<caret>abab<caret>ab<caret>ab<caret>b<caret>x");
myFixture.checkResult("<caret>a<caret>a<caret>ab<caret>ab<caret>ababbx");
}
public void testMotionRightMatchCharAction() {
typeTextInFile(parseKeys("2fb"),
"a<caret>a<caret>abab<caret>ab<caret>ab<caret>b<caret>x");
myFixture.checkResult("aaaba<caret>baba<caret>b<caret>b<caret>x");
}
public void testMotionLeftTillMatchCharAction() {
typeTextInFile(parseKeys("2Ta"),
"b<caret>a<caret>ba<caret>a<caret>a<caret>ba<caret>b");
myFixture.checkResult("b<caret>a<caret>ba<caret>a<caret>a<caret>bab");
}
public void testMotionRightTillMatchCharAction() {
typeTextInFile(parseKeys("2ta"),
"<caret>b<caret>a<caret>b<caret>a<caret>a<caret>a<caret>ba<caret>b");
myFixture.checkResult("ba<caret>b<caret>a<caret>a<caret>a<caret>ba<caret>b");
}
public void testMotionLastLeftMatchChar() {
typeTextInFile(parseKeys("Fa;"),
"a<caret>a<caret>abab<caret>ab<caret>ab<caret>b<caret>x");
myFixture.checkResult("<caret>aa<caret>ab<caret>ab<caret>ababbx");
}
public void testMotionLastRightMatchChar() {
typeTextInFile(parseKeys("fb;"),
"<caret>a<caret>aabab<caret>ab<caret>ab<caret>b<caret>x");
myFixture.checkResult("aaaba<caret>baba<caret>b<caret>b<caret>x");
}
public void testMotionLastLeftTillMatchChar() {
typeTextInFile(parseKeys("Ta,"),
"b<caret>aba<caret>a<caret>a<caret>ba<caret>b");
myFixture.checkResult("ba<caret>baa<caret>a<caret>ba<caret>b");
}
public void testMotionLastRightTillMatchChar() {
typeTextInFile(parseKeys("ta;"),
"<caret>b<caret>a<caret>b<caret>a<caret>a<caret>a<caret>ba<caret>b");
myFixture.checkResult("ba<caret>b<caret>a<caret>aa<caret>ba<caret>b");
}
public void testMotionLastMatchCharReverse() {
typeTextInFile(parseKeys("fa", "2;", "3,"),
"abaab<caret>a<caret>baaa<caret>abaaba");
myFixture.checkResult("abaab<caret>abaaa<caret>abaaba");
}
}