1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2024-10-18 01:42:46 +02:00

Compare commits

..

No commits in common. "da3d83ecc62e01b1ff14e25ad1770668a05379b4" and "85a1fbe89e358e5abbd140a7c38f8c9eb6da8de9" have entirely different histories.

24 changed files with 154 additions and 309 deletions

View File

@ -31,8 +31,6 @@ usual beta standards.
* [VIM-2744](https://youtrack.jetbrains.com/issue/VIM-2744) Fix undo from ex line * [VIM-2744](https://youtrack.jetbrains.com/issue/VIM-2744) Fix undo from ex line
* [VIM-2749](https://youtrack.jetbrains.com/issue/VIM-2749) Fix :tabn and :tabN commands * [VIM-2749](https://youtrack.jetbrains.com/issue/VIM-2749) Fix :tabn and :tabN commands
* [VIM-2718](https://youtrack.jetbrains.com/issue/VIM-2718) Fixed case where the primary caret was changed * [VIM-2718](https://youtrack.jetbrains.com/issue/VIM-2718) Fixed case where the primary caret was changed
* [VIM-2766](https://youtrack.jetbrains.com/issue/VIM-2766) Move NERDTree update to background thread
* [VIM-2768](https://youtrack.jetbrains.com/issue/VIM-2768) Refactor listeners
## 1.11.0, 2022-08-09 ## 1.11.0, 2022-08-09

View File

@ -11,7 +11,7 @@ IdeaVim
[![Gitter][gitter-svg]][gitter] [![Gitter][gitter-svg]][gitter]
[![Twitter][twitter-svg]][twitter] [![Twitter][twitter-svg]][twitter]
IdeaVim is a Vim engine for JetBrains IDEs. IdeaVim is a Vim emulation plugin for IntelliJ Platform-based IDEs.
##### Contact maintainers: ##### Contact maintainers:
* [Bug tracker](https://youtrack.jetbrains.com/issues/VIM) * [Bug tracker](https://youtrack.jetbrains.com/issues/VIM)
@ -36,7 +36,7 @@ Setup
- IdeaVim can be installed via `Settings | Plugins`. - IdeaVim can be installed via `Settings | Plugins`.
See the [detailed instructions](https://www.jetbrains.com/help/idea/managing-plugins.html#). See the [detailed instructions](https://www.jetbrains.com/help/idea/managing-plugins.html#).
- Use `Tools | Vim` in the menu to enable or disable vim. - Use `Tools | Vim Emulator` in the menu to enable or disable emulation.
- Use the `~/.ideavimrc` file as an analog of `~/.vimrc` ([learn more](#Files)). The XDG standard is supported, as well. - Use the `~/.ideavimrc` file as an analog of `~/.vimrc` ([learn more](#Files)). The XDG standard is supported, as well.
@ -88,7 +88,7 @@ Here are some examples of supported vim features and commands:
* Vim web help * Vim web help
* `~/.ideavimrc` configuration file * `~/.ideavimrc` configuration file
[IdeaVim plugins](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins): [Emulated Vim plugins](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins):
* vim-easymotion * vim-easymotion
* NERDTree * NERDTree
@ -198,7 +198,7 @@ Alternatively, you can set up initialization commands using [XDG](https://specif
Put your settings to `$XDG_CONFIG_HOME/ideavim/ideavimrc` file. Put your settings to `$XDG_CONFIG_HOME/ideavim/ideavimrc` file.
IdeaVim Plugins Emulated Vim Plugins
-------------------- --------------------
See [doc/emulated-plugins.md](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins) See [doc/emulated-plugins.md](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins)

View File

@ -26,7 +26,7 @@ plugins {
java java
kotlin("jvm") version "1.6.21" kotlin("jvm") version "1.6.21"
id("org.jetbrains.intellij") version "1.10.0-SNAPSHOT" id("org.jetbrains.intellij") version "1.9.0"
id("org.jetbrains.changelog") version "1.3.1" id("org.jetbrains.changelog") version "1.3.1"
// ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle // ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
@ -166,18 +166,6 @@ tasks {
} }
} }
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(javaVersion))
}
}
kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(javaVersion))
}
}
gradle.projectsEvaluated { gradle.projectsEvaluated {
tasks.compileJava { tasks.compileJava {
// options.compilerArgs.add("-Werror") // options.compilerArgs.add("-Werror")

View File

@ -1,10 +1,10 @@
# suppress inspection "UnusedProperty" for whole file # suppress inspection "UnusedProperty" for whole file
ideaVersion=LATEST-EAP-SNAPSHOT ideaVersion=2022.2.2
downloadIdeaSources=true downloadIdeaSources=true
instrumentPluginCode=true instrumentPluginCode=true
version=SNAPSHOT version=SNAPSHOT
javaVersion=17 javaVersion=11
remoteRobotVersion=0.11.15 remoteRobotVersion=0.11.15
antlrVersion=4.10.1 antlrVersion=4.10.1

View File

@ -27,7 +27,6 @@ import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.actionSystem.TypedAction; import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler; import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import com.intellij.openapi.editor.event.*; import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.util.Disposer;
import com.maddyhome.idea.vim.helper.HandlerInjector; import com.maddyhome.idea.vim.helper.HandlerInjector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -102,41 +101,32 @@ public class EventFacade {
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable); EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
} }
public void addEditorMouseListener(@NotNull Editor editor, public void addEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
@NotNull EditorMouseListener listener, editor.addEditorMouseListener(listener);
@NotNull Disposable disposable) {
editor.addEditorMouseListener(listener, disposable);
} }
public void removeEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) { public void removeEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
editor.removeEditorMouseListener(listener); editor.removeEditorMouseListener(listener);
} }
public void addComponentMouseListener(@NotNull Component component, public void addComponentMouseListener(@NotNull Component component, @NotNull MouseListener mouseListener) {
@NotNull MouseListener mouseListener,
@NotNull Disposable disposable) {
component.addMouseListener(mouseListener); component.addMouseListener(mouseListener);
Disposer.register(disposable, () -> component.removeMouseListener(mouseListener));
} }
public void removeComponentMouseListener(@NotNull Component component, @NotNull MouseListener mouseListener) { public void removeComponentMouseListener(@NotNull Component component, @NotNull MouseListener mouseListener) {
component.removeMouseListener(mouseListener); component.removeMouseListener(mouseListener);
} }
public void addEditorMouseMotionListener(@NotNull Editor editor, public void addEditorMouseMotionListener(@NotNull Editor editor, @NotNull EditorMouseMotionListener listener) {
@NotNull EditorMouseMotionListener listener, editor.addEditorMouseMotionListener(listener);
@NotNull Disposable disposable) {
editor.addEditorMouseMotionListener(listener, disposable);
} }
public void removeEditorMouseMotionListener(@NotNull Editor editor, @NotNull EditorMouseMotionListener listener) { public void removeEditorMouseMotionListener(@NotNull Editor editor, @NotNull EditorMouseMotionListener listener) {
editor.removeEditorMouseMotionListener(listener); editor.removeEditorMouseMotionListener(listener);
} }
public void addEditorSelectionListener(@NotNull Editor editor, public void addEditorSelectionListener(@NotNull Editor editor, @NotNull SelectionListener listener) {
@NotNull SelectionListener listener, editor.getSelectionModel().addSelectionListener(listener);
@NotNull Disposable disposable) {
editor.getSelectionModel().addSelectionListener(listener, disposable);
} }
public void removeEditorSelectionListener(@NotNull Editor editor, @NotNull SelectionListener listener) { public void removeEditorSelectionListener(@NotNull Editor editor, @NotNull SelectionListener listener) {

View File

@ -114,7 +114,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
@Override @Override
public void dispose() { public void dispose() {
LOG.debug("disposeComponent"); LOG.debug("disposeComponent");
turnOffPlugin(false); turnOffPlugin();
LOG.debug("done"); LOG.debug("done");
} }
@ -272,7 +272,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
if (isEnabled() == enabled) return; if (isEnabled() == enabled) return;
if (!enabled) { if (!enabled) {
getInstance().turnOffPlugin(true); getInstance().turnOffPlugin();
} }
getInstance().enabled = enabled; getInstance().enabled = enabled;
@ -365,14 +365,12 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
VimListenerManager.INSTANCE.turnOn(); VimListenerManager.INSTANCE.turnOn();
} }
private void turnOffPlugin(boolean unsubscribe) { private void turnOffPlugin() {
SearchGroup searchGroup = getSearchIfCreated(); SearchGroup searchGroup = getSearchIfCreated();
if (searchGroup != null) { if (searchGroup != null) {
searchGroup.turnOff(); searchGroup.turnOff();
} }
if (unsubscribe) { VimListenerManager.INSTANCE.turnOff();
VimListenerManager.INSTANCE.turnOff();
}
ExEntryPanel.fullReset(); ExEntryPanel.fullReset();
// Unregister vim actions in command mode // Unregister vim actions in command mode

View File

@ -243,7 +243,7 @@ class NerdTree : VimExtension {
e.presentation.isEnabled = !speedSearchIsHere(project) e.presentation.isEnabled = !speedSearchIsHere(project)
} }
override fun getActionUpdateThread() = ActionUpdateThread.EDT override fun getActionUpdateThread() = ActionUpdateThread.BGT
private fun speedSearchIsHere(project: Project): Boolean { private fun speedSearchIsHere(project: Project): Boolean {
val component = ProjectView.getInstance(project).currentProjectViewPane.tree ?: return false val component = ProjectView.getInstance(project).currentProjectViewPane.tree ?: return false

View File

@ -21,7 +21,6 @@ import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.codeInsight.actions.AsyncActionExecutionService; import com.intellij.codeInsight.actions.AsyncActionExecutionService;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager;
@ -36,13 +35,13 @@ import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseListener; import com.intellij.openapi.editor.event.EditorMouseListener;
import com.intellij.openapi.editor.impl.TextRangeInterval; import com.intellij.openapi.editor.impl.TextRangeInterval;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiUtilBase; import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.JBColor;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import com.maddyhome.idea.vim.EventFacade; import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
@ -156,12 +155,14 @@ public class ChangeGroup extends VimChangeGroupBase {
} }
}; };
public void editorCreated(Editor editor, @NotNull Disposable disposable) { @Override
EventFacade.getInstance().addEditorMouseListener(editor, listener, disposable); public void editorCreated(VimEditor editor) {
EventFacade.getInstance().addEditorMouseListener(((IjVimEditor) editor).getEditor(), listener);
} }
public void editorReleased(Editor editor) { @Override
EventFacade.getInstance().removeEditorMouseListener(editor, listener); public void editorReleased(VimEditor editor) {
EventFacade.getInstance().removeEditorMouseListener(((IjVimEditor) editor).getEditor(), listener);
} }
@Override @Override
@ -807,9 +808,8 @@ public class ChangeGroup extends VimChangeGroupBase {
lastShownTime = currentTime; lastShownTime = currentTime;
ApplicationManager.getApplication().invokeLater(() -> { ApplicationManager.getApplication().invokeLater(() -> {
final Balloon balloon = JBPopupFactory.getInstance() final Balloon balloon = JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder("Wow, nice vim skills!", VimIcons.IDEAVIM, .createHtmlTextBalloonBuilder("Wow, nice vim skills!", VimIcons.IDEAVIM, JBColor.background(), null)
MessageType.INFO.getTitleForeground(), MessageType.INFO.getPopupBackground(), .createBalloon();
null).createBalloon();
balloon.show(JBPopupFactory.getInstance().guessBestPopupLocation(((IjVimEditor)editor).getEditor()), balloon.show(JBPopupFactory.getInstance().guessBestPopupLocation(((IjVimEditor)editor).getEditor()),
Balloon.Position.below); Balloon.Position.below);
}); });

View File

@ -36,14 +36,9 @@ import com.intellij.openapi.editor.event.SelectionEvent
import com.intellij.openapi.editor.event.SelectionListener import com.intellij.openapi.editor.event.SelectionListener
import com.intellij.openapi.editor.ex.DocumentEx import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.impl.EditorComponentImpl import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.fileEditor.FileEditorManagerEvent import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.fileEditor.FileEditorManagerListener import com.intellij.openapi.fileEditor.FileEditorManagerListener
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.rd.createNestedDisposable
import com.intellij.openapi.util.Disposer
import com.intellij.util.ExceptionUtil import com.intellij.util.ExceptionUtil
import com.jetbrains.rd.util.lifetime.intersect
import com.maddyhome.idea.vim.EventFacade import com.maddyhome.idea.vim.EventFacade
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimKeyListener import com.maddyhome.idea.vim.VimKeyListener
@ -78,6 +73,8 @@ import com.maddyhome.idea.vim.helper.vimLastColumn
import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipEvents import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipEvents
import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipNDragEvents import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipNDragEvents
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.remove
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
@ -156,26 +153,17 @@ object VimListenerManager {
} }
fun add(editor: Editor) { fun add(editor: Editor) {
val pluginLifetime = VimPlugin.getInstance().createLifetime()
val editorLifetime = (editor as EditorImpl).disposable.createLifetime()
val disposable = editorLifetime.intersect(pluginLifetime).createNestedDisposable("MyLifetimedDisposable")
editor.contentComponent.addKeyListener(VimKeyListener) editor.contentComponent.addKeyListener(VimKeyListener)
Disposer.register(disposable) { editor.contentComponent.removeKeyListener(VimKeyListener) }
val eventFacade = EventFacade.getInstance() val eventFacade = EventFacade.getInstance()
eventFacade.addEditorMouseListener(editor, EditorMouseHandler, disposable) eventFacade.addEditorMouseListener(editor, EditorMouseHandler)
eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler, disposable) eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler)
eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler, disposable) eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler)
eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener, disposable) eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener)
VimPlugin.getEditor().editorCreated(editor) VimPlugin.getEditor().editorCreated(editor)
VimPlugin.getChange().editorCreated(editor, disposable) VimPlugin.getChange().editorCreated(IjVimEditor(editor))
Disposer.register(disposable) {
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, true)
}
} }
fun remove(editor: Editor, isReleased: Boolean) { fun remove(editor: Editor, isReleased: Boolean) {
@ -189,7 +177,7 @@ object VimListenerManager {
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, isReleased) VimPlugin.getEditorIfCreated()?.editorDeinit(editor, isReleased)
VimPlugin.getChange().editorReleased(editor) VimPlugin.getChange().editorReleased(IjVimEditor(editor))
} }
} }
@ -221,6 +209,7 @@ object VimListenerManager {
} }
override fun editorReleased(event: EditorFactoryEvent) { override fun editorReleased(event: EditorFactoryEvent) {
remove(event.editor, true)
VimPlugin.getMark().editorReleased(event) VimPlugin.getMark().editorReleased(event)
} }
} }

View File

@ -21,14 +21,15 @@ package com.maddyhome.idea.vim.statistic
import com.intellij.internal.statistic.beans.MetricEvent import com.intellij.internal.statistic.beans.MetricEvent
import com.intellij.internal.statistic.eventLog.EventLogGroup import com.intellij.internal.statistic.eventLog.EventLogGroup
import com.intellij.internal.statistic.eventLog.events.EventFields import com.intellij.internal.statistic.eventLog.events.EventFields
import com.intellij.internal.statistic.eventLog.events.EventPair
import com.intellij.internal.statistic.eventLog.events.StringListEventField
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.key.ShortcutOwner import com.maddyhome.idea.vim.key.ShortcutOwner
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
import java.awt.event.InputEvent
import java.awt.event.InputEvent.CTRL_DOWN_MASK import java.awt.event.InputEvent.CTRL_DOWN_MASK
import java.awt.event.InputEvent.SHIFT_DOWN_MASK import java.awt.event.InputEvent.SHIFT_DOWN_MASK
import java.awt.event.KeyEvent
import javax.swing.KeyStroke import javax.swing.KeyStroke
internal class ShortcutConflictState : ApplicationUsagesCollector() { internal class ShortcutConflictState : ApplicationUsagesCollector() {
@ -38,15 +39,17 @@ internal class ShortcutConflictState : ApplicationUsagesCollector() {
override fun getMetrics(): Set<MetricEvent> { override fun getMetrics(): Set<MetricEvent> {
val metrics = mutableSetOf<MetricEvent>() val metrics = mutableSetOf<MetricEvent>()
keyStrokes.forEach { keystroke -> keyStrokes.forEach { keystroke ->
getHandlersForShortcut(keystroke) getHandlersForShortcut(keystroke).forEach { mode ->
.filter { !setOf(HandledModes.INSERT_UNDEFINED, HandledModes.NORMAL_UNDEFINED, HandledModes.VISUAL_AND_SELECT_UNDEFINED).contains(it) } metrics += HANDLER.metric(injector.parser.toKeyNotation(keystroke), mode)
.forEach { mode -> }
metrics += HANDLER.metric(keystroke.toReadableString(), mode)
}
} }
return metrics return metrics
} }
fun StringListEventField.withKeyStroke(ks: KeyStroke): EventPair<List<String>> {
return this.with(getHandlersForShortcut(ks).map { it.name })
}
private fun getHandlersForShortcut(shortcut: KeyStroke): List<HandledModes> { private fun getHandlersForShortcut(shortcut: KeyStroke): List<HandledModes> {
val modes = VimPlugin.getKey().shortcutConflicts[shortcut] ?: return listOf(HandledModes.NORMAL_UNDEFINED, HandledModes.INSERT_UNDEFINED, HandledModes.VISUAL_AND_SELECT_UNDEFINED) val modes = VimPlugin.getKey().shortcutConflicts[shortcut] ?: return listOf(HandledModes.NORMAL_UNDEFINED, HandledModes.INSERT_UNDEFINED, HandledModes.VISUAL_AND_SELECT_UNDEFINED)
@ -165,23 +168,12 @@ internal class ShortcutConflictState : ApplicationUsagesCollector() {
KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK), KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK), KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
) )
private val KEY_STROKE = EventFields.String("key_stroke", keyStrokes.map { it.toReadableString() }) private val KEY_STROKE = EventFields.String("key_stroke", keyStrokes.map { injector.parser.toKeyNotation(it) })
private val HANDLER_MODE = EventFields.Enum<HandledModes>("handler") private val HANDLER_MODE = EventFields.Enum<HandledModes>("handler")
private val HANDLER = GROUP.registerEvent("vim.handler", KEY_STROKE, HANDLER_MODE) private val HANDLER = GROUP.registerEvent("vim.handler", KEY_STROKE, HANDLER_MODE)
} }
} }
private fun KeyStroke.toReadableString(): String {
val result = StringBuilder()
val modifiers = this.modifiers
if (modifiers > 0) {
result.append(InputEvent.getModifiersExText(modifiers))
.append("+")
}
result.append(KeyEvent.getKeyText(this.keyCode))
return result.toString()
}
private enum class HandledModes { private enum class HandledModes {
NORMAL_UNDEFINED, NORMAL_UNDEFINED,
NORMAL_IDE, NORMAL_IDE,

View File

@ -109,7 +109,7 @@
]]> ]]>
</change-notes> </change-notes>
<description><![CDATA[ <description><![CDATA[
<p>Vim engine for JetBrains IDEs</p> <p>Vim emulation plugin for IntelliJ Platform-based IDEs.</p>
<br/> <br/>
<p>IdeaVim supports many Vim features including normal/insert/visual modes, motion keys, deletion/changing, <p>IdeaVim supports many Vim features including normal/insert/visual modes, motion keys, deletion/changing,
marks, registers, some Ex commands, Vim regexps, configuration via ~/.ideavimrc, macros, Vim plugins, etc.</p> marks, registers, some Ex commands, Vim regexps, configuration via ~/.ideavimrc, macros, Vim plugins, etc.</p>

View File

@ -63,7 +63,7 @@ E548=E548: Digit expected: {0}
E549=E549: Illegal percentage: {0} E549=E549: Illegal percentage: {0}
E774=E774: 'operatorfunc' is empty E774=E774: 'operatorfunc' is empty
action.VimPluginToggle.text=Vim action.VimPluginToggle.text=Vim Emulator
action.VimPluginToggle.description=Toggle the vim plugin On/Off action.VimPluginToggle.description=Toggle the vim plugin On/Off
action.VimPluginToggle.enabled=Enabled action.VimPluginToggle.enabled=Enabled
action.VimPluginToggle.enable=Enable action.VimPluginToggle.enable=Enable

View File

@ -19,7 +19,6 @@ package com.maddyhome.idea.vim.action
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -28,40 +27,25 @@ import com.maddyhome.idea.vim.command.VimStateMachine
import com.maddyhome.idea.vim.handler.VimActionHandler import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.mode import com.maddyhome.idea.vim.helper.mode
class ResetModeAction : VimActionHandler.ConditionalMulticaret() { class ResetModeAction : VimActionHandler.SingleExecution() {
private lateinit var modeBeforeReset: VimStateMachine.Mode
override val type: Command.Type = Command.Type.OTHER_WRITABLE override val type: Command.Type = Command.Type.OTHER_WRITABLE
override fun runAsMulticaret(
override fun execute(
editor: VimEditor, editor: VimEditor,
context: ExecutionContext, context: ExecutionContext,
cmd: Command, cmd: Command,
operatorArguments: OperatorArguments, operatorArguments: OperatorArguments,
): Boolean { ): Boolean {
modeBeforeReset = editor.mode val modeBeforeReset = editor.mode
KeyHandler.getInstance().fullReset(editor) KeyHandler.getInstance().fullReset(editor)
return true
}
override fun execute(
editor: VimEditor,
caret: VimCaret,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
if (modeBeforeReset == VimStateMachine.Mode.INSERT) { if (modeBeforeReset == VimStateMachine.Mode.INSERT) {
val position = injector.motion.getOffsetOfHorizontalMotion(editor, caret, -1, false) editor.forEachCaret { caret ->
caret.moveToOffset(position) val position = injector.motion.getOffsetOfHorizontalMotion(editor, caret, -1, false)
caret.moveToOffset(position)
}
} }
return true
}
override fun execute( return true
editor: VimEditor,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
error("This method should not be used")
} }
} }

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.leftright package com.maddyhome.idea.vim.action.motion.leftright
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimMotionGroupBase import com.maddyhome.idea.vim.api.VimMotionGroupBase
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
@ -36,25 +35,27 @@ class MotionShiftEndAction : ShiftedSpecialKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command, caret: VimCaret) { override fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command) {
var allow = false editor.forEachCaret { caret ->
if (editor.inInsertMode) { var allow = false
allow = true if (editor.inInsertMode) {
} else if (editor.inVisualMode || editor.inSelectMode) {
val opt = (
injector.optionService.getOptionValue(
OptionScope.LOCAL(editor),
OptionConstants.selectionName
) as VimString
).value
if (opt != "old") {
allow = true allow = true
} else if (editor.inVisualMode || editor.inSelectMode) {
val opt = (
injector.optionService.getOptionValue(
OptionScope.LOCAL(editor),
OptionConstants.selectionName
) as VimString
).value
if (opt != "old") {
allow = true
}
} }
}
val newOffset = injector.motion.moveCaretToLineEndOffset(editor, caret, cmd.count - 1, allow) val newOffset = injector.motion.moveCaretToLineEndOffset(editor, caret, cmd.count - 1, allow)
caret.vimLastColumn = VimMotionGroupBase.LAST_COLUMN caret.vimLastColumn = VimMotionGroupBase.LAST_COLUMN
caret.moveToOffset(newOffset) caret.moveToOffset(newOffset)
caret.vimLastColumn = VimMotionGroupBase.LAST_COLUMN caret.vimLastColumn = VimMotionGroupBase.LAST_COLUMN
}
} }
} }

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.leftright package com.maddyhome.idea.vim.action.motion.leftright
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -32,8 +31,10 @@ class MotionShiftHomeAction : ShiftedSpecialKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command, caret: VimCaret) { override fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val newOffset = injector.motion.moveCaretToLineStart(editor, caret) editor.forEachCaret { caret ->
caret.moveToOffset(newOffset) val newOffset = injector.motion.moveCaretToLineStart(editor, caret)
caret.moveToOffset(newOffset)
}
} }
} }

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.leftright package com.maddyhome.idea.vim.action.motion.leftright
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -30,20 +29,23 @@ import com.maddyhome.idea.vim.handler.ShiftedArrowKeyHandler
* @author Alex Plate * @author Alex Plate
*/ */
class MotionShiftLeftAction : ShiftedArrowKeyHandler(true) { class MotionShiftLeftAction : ShiftedArrowKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motionWithKeyModel(editor: VimEditor, caret: VimCaret, context: ExecutionContext, cmd: Command) { override fun motionWithKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val vertical = injector.motion.getOffsetOfHorizontalMotion(editor, caret, -cmd.count, true) editor.forEachCaret { caret ->
caret.moveToOffset(vertical) val vertical = injector.motion.getOffsetOfHorizontalMotion(editor, caret, -cmd.count, true)
caret.moveToOffset(vertical)
}
} }
override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) { override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val caret = editor.currentCaret() editor.forEachCaret { caret ->
val newOffset = injector.motion.findOffsetOfNextWord(editor, caret.offset.point, -cmd.count, false) val newOffset = injector.motion.findOffsetOfNextWord(editor, caret.offset.point, -cmd.count, false)
if (newOffset is Motion.AbsoluteOffset) { if (newOffset is Motion.AbsoluteOffset) {
caret.moveToOffset(newOffset.offset) caret.moveToOffset(newOffset.offset)
}
} }
} }
} }

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.leftright package com.maddyhome.idea.vim.action.motion.leftright
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -30,20 +29,23 @@ import com.maddyhome.idea.vim.handler.ShiftedArrowKeyHandler
* @author Alex Plate * @author Alex Plate
*/ */
class MotionShiftRightAction : ShiftedArrowKeyHandler(true) { class MotionShiftRightAction : ShiftedArrowKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motionWithKeyModel(editor: VimEditor, caret: VimCaret, context: ExecutionContext, cmd: Command) { override fun motionWithKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val vertical = injector.motion.getOffsetOfHorizontalMotion(editor, caret, cmd.count, true) editor.forEachCaret { caret ->
caret.moveToOffset(vertical) val vertical = injector.motion.getOffsetOfHorizontalMotion(editor, caret, cmd.count, true)
caret.moveToOffset(vertical)
}
} }
override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) { override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val caret = editor.currentCaret() editor.forEachCaret { caret ->
val newOffset = injector.motion.findOffsetOfNextWord(editor, caret.offset.point, cmd.count, false) val newOffset = injector.motion.findOffsetOfNextWord(editor, caret.offset.point, cmd.count, false)
if (newOffset is Motion.AbsoluteOffset) { if (newOffset is Motion.AbsoluteOffset) {
caret.moveToOffset(newOffset.offset) caret.moveToOffset(newOffset.offset)
}
} }
} }
} }

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.updown package com.maddyhome.idea.vim.action.motion.updown
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -29,16 +28,18 @@ import com.maddyhome.idea.vim.handler.ShiftedArrowKeyHandler
* @author Alex Plate * @author Alex Plate
*/ */
class MotionShiftDownAction : ShiftedArrowKeyHandler(false) { class MotionShiftDownAction : ShiftedArrowKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motionWithKeyModel(editor: VimEditor, caret: VimCaret, context: ExecutionContext, cmd: Command) { override fun motionWithKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val vertical = injector.motion.getVerticalMotionOffset(editor, caret, cmd.count) editor.forEachCaret { caret ->
val col = injector.engineEditorHelper.prepareLastColumn(caret) val vertical = injector.motion.getVerticalMotionOffset(editor, caret, cmd.count)
caret.moveToOffset(vertical) val col = injector.engineEditorHelper.prepareLastColumn(caret)
caret.moveToOffset(vertical)
injector.engineEditorHelper.updateLastColumn(caret, col) injector.engineEditorHelper.updateLastColumn(caret, col)
}
} }
override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) { override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.updown package com.maddyhome.idea.vim.action.motion.updown
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -29,16 +28,18 @@ import com.maddyhome.idea.vim.handler.ShiftedArrowKeyHandler
* @author Alex Plate * @author Alex Plate
*/ */
class MotionShiftUpAction : ShiftedArrowKeyHandler(false) { class MotionShiftUpAction : ShiftedArrowKeyHandler() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun motionWithKeyModel(editor: VimEditor, caret: VimCaret, context: ExecutionContext, cmd: Command) { override fun motionWithKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {
val vertical = injector.motion.getVerticalMotionOffset(editor, caret, -cmd.count) editor.forEachCaret { caret ->
val col = injector.engineEditorHelper.prepareLastColumn(caret) val vertical = injector.motion.getVerticalMotionOffset(editor, caret, -cmd.count)
caret.moveToOffset(vertical) val col = injector.engineEditorHelper.prepareLastColumn(caret)
caret.moveToOffset(vertical)
injector.engineEditorHelper.updateLastColumn(caret, col) injector.engineEditorHelper.updateLastColumn(caret, col)
}
} }
override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) { override fun motionWithoutKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command) {

View File

@ -30,17 +30,20 @@ import com.maddyhome.idea.vim.helper.inBlockSubMode
/** /**
* @author vlan * @author vlan
*/ */
class VisualSwapEndsAction : VimActionHandler.ForEachCaret() { class VisualSwapEndsAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun execute( override fun execute(
editor: VimEditor, editor: VimEditor,
caret: VimCaret,
context: ExecutionContext, context: ExecutionContext,
cmd: Command, cmd: Command,
operatorArguments: OperatorArguments operatorArguments: OperatorArguments,
): Boolean = swapVisualEnds(caret) ): Boolean {
var ret = true
editor.forEachCaret { ret = ret and swapVisualEnds(it) }
return ret
}
} }
/** /**

View File

@ -19,7 +19,6 @@
package com.maddyhome.idea.vim.action.motion.visual package com.maddyhome.idea.vim.action.motion.visual
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
@ -30,10 +29,11 @@ import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
class VisualToggleLineModeAction : VimActionHandler.ConditionalMulticaret() { class VisualToggleLineModeAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY override val type: Command.Type = Command.Type.OTHER_READONLY
override fun runAsMulticaret(
override fun execute(
editor: VimEditor, editor: VimEditor,
context: ExecutionContext, context: ExecutionContext,
cmd: Command, cmd: Command,
@ -46,29 +46,10 @@ class VisualToggleLineModeAction : VimActionHandler.ConditionalMulticaret() {
) as VimString ) as VimString
).value ).value
return if ("cmd" in listOption) { return if ("cmd" in listOption) {
injector.visualMotionGroup.enterSelectMode(editor, VimStateMachine.SubMode.VISUAL_LINE) injector.visualMotionGroup.enterSelectMode(editor, VimStateMachine.SubMode.VISUAL_LINE).also {
true editor.forEachCaret { it.vimSetSelection(it.offset.point) }
} else false }
} } else injector.visualMotionGroup
override fun execute(
editor: VimEditor,
caret: VimCaret,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
caret.vimSetSelection(caret.offset.point)
return true
}
override fun execute(
editor: VimEditor,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
return injector.visualMotionGroup
.toggleVisual(editor, cmd.count, cmd.rawCount, VimStateMachine.SubMode.VISUAL_LINE) .toggleVisual(editor, cmd.count, cmd.rawCount, VimStateMachine.SubMode.VISUAL_LINE)
} }
} }

View File

@ -47,6 +47,10 @@ interface VimChangeGroup {
fun initInsert(editor: VimEditor, context: ExecutionContext, mode: VimStateMachine.Mode) fun initInsert(editor: VimEditor, context: ExecutionContext, mode: VimStateMachine.Mode)
fun editorCreated(editor: VimEditor?)
fun editorReleased(editor: VimEditor?)
fun processEscape(editor: VimEditor, context: ExecutionContext?, operatorArguments: OperatorArguments) fun processEscape(editor: VimEditor, context: ExecutionContext?, operatorArguments: OperatorArguments)
fun processEnter(editor: VimEditor, context: ExecutionContext) fun processEnter(editor: VimEditor, context: ExecutionContext)

View File

@ -42,28 +42,8 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
* *
* Handler is called once for all carets * Handler is called once for all carets
*/ */
abstract class ShiftedSpecialKeyHandler : VimActionHandler.ConditionalMulticaret() { abstract class ShiftedSpecialKeyHandler : VimActionHandler.SingleExecution() {
final override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean { final override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
error("This method should not be executed")
}
override fun execute(
editor: VimEditor,
caret: VimCaret,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
motion(editor, context, cmd, caret)
return true
}
override fun runAsMulticaret(
editor: VimEditor,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
val startSel = OptionConstants.keymodel_startsel in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.keymodelName) as VimString).value val startSel = OptionConstants.keymodel_startsel in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.keymodelName) as VimString).value
if (startSel && !editor.inVisualMode && !editor.inSelectMode) { if (startSel && !editor.inVisualMode && !editor.inSelectMode) {
if (OptionConstants.selectmode_key in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value) { if (OptionConstants.selectmode_key in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value) {
@ -73,6 +53,7 @@ abstract class ShiftedSpecialKeyHandler : VimActionHandler.ConditionalMulticaret
.toggleVisual(editor, 1, 0, VimStateMachine.SubMode.VISUAL_CHARACTER) .toggleVisual(editor, 1, 0, VimStateMachine.SubMode.VISUAL_CHARACTER)
} }
} }
motion(editor, context, cmd)
return true return true
} }
@ -80,7 +61,7 @@ abstract class ShiftedSpecialKeyHandler : VimActionHandler.ConditionalMulticaret
* This method is called when `keymodel` doesn't contain `startsel`, * This method is called when `keymodel` doesn't contain `startsel`,
* or contains one of `continue*` values but in different mode. * or contains one of `continue*` values but in different mode.
*/ */
abstract fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command, caret: VimCaret) abstract fun motion(editor: VimEditor, context: ExecutionContext, cmd: Command)
} }
/** /**
@ -90,16 +71,16 @@ abstract class ShiftedSpecialKeyHandler : VimActionHandler.ConditionalMulticaret
* *
* Handler is called once for all carets * Handler is called once for all carets
*/ */
abstract class ShiftedArrowKeyHandler(private val runBothCommandsAsMulticaret: Boolean) : VimActionHandler.ConditionalMulticaret() { abstract class ShiftedArrowKeyHandler : VimActionHandler.SingleExecution() {
final override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val keymodelOption = (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.keymodelName) as VimString).value
val startSel = OptionConstants.keymodel_startsel in keymodelOption
val inVisualMode = editor.inVisualMode
val inSelectMode = editor.inSelectMode
override fun runAsMulticaret( val continueSelectSelection = OptionConstants.keymodel_continueselect in keymodelOption && inSelectMode
editor: VimEditor, val continueVisualSelection = OptionConstants.keymodel_continuevisual in keymodelOption && inVisualMode
context: ExecutionContext, if (startSel || continueSelectSelection || continueVisualSelection) {
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
val (inVisualMode, inSelectMode, withKey) = withKeyOrNot(editor)
if (withKey) {
if (!inVisualMode && !inSelectMode) { if (!inVisualMode && !inSelectMode) {
if (OptionConstants.selectmode_key in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value) { if (OptionConstants.selectmode_key in (injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value) {
injector.visualMotionGroup.enterSelectMode(editor, VimStateMachine.SubMode.VISUAL_CHARACTER) injector.visualMotionGroup.enterSelectMode(editor, VimStateMachine.SubMode.VISUAL_CHARACTER)
@ -108,54 +89,17 @@ abstract class ShiftedArrowKeyHandler(private val runBothCommandsAsMulticaret: B
.toggleVisual(editor, 1, 0, VimStateMachine.SubMode.VISUAL_CHARACTER) .toggleVisual(editor, 1, 0, VimStateMachine.SubMode.VISUAL_CHARACTER)
} }
} }
return true motionWithKeyModel(editor, context, cmd)
} else { } else {
return runBothCommandsAsMulticaret motionWithoutKeyModel(editor, context, cmd)
} }
}
private fun withKeyOrNot(editor: VimEditor): Triple<Boolean, Boolean, Boolean> {
val keymodelOption =
(injector.optionService.getOptionValue(OptionScope.GLOBAL, OptionConstants.keymodelName) as VimString).value
val startSel = OptionConstants.keymodel_startsel in keymodelOption
val inVisualMode = editor.inVisualMode
val inSelectMode = editor.inSelectMode
val continueSelectSelection = OptionConstants.keymodel_continueselect in keymodelOption && inSelectMode
val continueVisualSelection = OptionConstants.keymodel_continuevisual in keymodelOption && inVisualMode
val withKey = startSel || continueSelectSelection || continueVisualSelection
return Triple(inVisualMode, inSelectMode, withKey)
}
override fun execute(
editor: VimEditor,
caret: VimCaret,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
if (runBothCommandsAsMulticaret) {
val (_, _, withKey) = withKeyOrNot(editor)
if (withKey) {
motionWithKeyModel(editor, caret, context, cmd)
} else {
motionWithoutKeyModel(editor, context, cmd)
}
} else {
motionWithKeyModel(editor, caret, context, cmd)
}
return true
}
final override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
motionWithoutKeyModel(editor, context, cmd)
return true return true
} }
/** /**
* This method is called when `keymodel` contains `startsel`, or one of `continue*` values in corresponding mode * This method is called when `keymodel` contains `startsel`, or one of `continue*` values in corresponding mode
*/ */
abstract fun motionWithKeyModel(editor: VimEditor, caret: VimCaret, context: ExecutionContext, cmd: Command) abstract fun motionWithKeyModel(editor: VimEditor, context: ExecutionContext, cmd: Command)
/** /**
* This method is called when `keymodel` doesn't contain `startsel`, * This method is called when `keymodel` doesn't contain `startsel`,

View File

@ -61,30 +61,6 @@ sealed class VimActionHandler(myRunForEachCaret: Boolean) : EditorActionHandlerB
): Boolean ): Boolean
} }
abstract class ConditionalMulticaret : VimActionHandler(false) {
abstract fun runAsMulticaret(
editor: VimEditor,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean
abstract fun execute(
editor: VimEditor,
caret: VimCaret,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean
abstract fun execute(
editor: VimEditor,
context: ExecutionContext,
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean
}
final override fun baseExecute( final override fun baseExecute(
editor: VimEditor, editor: VimEditor,
caret: VimCaret, caret: VimCaret,
@ -95,16 +71,6 @@ sealed class VimActionHandler(myRunForEachCaret: Boolean) : EditorActionHandlerB
return when (this) { return when (this) {
is ForEachCaret -> execute(editor, caret, context, cmd, operatorArguments) is ForEachCaret -> execute(editor, caret, context, cmd, operatorArguments)
is SingleExecution -> execute(editor, context, cmd, operatorArguments) is SingleExecution -> execute(editor, context, cmd, operatorArguments)
is ConditionalMulticaret -> {
val runAsMulticaret = runAsMulticaret(editor, context, cmd, operatorArguments)
return if (runAsMulticaret) {
var res = true
editor.forEachCaret { res = execute(editor, it, context, cmd, operatorArguments) && res }
res
} else {
execute(editor, context, cmd, operatorArguments)
}
}
} }
} }
} }