1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-07-29 16:59:01 +02:00

Extract visual motions to separate file

This commit is contained in:
Alex Plate 2019-02-26 13:23:00 +03:00
parent 2d4eed726f
commit febcccc670
No known key found for this signature in database
GPG Key ID: 0B97153C8FFEC09F
19 changed files with 489 additions and 453 deletions

View File

@ -25,6 +25,7 @@ import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -42,7 +43,7 @@ public class FilterVisualLinesAction extends VimCommandAction {
@Override
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
VimPlugin.getProcess().startFilterCommand(editor, context, cmd);
VimPlugin.getMotion().resetVisual(editor, true);
VisualMotionGroup.INSTANCE.resetVisual(editor, true);
return true;
}
});

View File

@ -22,10 +22,10 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@ -39,7 +39,7 @@ public class VisualExitModeAction extends VimCommandAction {
public VisualExitModeAction() {
super(new EditorActionHandler() {
public void execute(@NotNull Editor editor, @NotNull DataContext context) {
VimPlugin.getMotion().processEscape(InjectedLanguageUtil.getTopLevelEditor(editor));
VisualMotionGroup.INSTANCE.processEscape(InjectedLanguageUtil.getTopLevelEditor(editor));
}
});
}

View File

@ -20,10 +20,10 @@ package com.maddyhome.idea.vim.action.motion.visual;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -38,7 +38,7 @@ public class VisualSelectPreviousAction extends VimCommandAction {
public VisualSelectPreviousAction() {
super(new EditorActionHandlerBase() {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
return VimPlugin.getMotion().selectPreviousVisualMode(editor);
return VisualMotionGroup.INSTANCE.selectPreviousVisualMode(editor);
}
});
}

View File

@ -21,11 +21,11 @@ package com.maddyhome.idea.vim.action.motion.visual;
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.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -41,11 +41,11 @@ public class VisualSwapEndsAction extends VimCommandAction {
super(new EditorActionHandlerBase() {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
if (CommandState.inVisualBlockMode(editor)) {
return VimPlugin.getMotion().swapVisualBlockEnds(editor);
return VisualMotionGroup.INSTANCE.swapVisualBlockEnds(editor);
}
boolean ret = true;
for (Caret caret : editor.getCaretModel().getAllCarets()) {
ret = ret && VimPlugin.getMotion().swapVisualEnds(editor, caret);
ret = ret && VisualMotionGroup.INSTANCE.swapVisualEnds(editor, caret);
}
return ret;
}

View File

@ -21,11 +21,11 @@ package com.maddyhome.idea.vim.action.motion.visual;
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.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -41,12 +41,12 @@ public class VisualSwapEndsBlockAction extends VimCommandAction {
super(new EditorActionHandlerBase() {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
if (CommandState.inVisualBlockMode(editor)) {
return VimPlugin.getMotion().swapVisualBlockEnds(editor);
return VisualMotionGroup.INSTANCE.swapVisualBlockEnds(editor);
}
else {
boolean ret = true;
for (Caret caret : editor.getCaretModel().getAllCarets()) {
ret = ret && VimPlugin.getMotion().swapVisualEnds(editor, caret);
ret = ret && VisualMotionGroup.INSTANCE.swapVisualEnds(editor, caret);
}
return ret;
}

View File

@ -20,10 +20,10 @@ package com.maddyhome.idea.vim.action.motion.visual;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -38,7 +38,7 @@ public class VisualSwapSelectionsAction extends VimCommandAction {
public VisualSwapSelectionsAction() {
super(new EditorActionHandlerBase() {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
return VimPlugin.getMotion().swapVisualSelections(editor);
return VisualMotionGroup.INSTANCE.swapVisualSelections(editor);
}
});
}

View File

@ -21,9 +21,9 @@ package com.maddyhome.idea.vim.action.motion.visual;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -37,7 +37,7 @@ public class VisualToggleBlockModeAction extends EditorAction {
private static class Handler extends EditorActionHandlerBase {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
return VimPlugin.getMotion()
return VisualMotionGroup.INSTANCE
.toggleVisual(editor, cmd.getCount(), cmd.getRawCount(), CommandState.SubMode.VISUAL_BLOCK);
}
}

View File

@ -20,12 +20,12 @@ package com.maddyhome.idea.vim.action.motion.visual;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -38,8 +38,8 @@ public class VisualToggleCharacterModeAction extends VimCommandAction {
public VisualToggleCharacterModeAction() {
super(new EditorActionHandlerBase() {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
return VimPlugin.getMotion().toggleVisual(editor, cmd.getCount(), cmd.getRawCount(),
CommandState.SubMode.VISUAL_CHARACTER);
return VisualMotionGroup.INSTANCE.toggleVisual(editor, cmd.getCount(), cmd.getRawCount(),
CommandState.SubMode.VISUAL_CHARACTER);
}
});
}

View File

@ -21,9 +21,9 @@ package com.maddyhome.idea.vim.action.motion.visual;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import org.jetbrains.annotations.NotNull;
@ -37,7 +37,7 @@ public class VisualToggleLineModeAction extends EditorAction {
private static class Handler extends EditorActionHandlerBase {
protected boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull Command cmd) {
return VimPlugin.getMotion()
return VisualMotionGroup.INSTANCE
.toggleVisual(editor, cmd.getCount(), cmd.getRawCount(), CommandState.SubMode.VISUAL_LINE);
}
}

View File

@ -31,6 +31,8 @@ import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup.selectPreviousVisualMode
import com.maddyhome.idea.vim.helper.runAfterGotFocus
/**
@ -59,7 +61,7 @@ class ActionHandler : CommandHandler(
context: DataContext, actionName: String) {
val visualAction = cmd.ranges.size() > 0
if (visualAction) {
VimPlugin.getMotion().selectPreviousVisualMode(editor)
VisualMotionGroup.selectPreviousVisualMode(editor)
}
try {
KeyHandler.executeAction(action, context)

View File

@ -33,6 +33,8 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
import com.maddyhome.idea.vim.extension.VimExtensionHandler
import com.maddyhome.idea.vim.extension.VimNonDisposableExtension
import com.maddyhome.idea.vim.group.MotionGroup
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup.updateSelection
import com.maddyhome.idea.vim.helper.CaretData
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.SearchHelper.findWordUnderCursor
@ -113,7 +115,7 @@ class VimMultipleCursorsExtension : VimNonDisposableExtension() {
}
}
if (newPositions.size > 0) {
VimPlugin.getMotion().exitVisual(editor)
VisualMotionGroup.exitVisual(editor)
newPositions.forEach { editor.caretModel.addCaret(it) ?: return }
return
}
@ -209,20 +211,20 @@ class VimMultipleCursorsExtension : VimNonDisposableExtension() {
if (tryFindNextOccurrence(editor, caret, selectedText) == -1) return
if (!editor.caretModel.removeCaret(caret)) {
VimPlugin.getMotion().exitVisual(editor)
VisualMotionGroup.exitVisual(editor)
}
}
}
private fun selectWord(editor: Editor, caret: Caret, pattern: String, offset: Int) {
CaretData.setVisualStart(caret, offset)
VimPlugin.getMotion().updateSelection(editor, caret, offset + pattern.length - 1)
VisualMotionGroup.updateSelection(editor, caret, offset + pattern.length - 1)
MotionGroup.moveCaret(editor, caret, offset + pattern.length - 1)
}
private fun findNextOccurrence(editor: Editor, caret: Caret, range: TextRange, whole: Boolean): Int {
caret.selectWordAtCaret(false)
VimPlugin.getMotion().setVisualMode(editor, CommandState.getInstance(editor).subMode)
VisualMotionGroup.setVisualMode(editor, CommandState.getInstance(editor).subMode)
val offset = VimPlugin.getSearch().searchWord(editor, caret, 1, whole, 1)
MotionGroup.moveCaret(editor, caret, range.endOffset - 1, true)

View File

@ -40,6 +40,7 @@ import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.EditorData;
import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.helper.SearchHelper;
@ -303,7 +304,7 @@ public class FileGroup {
else {
msg.append("Selected ");
TextRange vr = VimPlugin.getMotion().getVisualRange(editor);
TextRange vr = VisualMotionGroup.INSTANCE.getVisualRange(editor);
vr.normalize();
int lines;

View File

@ -19,8 +19,22 @@ package com.maddyhome.idea.vim.group;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollingModel;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.event.EditorFactoryEvent;
import com.intellij.openapi.editor.event.EditorFactoryListener;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.event.EditorMouseListener;
import com.intellij.openapi.editor.event.EditorMouseMotionListener;
import com.intellij.openapi.editor.event.SelectionEvent;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.FileEditor;
@ -38,17 +52,21 @@ import com.maddyhome.idea.vim.KeyHandler;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.motion.MotionEditorAction;
import com.maddyhome.idea.vim.action.motion.TextObjectAction;
import com.maddyhome.idea.vim.command.*;
import com.maddyhome.idea.vim.command.Argument;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.VisualChange;
import com.maddyhome.idea.vim.common.Jump;
import com.maddyhome.idea.vim.common.Mark;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.handler.ExecuteMethodNotOverriddenException;
import com.maddyhome.idea.vim.helper.CaretData;
import com.maddyhome.idea.vim.helper.EditorData;
import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.helper.SearchHelper;
import com.maddyhome.idea.vim.option.BoundStringOption;
import com.maddyhome.idea.vim.option.NumberOption;
import com.maddyhome.idea.vim.option.Options;
import com.maddyhome.idea.vim.ui.ExEntryPanel;
@ -169,7 +187,7 @@ public class MotionGroup {
break;
}
setVisualMode(editor, visualMode);
VisualMotionGroup.INSTANCE.setVisualMode(editor, visualMode);
final CaretModel caretModel = editor.getCaretModel();
if (CommandState.getInstance(editor).getSubMode() != CommandState.SubMode.NONE) {
@ -218,7 +236,7 @@ public class MotionGroup {
if (update) {
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
for (@NotNull Caret caret : editor.getCaretModel().getAllCarets()) {
updateSelection(editor, caret, caret.getOffset());
VisualMotionGroup.INSTANCE.updateSelection(editor, caret, caret.getOffset());
}
}
}
@ -231,10 +249,10 @@ public class MotionGroup {
int end = editor.getSelectionModel().getSelectionEnd();
editor.getSelectionModel().setSelection(start, Math.max(start, end - 1));
setVisualMode(editor, CommandState.SubMode.VISUAL_LINE);
VisualMotionGroup.INSTANCE.setVisualMode(editor, CommandState.SubMode.VISUAL_LINE);
final Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
VisualChange range = getVisualOperatorRange(editor, primaryCaret, EnumSet.of(CommandFlags.FLAG_MOT_LINEWISE));
VisualChange range = VisualMotionGroup.INSTANCE.getVisualOperatorRange(editor, primaryCaret, EnumSet.of(CommandFlags.FLAG_MOT_LINEWISE));
if (range.getLines() > 1) {
MotionGroup.moveCaret(editor, primaryCaret,
moveCaretVertical(editor, primaryCaret, -1));
@ -274,7 +292,7 @@ public class MotionGroup {
}
MotionGroup.moveCaret(editor, editor.getCaretModel().getPrimaryCaret(), start);
toggleVisual(editor, 1, 0, mode);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 0, mode);
MotionGroup.moveCaret(editor, editor.getCaretModel().getPrimaryCaret(), end);
KeyHandler.getInstance().reset(editor);
}
@ -1335,7 +1353,7 @@ public class MotionGroup {
}
if (keepVisual) {
VimPlugin.getMotion().updateSelection(editor, caret, offset);
VisualMotionGroup.INSTANCE.updateSelection(editor, caret, offset);
}
else {
editor.getSelectionModel().removeSelection();
@ -1494,395 +1512,6 @@ public class MotionGroup {
}
}
public boolean selectPreviousVisualMode(@NotNull Editor editor) {
final SelectionType lastSelectionType = EditorData.getLastSelectionType(editor);
if (lastSelectionType == null) {
return false;
}
final TextRange visualMarks = VimPlugin.getMark().getVisualSelectionMarks(editor);
if (visualMarks == null) {
return false;
}
editor.getCaretModel().removeSecondaryCarets();
CommandState.getInstance(editor)
.pushState(CommandState.Mode.VISUAL, lastSelectionType.toSubMode(), MappingMode.VISUAL);
Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
CaretData.setVisualStart(primaryCaret, visualMarks.getStartOffset());
CaretData.setVisualEnd(primaryCaret, visualMarks.getEndOffset());
CaretData.setVisualOffset(primaryCaret, visualMarks.getEndOffset());
updateSelection(editor, primaryCaret, visualMarks.getEndOffset());
primaryCaret.moveToOffset(visualMarks.getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
return true;
}
public boolean swapVisualSelections(@NotNull Editor editor) {
final SelectionType lastSelectionType = EditorData.getLastSelectionType(editor);
final TextRange lastVisualRange = EditorData.getLastVisualRange(editor);
if (lastSelectionType == null || lastVisualRange == null) {
return false;
}
final SelectionType selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).getSubMode());
EditorData.setLastSelectionType(editor, selectionType);
editor.getCaretModel().removeSecondaryCarets();
Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
CaretData.setVisualStart(primaryCaret, lastVisualRange.getStartOffset());
CaretData.setVisualEnd(primaryCaret, lastVisualRange.getEndOffset());
CaretData.setVisualOffset(primaryCaret, lastVisualRange.getEndOffset());
CommandState.getInstance(editor).setSubMode(lastSelectionType.toSubMode());
updateSelection(editor, primaryCaret, lastVisualRange.getEndOffset());
primaryCaret.moveToOffset(lastVisualRange.getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
return true;
}
public void setVisualMode(@NotNull Editor editor, @NotNull CommandState.SubMode mode) {
CommandState.SubMode oldMode = CommandState.getInstance(editor).getSubMode();
if (mode == CommandState.SubMode.NONE) {
int start = editor.getSelectionModel().getSelectionStart();
int end = editor.getSelectionModel().getSelectionEnd();
if (start != end) {
int line = editor.offsetToLogicalPosition(start).line;
int logicalStart = EditorHelper.getLineStartOffset(editor, line);
int lend = EditorHelper.getLineEndOffset(editor, line, true);
if (logicalStart == start && lend + 1 == end) {
mode = CommandState.SubMode.VISUAL_LINE;
}
else {
mode = CommandState.SubMode.VISUAL_CHARACTER;
}
}
}
if (oldMode == CommandState.SubMode.NONE && mode == CommandState.SubMode.NONE) {
editor.getSelectionModel().removeSelection();
return;
}
if (mode == CommandState.SubMode.NONE) {
exitVisual(editor);
}
else {
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, mode, MappingMode.VISUAL);
}
KeyHandler.getInstance().reset(editor);
for (Caret caret : editor.getCaretModel().getAllCarets()) {
CaretData.setVisualStart(caret, caret.getSelectionStart());
int visualEnd = caret.getSelectionEnd();
if (CommandState.getInstance(editor).getSubMode() == CommandState.SubMode.VISUAL_CHARACTER) {
BoundStringOption opt = (BoundStringOption) Options.getInstance().getOption("selection");
int adj = 1;
if (opt.getValue().equals("exclusive")) {
adj = 0;
}
visualEnd -= adj;
}
CaretData.setVisualEnd(caret, visualEnd);
CaretData.setVisualOffset(caret, caret.getOffset());
}
VimPlugin.getMark().setVisualSelectionMarks(editor, getRawVisualRange(editor.getCaretModel().getPrimaryCaret()));
}
public boolean toggleVisual(@NotNull Editor editor, int count, int rawCount, @NotNull CommandState.SubMode mode) {
CommandState.SubMode currentMode = CommandState.getInstance(editor).getSubMode();
if (CommandState.getInstance(editor).getMode() != CommandState.Mode.VISUAL) {
if (rawCount > 0) {
if (editor.getCaretModel().getCaretCount() > 1) {
return false;
}
VisualChange range = CaretData.getLastVisualOperatorRange(editor.getCaretModel().getPrimaryCaret());
if (range == null) {
return false;
}
mode = range.getType().toSubMode();
int start = editor.getCaretModel().getOffset();
int end = calculateVisualRange(editor, range, count);
Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, mode, MappingMode.VISUAL);
CaretData.setVisualStart(primaryCaret, start);
updateSelection(editor, primaryCaret, end);
MotionGroup.moveCaret(editor, primaryCaret, CaretData.getVisualEnd(primaryCaret), true);
}
else {
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, mode, MappingMode.VISUAL);
if (mode == CommandState.SubMode.VISUAL_BLOCK) {
EditorData.setVisualBlockStart(editor, editor.getSelectionModel().getSelectionStart());
updateBlockSelection(editor, editor.getSelectionModel().getSelectionEnd());
MotionGroup
.moveCaret(editor, editor.getCaretModel().getPrimaryCaret(), EditorData.getVisualBlockEnd(editor), true);
}
else {
for (Caret caret : editor.getCaretModel().getAllCarets()) {
CaretData.setVisualStart(caret, caret.getSelectionStart());
updateSelection(editor, caret, caret.getSelectionEnd());
MotionGroup.moveCaret(editor, caret, CaretData.getVisualEnd(caret), true);
}
}
}
}
else if (mode == currentMode) {
exitVisual(editor);
}
else if (mode == CommandState.SubMode.VISUAL_BLOCK) {
CommandState.getInstance(editor).setSubMode(mode);
updateBlockSelection(editor, EditorData.getVisualBlockEnd(editor));
}
else {
CommandState.getInstance(editor).setSubMode(mode);
for (Caret caret : editor.getCaretModel().getAllCarets()) {
updateSelection(editor, caret, CaretData.getVisualEnd(caret));
}
}
return true;
}
private int calculateVisualRange(@NotNull Editor editor, @NotNull VisualChange range, int count) {
int lines = range.getLines();
int chars = range.getColumns();
if (range.getType() == SelectionType.LINE_WISE || range.getType() == SelectionType.BLOCK_WISE || lines > 1) {
lines *= count;
}
if ((range.getType() == SelectionType.CHARACTER_WISE && lines == 1) ||
range.getType() == SelectionType.BLOCK_WISE) {
chars *= count;
}
int start = editor.getCaretModel().getOffset();
LogicalPosition sp = editor.offsetToLogicalPosition(start);
int endLine = sp.line + lines - 1;
int res;
if (range.getType() == SelectionType.LINE_WISE) {
res = moveCaretToLine(editor, endLine);
}
else if (range.getType() == SelectionType.CHARACTER_WISE) {
if (lines > 1) {
res = moveCaretToLineStart(editor, endLine) + Math.min(EditorHelper.getLineLength(editor, endLine), chars);
}
else {
res = EditorHelper.normalizeOffset(editor, sp.line, start + chars - 1, false);
}
}
else {
int endColumn = Math.min(EditorHelper.getLineLength(editor, endLine), sp.column + chars - 1);
res = editor.logicalPositionToOffset(new LogicalPosition(endLine, endColumn));
}
return res;
}
public void exitVisual(@NotNull final Editor editor) {
resetVisual(editor, true);
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
CommandState.getInstance(editor).popState();
}
}
public void resetVisual(@NotNull final Editor editor, final boolean removeSelection) {
final boolean wasVisualBlock = CommandState.inVisualBlockMode(editor);
final SelectionType selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).getSubMode());
EditorData.setLastSelectionType(editor, selectionType);
final TextRange visualMarks = VimPlugin.getMark().getVisualSelectionMarks(editor);
if (visualMarks != null) {
EditorData.setLastVisualRange(editor, visualMarks);
}
if (removeSelection) {
if (!EditorData.isKeepingVisualOperatorAction(editor)) {
for (Caret caret : editor.getCaretModel().getAllCarets()) {
caret.removeSelection();
}
}
if (wasVisualBlock) {
editor.getCaretModel().removeSecondaryCarets();
}
}
CommandState.getInstance(editor).setSubMode(CommandState.SubMode.NONE);
}
@NotNull
public VisualChange getVisualOperatorRange(@NotNull Editor editor, @NotNull Caret caret, EnumSet<CommandFlags> cmdFlags) {
int start = CaretData.getVisualStart(caret);
int end = CaretData.getVisualEnd(caret);
if (CommandState.inVisualBlockMode(editor)) {
start = EditorData.getVisualBlockStart(editor);
end = EditorData.getVisualBlockEnd(editor);
}
if (start > end) {
int t = start;
start = end;
end = t;
}
start = EditorHelper.normalizeOffset(editor, start, false);
end = EditorHelper.normalizeOffset(editor, end, false);
LogicalPosition sp = editor.offsetToLogicalPosition(start);
LogicalPosition ep = editor.offsetToLogicalPosition(end);
int lines = ep.line - sp.line + 1;
int chars;
SelectionType type;
if (CommandState.getInstance(editor).getSubMode() == CommandState.SubMode.VISUAL_LINE ||
cmdFlags.contains(CommandFlags.FLAG_MOT_LINEWISE)) {
chars = ep.column;
type = SelectionType.LINE_WISE;
}
else if (CommandState.getInstance(editor).getSubMode() == CommandState.SubMode.VISUAL_CHARACTER) {
type = SelectionType.CHARACTER_WISE;
if (lines > 1) {
chars = ep.column;
}
else {
chars = ep.column - sp.column + 1;
}
}
else {
chars = ep.column - sp.column + 1;
if (CaretData.getLastColumn(editor.getCaretModel().getPrimaryCaret()) == MotionGroup.LAST_COLUMN) {
chars = MotionGroup.LAST_COLUMN;
}
type = SelectionType.BLOCK_WISE;
}
return new VisualChange(lines, chars, type);
}
@NotNull
public TextRange getVisualRange(@NotNull Editor editor) {
return new TextRange(editor.getSelectionModel().getBlockSelectionStarts(),
editor.getSelectionModel().getBlockSelectionEnds());
}
@NotNull
public TextRange getVisualRange(@NotNull Caret caret) {
return new TextRange(caret.getSelectionStart(), caret.getSelectionEnd());
}
@NotNull
public TextRange getRawVisualRange(@NotNull Caret caret) {
return new TextRange(CaretData.getVisualStart(caret), CaretData.getVisualEnd(caret));
}
public void updateBlockSelection(@NotNull Editor editor) {
updateBlockSelection(editor, EditorData.getVisualBlockEnd(editor));
}
private void updateBlockSelection(@NotNull Editor editor, int offset) {
EditorData.setVisualBlockEnd(editor, offset);
EditorData.setVisualBlockOffset(editor, offset);
int start = EditorData.getVisualBlockStart(editor);
int end = EditorData.getVisualBlockEnd(editor);
LogicalPosition blockStart = editor.offsetToLogicalPosition(start);
LogicalPosition blockEnd = editor.offsetToLogicalPosition(end);
if (blockStart.column < blockEnd.column) {
blockEnd = new LogicalPosition(blockEnd.line, blockEnd.column + 1);
}
else {
blockStart = new LogicalPosition(blockStart.line, blockStart.column + 1);
}
editor.getSelectionModel().setBlockSelection(blockStart, blockEnd);
for (Caret caret : editor.getCaretModel().getAllCarets()) {
int line = caret.getLogicalPosition().line;
int lineEndOffset = EditorHelper.getLineEndOffset(editor, line, true);
if (CaretData.getLastColumn(editor.getCaretModel().getPrimaryCaret()) >= MotionGroup.LAST_COLUMN) {
caret.setSelection(caret.getSelectionStart(), lineEndOffset);
}
if (!EditorHelper.isLineEmpty(editor, line, false)) {
caret.moveToOffset(caret.getSelectionEnd() - 1);
}
}
editor.getCaretModel().getPrimaryCaret().moveToOffset(end);
VimPlugin.getMark().setVisualSelectionMarks(editor, new TextRange(start, end));
}
public void updateSelection(@NotNull Editor editor, @NotNull Caret caret, int offset) {
if (CommandState.getInstance(editor).getSubMode() == CommandState.SubMode.VISUAL_BLOCK) {
updateBlockSelection(editor, offset);
}
else {
CaretData.setVisualEnd(caret, offset);
CaretData.setVisualOffset(caret, offset);
int start = CaretData.getVisualStart(caret);
int end = offset;
final CommandState.SubMode subMode = CommandState.getInstance(editor).getSubMode();
if (subMode == CommandState.SubMode.VISUAL_CHARACTER) {
if (start > end) {
int t = start;
start = end;
end = t;
}
final BoundStringOption opt = (BoundStringOption) Options.getInstance().getOption("selection");
int lineEnd = EditorHelper.getLineEndForOffset(editor, end);
final int adj = opt.getValue().equals("exclusive") || end == lineEnd ? 0 : 1;
final int adjEnd = Math.min(EditorHelper.getFileSize(editor), end + adj);
caret.setSelection(start, adjEnd);
}
else if (subMode == CommandState.SubMode.VISUAL_LINE) {
if (start > end) {
int t = start;
start = end;
end = t;
}
start = EditorHelper.getLineStartForOffset(editor, start);
end = EditorHelper.getLineEndForOffset(editor, end);
caret.setSelection(start, end);
}
VimPlugin.getMark().setVisualSelectionMarks(editor, new TextRange(start, end));
}
}
public boolean swapVisualBlockEnds(@NotNull Editor editor) {
if (!CommandState.inVisualBlockMode(editor)) return false;
int t = EditorData.getVisualBlockEnd(editor);
EditorData.setVisualBlockEnd(editor, EditorData.getVisualBlockStart(editor));
EditorData.setVisualBlockStart(editor, t);
moveCaret(editor, editor.getCaretModel().getPrimaryCaret(), EditorData.getVisualBlockEnd(editor));
return true;
}
public boolean swapVisualEnds(@NotNull Editor editor, @NotNull Caret caret) {
int t = CaretData.getVisualEnd(caret);
CaretData.setVisualEnd(caret, CaretData.getVisualStart(caret));
CaretData.setVisualStart(caret, t);
moveCaret(editor, caret, CaretData.getVisualEnd(caret));
return true;
}
public void moveVisualStart(@NotNull Caret caret, int startOffset) {
CaretData.setVisualStart(caret, startOffset);
}
public void processEscape(@NotNull Editor editor) {
exitVisual(editor);
}
public static class MotionEditorChange implements FileEditorManagerListener {
public void selectionChanged(@NotNull FileEditorManagerEvent event) {
if (ExEntryPanel.getInstance().isActive()) {
@ -1893,7 +1522,7 @@ public class MotionGroup {
final Editor editor = ((TextEditor) fileEditor).getEditor();
ExOutputModel.getInstance(editor).clear();
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
VimPlugin.getMotion().exitVisual(editor);
VisualMotionGroup.INSTANCE.exitVisual(editor);
}
}
}

View File

@ -25,19 +25,27 @@ import com.intellij.util.text.CharSequenceReader;
import com.maddyhome.idea.vim.KeyHandler;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.ex.CommandParser;
import com.maddyhome.idea.vim.ex.ExException;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.UiHelper;
import com.maddyhome.idea.vim.ui.ExEntryPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.EnumSet;
/**
@ -117,7 +125,7 @@ public class ProcessGroup {
flags = CommandParser.getInstance().processCommand(editor, context, text, 1);
if (logger.isDebugEnabled()) logger.debug("flags=" + flags);
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
VimPlugin.getMotion().exitVisual(editor);
VisualMotionGroup.INSTANCE.exitVisual(editor);
}
}
else {

View File

@ -36,13 +36,20 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Ref;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.SelectionType;
import com.maddyhome.idea.vim.common.CharacterPosition;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.ex.LineRange;
import com.maddyhome.idea.vim.helper.*;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.EditorData;
import com.maddyhome.idea.vim.helper.EditorDataContext;
import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.helper.MessageHelper;
import com.maddyhome.idea.vim.helper.Msg;
import com.maddyhome.idea.vim.helper.SearchHelper;
import com.maddyhome.idea.vim.helper.StringHelper;
import com.maddyhome.idea.vim.option.ListOption;
import com.maddyhome.idea.vim.option.Options;
import com.maddyhome.idea.vim.regexp.CharHelper;
@ -57,7 +64,12 @@ import org.jetbrains.annotations.Nullable;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
public class SearchGroup {
@Nullable
@ -82,7 +94,7 @@ public class SearchGroup {
@NotNull String excmd, String exarg) {
// Explicitly exit visual mode here, so that visual mode marks don't change when we move the cursor to a match.
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
VimPlugin.getMotion().exitVisual(editor);
VisualMotionGroup.INSTANCE.exitVisual(editor);
}
CharPointer cmd = new CharPointer(new StringBuffer(exarg));

View File

@ -0,0 +1,380 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2019 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.group.motion
import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.editor.ScrollType
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.command.SelectionType
import com.maddyhome.idea.vim.command.VisualChange
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.group.MotionGroup
import com.maddyhome.idea.vim.helper.CaretData
import com.maddyhome.idea.vim.helper.EditorData
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.option.BoundStringOption
import com.maddyhome.idea.vim.option.Options
import java.util.*
/**
* @author Alex Plate
*/
object VisualMotionGroup {
fun selectPreviousVisualMode(editor: Editor): Boolean {
val lastSelectionType = EditorData.getLastSelectionType(editor) ?: return false
val visualMarks = VimPlugin.getMark().getVisualSelectionMarks(editor) ?: return false
editor.caretModel.removeSecondaryCarets()
CommandState.getInstance(editor)
.pushState(CommandState.Mode.VISUAL, lastSelectionType.toSubMode(), MappingMode.VISUAL)
val primaryCaret = editor.caretModel.primaryCaret
CaretData.setVisualStart(primaryCaret, visualMarks.startOffset)
CaretData.setVisualEnd(primaryCaret, visualMarks.endOffset)
CaretData.setVisualOffset(primaryCaret, visualMarks.endOffset)
updateSelection(editor, primaryCaret, visualMarks.endOffset)
primaryCaret.moveToOffset(visualMarks.endOffset)
editor.scrollingModel.scrollToCaret(ScrollType.CENTER)
return true
}
fun swapVisualSelections(editor: Editor): Boolean {
val lastSelectionType = EditorData.getLastSelectionType(editor) ?: return false
val lastVisualRange = EditorData.getLastVisualRange(editor) ?: return false
val selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).subMode)
EditorData.setLastSelectionType(editor, selectionType)
editor.caretModel.removeSecondaryCarets()
val primaryCaret = editor.caretModel.primaryCaret
CaretData.setVisualStart(primaryCaret, lastVisualRange.startOffset)
CaretData.setVisualEnd(primaryCaret, lastVisualRange.endOffset)
CaretData.setVisualOffset(primaryCaret, lastVisualRange.endOffset)
CommandState.getInstance(editor).subMode = lastSelectionType.toSubMode()
updateSelection(editor, primaryCaret, lastVisualRange.endOffset)
primaryCaret.moveToOffset(lastVisualRange.endOffset)
editor.scrollingModel.scrollToCaret(ScrollType.CENTER)
return true
}
fun setVisualMode(editor: Editor, mode: CommandState.SubMode) {
var modeWithSelection = mode
val oldMode = CommandState.getInstance(editor).subMode
if (modeWithSelection == CommandState.SubMode.NONE) {
val start = editor.selectionModel.selectionStart
val end = editor.selectionModel.selectionEnd
if (start != end) {
val line = editor.offsetToLogicalPosition(start).line
val logicalStart = EditorHelper.getLineStartOffset(editor, line)
val lend = EditorHelper.getLineEndOffset(editor, line, true)
modeWithSelection = if (logicalStart == start && lend + 1 == end) {
CommandState.SubMode.VISUAL_LINE
} else {
CommandState.SubMode.VISUAL_CHARACTER
}
}
}
if (oldMode == CommandState.SubMode.NONE && modeWithSelection == CommandState.SubMode.NONE) {
editor.selectionModel.removeSelection()
return
}
if (modeWithSelection == CommandState.SubMode.NONE) {
VisualMotionGroup.exitVisual(editor)
} else {
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, modeWithSelection, MappingMode.VISUAL)
}
KeyHandler.getInstance().reset(editor)
for (caret in editor.caretModel.allCarets) {
CaretData.setVisualStart(caret, caret.selectionStart)
var visualEnd = caret.selectionEnd
if (CommandState.getInstance(editor).subMode == CommandState.SubMode.VISUAL_CHARACTER) {
val opt = Options.getInstance().getOption("selection") as BoundStringOption
var adj = 1
if (opt.value == "exclusive") {
adj = 0
}
visualEnd -= adj
}
CaretData.setVisualEnd(caret, visualEnd)
CaretData.setVisualOffset(caret, caret.offset)
}
VimPlugin.getMark().setVisualSelectionMarks(editor, getRawVisualRange(editor.caretModel.primaryCaret))
}
fun toggleVisual(editor: Editor, count: Int, rawCount: Int, mode: CommandState.SubMode): Boolean {
var modeWithSelection = mode
val currentMode = CommandState.getInstance(editor).subMode
if (CommandState.getInstance(editor).mode != CommandState.Mode.VISUAL) {
if (rawCount > 0) {
if (editor.caretModel.caretCount > 1) {
return false
}
val range = CaretData.getLastVisualOperatorRange(editor.caretModel.primaryCaret) ?: return false
modeWithSelection = range.type.toSubMode()
val start = editor.caretModel.offset
val end = calculateVisualRange(editor, range, count)
val primaryCaret = editor.caretModel.primaryCaret
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, modeWithSelection, MappingMode.VISUAL)
CaretData.setVisualStart(primaryCaret, start)
updateSelection(editor, primaryCaret, end)
MotionGroup.moveCaret(editor, primaryCaret, CaretData.getVisualEnd(primaryCaret), true)
} else {
CommandState.getInstance(editor).pushState(CommandState.Mode.VISUAL, modeWithSelection, MappingMode.VISUAL)
if (modeWithSelection == CommandState.SubMode.VISUAL_BLOCK) {
EditorData.setVisualBlockStart(editor, editor.selectionModel.selectionStart)
updateBlockSelection(editor, editor.selectionModel.selectionEnd)
MotionGroup
.moveCaret(editor, editor.caretModel.primaryCaret, EditorData.getVisualBlockEnd(editor), true)
} else {
for (caret in editor.caretModel.allCarets) {
CaretData.setVisualStart(caret, caret.selectionStart)
updateSelection(editor, caret, caret.selectionEnd)
MotionGroup.moveCaret(editor, caret, CaretData.getVisualEnd(caret), true)
}
}
}
} else if (modeWithSelection == currentMode) {
VisualMotionGroup.exitVisual(editor)
} else if (modeWithSelection == CommandState.SubMode.VISUAL_BLOCK) {
CommandState.getInstance(editor).subMode = modeWithSelection
updateBlockSelection(editor, EditorData.getVisualBlockEnd(editor))
} else {
CommandState.getInstance(editor).subMode = modeWithSelection
for (caret in editor.caretModel.allCarets) {
updateSelection(editor, caret, CaretData.getVisualEnd(caret))
}
}
return true
}
private fun calculateVisualRange(editor: Editor, range: VisualChange, count: Int): Int {
var lines = range.lines
var chars = range.columns
if (range.type == SelectionType.LINE_WISE || range.type == SelectionType.BLOCK_WISE || lines > 1) {
lines *= count
}
if (range.type == SelectionType.CHARACTER_WISE && lines == 1 || range.type == SelectionType.BLOCK_WISE) {
chars *= count
}
val start = editor.caretModel.offset
val sp = editor.offsetToLogicalPosition(start)
val endLine = sp.line + lines - 1
return if (range.type == SelectionType.LINE_WISE) {
VimPlugin.getMotion().moveCaretToLine(editor, endLine)
} else if (range.type == SelectionType.CHARACTER_WISE) {
if (lines > 1) {
VimPlugin.getMotion().moveCaretToLineStart(editor, endLine) + Math.min(EditorHelper.getLineLength(editor, endLine), chars)
} else {
EditorHelper.normalizeOffset(editor, sp.line, start + chars - 1, false)
}
} else {
val endColumn = Math.min(EditorHelper.getLineLength(editor, endLine), sp.column + chars - 1)
editor.logicalPositionToOffset(LogicalPosition(endLine, endColumn))
}
}
fun getVisualOperatorRange(editor: Editor, caret: Caret, cmdFlags: EnumSet<CommandFlags>): VisualChange {
var start = CaretData.getVisualStart(caret)
var end = CaretData.getVisualEnd(caret)
if (CommandState.inVisualBlockMode(editor)) {
start = EditorData.getVisualBlockStart(editor)
end = EditorData.getVisualBlockEnd(editor)
}
if (start > end) {
val t = start
start = end
end = t
}
start = EditorHelper.normalizeOffset(editor, start, false)
end = EditorHelper.normalizeOffset(editor, end, false)
val sp = editor.offsetToLogicalPosition(start)
val ep = editor.offsetToLogicalPosition(end)
val lines = ep.line - sp.line + 1
val (type, chars) = if (CommandState.getInstance(editor).subMode == CommandState.SubMode.VISUAL_LINE || CommandFlags.FLAG_MOT_LINEWISE in cmdFlags) {
SelectionType.LINE_WISE to ep.column
} else if (CommandState.getInstance(editor).subMode == CommandState.SubMode.VISUAL_CHARACTER) {
SelectionType.CHARACTER_WISE to if (lines > 1) {
ep.column
} else {
ep.column - sp.column + 1
}
} else {
SelectionType.BLOCK_WISE to if (CaretData.getLastColumn(editor.caretModel.primaryCaret) == MotionGroup.LAST_COLUMN) {
MotionGroup.LAST_COLUMN
} else ep.column - sp.column + 1
}
return VisualChange(lines, chars, type)
}
fun getVisualRange(editor: Editor) = editor.selectionModel.run { TextRange(blockSelectionStarts, blockSelectionEnds) }
fun getVisualRange(caret: Caret) = TextRange(caret.selectionStart, caret.selectionEnd)
fun getRawVisualRange(caret: Caret) = TextRange(CaretData.getVisualStart(caret), CaretData.getVisualEnd(caret))
fun updateBlockSelection(editor: Editor) = updateBlockSelection(editor, EditorData.getVisualBlockEnd(editor))
private fun updateBlockSelection(editor: Editor, offset: Int) {
EditorData.setVisualBlockEnd(editor, offset)
EditorData.setVisualBlockOffset(editor, offset)
val start = EditorData.getVisualBlockStart(editor)
val end = EditorData.getVisualBlockEnd(editor)
var blockStart = editor.offsetToLogicalPosition(start)
var blockEnd = editor.offsetToLogicalPosition(end)
if (blockStart.column < blockEnd.column) {
blockEnd = LogicalPosition(blockEnd.line, blockEnd.column + 1)
} else {
blockStart = LogicalPosition(blockStart.line, blockStart.column + 1)
}
editor.selectionModel.setBlockSelection(blockStart, blockEnd)
for (caret in editor.caretModel.allCarets) {
val line = caret.logicalPosition.line
val lineEndOffset = EditorHelper.getLineEndOffset(editor, line, true)
if (CaretData.getLastColumn(editor.caretModel.primaryCaret) >= MotionGroup.LAST_COLUMN) {
caret.setSelection(caret.selectionStart, lineEndOffset)
}
if (!EditorHelper.isLineEmpty(editor, line, false)) {
caret.moveToOffset(caret.selectionEnd - 1)
}
}
editor.caretModel.primaryCaret.moveToOffset(end)
VimPlugin.getMark().setVisualSelectionMarks(editor, TextRange(start, end))
}
fun updateSelection(editor: Editor, caret: Caret, offset: Int) {
if (CommandState.getInstance(editor).subMode == CommandState.SubMode.VISUAL_BLOCK) {
VisualMotionGroup.updateBlockSelection(editor, offset)
} else {
CaretData.setVisualEnd(caret, offset)
CaretData.setVisualOffset(caret, offset)
var start = CaretData.getVisualStart(caret)
var end = offset
val subMode = CommandState.getInstance(editor).subMode
if (subMode == CommandState.SubMode.VISUAL_CHARACTER) {
if (start > end) {
val t = start
start = end
end = t
}
val opt = Options.getInstance().getOption("selection") as BoundStringOption
val lineEnd = EditorHelper.getLineEndForOffset(editor, end)
val adj = if (opt.value == "exclusive" || end == lineEnd) 0 else 1
val adjEnd = minOf(EditorHelper.getFileSize(editor), end + adj)
caret.setSelection(start, adjEnd)
} else if (subMode == CommandState.SubMode.VISUAL_LINE) {
if (start > end) {
val t = start
start = end
end = t
}
start = EditorHelper.getLineStartForOffset(editor, start)
end = EditorHelper.getLineEndForOffset(editor, end)
caret.setSelection(start, end)
}
VimPlugin.getMark().setVisualSelectionMarks(editor, TextRange(start, end))
}
}
fun swapVisualBlockEnds(editor: Editor): Boolean {
if (!CommandState.inVisualBlockMode(editor)) return false
val t = EditorData.getVisualBlockEnd(editor)
EditorData.setVisualBlockEnd(editor, EditorData.getVisualBlockStart(editor))
EditorData.setVisualBlockStart(editor, t)
MotionGroup.moveCaret(editor, editor.caretModel.primaryCaret, EditorData.getVisualBlockEnd(editor))
return true
}
fun swapVisualEnds(editor: Editor, caret: Caret): Boolean {
val t = CaretData.getVisualEnd(caret)
CaretData.setVisualEnd(caret, CaretData.getVisualStart(caret))
CaretData.setVisualStart(caret, t)
MotionGroup.moveCaret(editor, caret, CaretData.getVisualEnd(caret))
return true
}
fun processEscape(editor: Editor) = VisualMotionGroup.exitVisual(editor)
fun resetVisual(editor: Editor, removeSelection: Boolean) {
val wasVisualBlock = CommandState.inVisualBlockMode(editor)
val selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).subMode)
EditorData.setLastSelectionType(editor, selectionType)
VimPlugin.getMark().getVisualSelectionMarks(editor)?.let {
EditorData.setLastVisualRange(editor, it)
}
if (removeSelection) {
if (!EditorData.isKeepingVisualOperatorAction(editor)) {
for (caret in editor.caretModel.allCarets) {
caret.removeSelection()
}
}
if (wasVisualBlock) {
editor.caretModel.removeSecondaryCarets()
}
}
CommandState.getInstance(editor).subMode = CommandState.SubMode.NONE
}
fun exitVisual(editor: Editor) {
resetVisual(editor, true)
if (CommandState.getInstance(editor).mode == CommandState.Mode.VISUAL) {
CommandState.getInstance(editor).popState()
}
}
fun moveVisualStart(caret: Caret, startOffset: Int) = CaretData.setVisualStart(caret, startOffset)
}

View File

@ -21,13 +21,13 @@ package com.maddyhome.idea.vim.handler;
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.command.Argument;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.group.MotionGroup;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -54,25 +54,25 @@ public abstract class TextObjectActionHandler extends EditorActionHandlerBase {
}
TextRange vr;
vr = VimPlugin.getMotion().getRawVisualRange(caret);
vr = VisualMotionGroup.INSTANCE.getRawVisualRange(caret);
boolean block = cmd.getFlags().contains(CommandFlags.FLAG_TEXT_BLOCK);
int newstart = block || vr.getEndOffset() >= vr.getStartOffset() ? range.getStartOffset() : range.getEndOffset();
int newend = block || vr.getEndOffset() >= vr.getStartOffset() ? range.getEndOffset() : range.getStartOffset();
if (vr.getStartOffset() == vr.getEndOffset() || block) {
VimPlugin.getMotion().moveVisualStart(caret, newstart);
VisualMotionGroup.INSTANCE.moveVisualStart(caret, newstart);
}
if ((cmd.getFlags().contains(CommandFlags.FLAG_MOT_LINEWISE) &&
!cmd.getFlags().contains(CommandFlags.FLAG_VISUAL_CHARACTERWISE)) &&
CommandState.getInstance(editor).getSubMode() != CommandState.SubMode.VISUAL_LINE) {
VimPlugin.getMotion().toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_LINE);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_LINE);
}
else if ((!cmd.getFlags().contains(CommandFlags.FLAG_MOT_LINEWISE) ||
cmd.getFlags().contains(CommandFlags.FLAG_VISUAL_CHARACTERWISE)) &&
CommandState.getInstance(editor).getSubMode() == CommandState.SubMode.VISUAL_LINE) {
VimPlugin.getMotion().toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_CHARACTER);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_CHARACTER);
}
MotionGroup.moveCaret(editor, caret, newend);

View File

@ -24,11 +24,12 @@ import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.VisualChange;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.group.MotionGroup;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.CaretData;
import com.maddyhome.idea.vim.helper.EditorData;
import com.maddyhome.idea.vim.helper.EditorHelper;
@ -67,7 +68,7 @@ public abstract class VisualOperatorActionHandler extends EditorActionHandlerBas
boolean willRunForEachCaret = myRunForEachCaret && !CommandState.inVisualBlockMode(editor);
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
TextRange range = VimPlugin.getMotion().getVisualRange(editor);
TextRange range = VisualMotionGroup.INSTANCE.getVisualRange(editor);
if (logger.isDebugEnabled()) logger.debug("range=" + range);
}
@ -148,7 +149,7 @@ public abstract class VisualOperatorActionHandler extends EditorActionHandlerBas
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.REPEAT) {
CaretData.setPreviousLastColumn(caret, CaretData.getLastColumn(caret));
VisualChange range = CaretData.getLastVisualOperatorRange(caret);
VimPlugin.getMotion().toggleVisual(editor, 1, 1, CommandState.SubMode.NONE);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 1, CommandState.SubMode.NONE);
if (range != null && range.getColumns() == MotionGroup.LAST_COLUMN) {
CaretData.setLastColumn(editor, caret, MotionGroup.LAST_COLUMN);
}
@ -158,13 +159,13 @@ public abstract class VisualOperatorActionHandler extends EditorActionHandlerBas
TextRange res = null;
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
if (!myRunForEachCaret) {
res = VimPlugin.getMotion().getVisualRange(editor);
res = VisualMotionGroup.INSTANCE.getVisualRange(editor);
}
else {
res = VimPlugin.getMotion().getVisualRange(caret);
res = VisualMotionGroup.INSTANCE.getVisualRange(caret);
}
if (!wasRepeat) {
change = VimPlugin.getMotion()
change = VisualMotionGroup.INSTANCE
.getVisualOperatorRange(editor, caret, cmd == null ? EnumSet.of(CommandFlags.FLAG_MOT_LINEWISE) : cmd.getFlags());
}
if (logger.isDebugEnabled()) logger.debug("change=" + change);
@ -190,12 +191,12 @@ public abstract class VisualOperatorActionHandler extends EditorActionHandlerBas
// If this is a mutli key change then exit visual now
if (cmd.getFlags().contains(CommandFlags.FLAG_MULTIKEY_UNDO)) {
logger.debug("multikey undo - exit visual");
VimPlugin.getMotion().exitVisual(editor);
VisualMotionGroup.INSTANCE.exitVisual(editor);
}
else if (cmd.getFlags().contains(CommandFlags.FLAG_FORCE_LINEWISE)) {
lastMode = CommandState.getInstance(editor).getSubMode();
if (lastMode != CommandState.SubMode.VISUAL_LINE && cmd.getFlags().contains(CommandFlags.FLAG_FORCE_VISUAL)) {
VimPlugin.getMotion().toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_LINE);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 0, CommandState.SubMode.VISUAL_LINE);
}
}
}
@ -221,14 +222,14 @@ public abstract class VisualOperatorActionHandler extends EditorActionHandlerBas
if (cmd != null && cmd.getFlags().contains(CommandFlags.FLAG_FORCE_LINEWISE)) {
if (lastMode != CommandState.SubMode.VISUAL_LINE && cmd.getFlags().contains(CommandFlags.FLAG_FORCE_VISUAL)) {
VimPlugin.getMotion().toggleVisual(editor, 1, 0, lastMode);
VisualMotionGroup.INSTANCE.toggleVisual(editor, 1, 0, lastMode);
}
}
if (cmd == null ||
!cmd.getFlags().contains(CommandFlags.FLAG_MULTIKEY_UNDO) && !cmd.getFlags().contains(CommandFlags.FLAG_EXPECT_MORE)) {
logger.debug("not multikey undo - exit visual");
VimPlugin.getMotion().exitVisual(editor);
VisualMotionGroup.INSTANCE.exitVisual(editor);
}
if (res) {

View File

@ -21,11 +21,11 @@ package com.maddyhome.idea.vim.helper;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Key;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.VisualChange;
import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.group.MotionGroup;
import com.maddyhome.idea.vim.group.motion.VisualMotionGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -69,7 +69,7 @@ public class CaretData {
}
if (previousWasDollar != currentIsDollar && CommandState.inVisualBlockMode(editor)) {
VimPlugin.getMotion().updateBlockSelection(editor);
VisualMotionGroup.INSTANCE.updateBlockSelection(editor);
}
}