From c6ef3f286fd0208abe7efaa67e41213f44dc42d9 Mon Sep 17 00:00:00 2001 From: chylex <contact@chylex.com> Date: Wed, 21 Dec 2022 04:34:56 +0100 Subject: [PATCH] Fix(VIM-696) Restore visual mode after undo/redo, and disable incompatible actions --- .../com/maddyhome/idea/vim/group/IjOptions.kt | 2 +- .../idea/vim/helper/UndoRedoHelper.kt | 30 +++++++++++++------ .../idea/vim/action/change/RedoAction.kt | 2 +- .../idea/vim/action/change/UndoAction.kt | 2 +- .../change/ChangeCaseLowerVisualAction.kt | 3 +- .../change/ChangeCaseUpperVisualAction.kt | 3 +- .../ksp-generated/engine_commands.json | 15 ++++------ 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/maddyhome/idea/vim/group/IjOptions.kt b/src/main/java/com/maddyhome/idea/vim/group/IjOptions.kt index 97de3f8d0..d7e738541 100644 --- a/src/main/java/com/maddyhome/idea/vim/group/IjOptions.kt +++ b/src/main/java/com/maddyhome/idea/vim/group/IjOptions.kt @@ -143,7 +143,7 @@ object IjOptions { addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true)) val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isHidden = true)) - val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", false, isHidden = true)) + val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isHidden = true)) val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true, isHidden = true)) val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isHidden = true)) diff --git a/src/main/java/com/maddyhome/idea/vim/helper/UndoRedoHelper.kt b/src/main/java/com/maddyhome/idea/vim/helper/UndoRedoHelper.kt index f850019c1..9c8274ee3 100644 --- a/src/main/java/com/maddyhome/idea/vim/helper/UndoRedoHelper.kt +++ b/src/main/java/com/maddyhome/idea/vim/helper/UndoRedoHelper.kt @@ -19,6 +19,7 @@ import com.intellij.openapi.fileEditor.TextEditor import com.intellij.openapi.fileEditor.TextEditorWithPreview import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider import com.intellij.openapi.util.registry.Registry +import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.VimCaret import com.maddyhome.idea.vim.api.VimEditor @@ -28,6 +29,8 @@ import com.maddyhome.idea.vim.common.InsertSequence import com.maddyhome.idea.vim.newapi.IjVimCaret import com.maddyhome.idea.vim.newapi.globalIjOptions import com.maddyhome.idea.vim.newapi.ij +import com.maddyhome.idea.vim.state.mode.SelectionType +import com.maddyhome.idea.vim.state.mode.inVisualMode import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService /** @@ -75,15 +78,7 @@ internal class UndoRedoHelper : VimTimestampBasedUndoService { // TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo editor.runWithChangeTracking { undoManager.undo(fileEditor) - - // We execute undo one more time if the previous one just restored selection - if (!hasChanges && hasSelection(editor) && undoManager.isUndoAvailable(fileEditor)) { - undoManager.undo(fileEditor) - } - } - - CommandProcessor.getInstance().runUndoTransparentAction { - removeSelections(editor) + restoreVisualMode(editor) } } else { runWithBooleanRegistryOption("ide.undo.transparent.caret.movement", true) { @@ -230,4 +225,21 @@ internal class UndoRedoHelper : VimTimestampBasedUndoService { val hasChanges: Boolean get() = changeListener.hasChanged || initialPath != editor.getPath() } + + private fun restoreVisualMode(editor: VimEditor) { + if (!editor.inVisualMode && editor.getSelectionModel().hasSelection()) { + val detectedMode = VimPlugin.getVisualMotion().detectSelectionType(editor) + + // Visual block selection is restored into multiple carets, so multi-carets that form a block are always + // identified as visual block mode, leading to false positives. + // Since I use visual block mode much less often than multi-carets, this is a judgment call to never restore + // visual block mode. + val wantedMode = if (detectedMode == SelectionType.BLOCK_WISE) + SelectionType.CHARACTER_WISE + else + detectedMode + + VimPlugin.getVisualMotion().enterVisualMode(editor, wantedMode) + } + } } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/RedoAction.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/RedoAction.kt index ffa99d9ff..cc2b0de6c 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/RedoAction.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/RedoAction.kt @@ -16,7 +16,7 @@ import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.OperatorArguments import com.maddyhome.idea.vim.handler.VimActionHandler -@CommandOrMotion(keys = ["<C-R>"], modes = [Mode.NORMAL]) +@CommandOrMotion(keys = ["U", "<C-R>"], modes = [Mode.NORMAL, Mode.VISUAL]) class RedoAction : VimActionHandler.SingleExecution() { override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/UndoAction.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/UndoAction.kt index d74266c98..67c28ab93 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/UndoAction.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/UndoAction.kt @@ -16,7 +16,7 @@ import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.OperatorArguments import com.maddyhome.idea.vim.handler.VimActionHandler -@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL]) +@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL, Mode.VISUAL]) class UndoAction : VimActionHandler.SingleExecution() { override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseLowerVisualAction.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseLowerVisualAction.kt index 39c92aa3b..79a320981 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseLowerVisualAction.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseLowerVisualAction.kt @@ -8,7 +8,6 @@ package com.maddyhome.idea.vim.action.change.change import com.intellij.vim.annotations.CommandOrMotion -import com.intellij.vim.annotations.Mode import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.VimCaret import com.maddyhome.idea.vim.api.VimChangeGroup @@ -22,7 +21,7 @@ import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler /** * @author vlan */ -@CommandOrMotion(keys = ["u"], modes = [Mode.VISUAL]) +@CommandOrMotion(keys = [], modes = []) class ChangeCaseLowerVisualAction : VisualOperatorActionHandler.ForEachCaret() { override val type: Command.Type = Command.Type.CHANGE diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseUpperVisualAction.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseUpperVisualAction.kt index 36d5f58c3..4782c578a 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseUpperVisualAction.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/action/change/change/ChangeCaseUpperVisualAction.kt @@ -8,7 +8,6 @@ package com.maddyhome.idea.vim.action.change.change import com.intellij.vim.annotations.CommandOrMotion -import com.intellij.vim.annotations.Mode import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.VimCaret import com.maddyhome.idea.vim.api.VimChangeGroup @@ -22,7 +21,7 @@ import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler /** * @author vlan */ -@CommandOrMotion(keys = ["U"], modes = [Mode.VISUAL]) +@CommandOrMotion(keys = [], modes = []) class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() { override val type: Command.Type = Command.Type.CHANGE diff --git a/vim-engine/src/main/resources/ksp-generated/engine_commands.json b/vim-engine/src/main/resources/ksp-generated/engine_commands.json index 2bf8fce56..704a67cf5 100644 --- a/vim-engine/src/main/resources/ksp-generated/engine_commands.json +++ b/vim-engine/src/main/resources/ksp-generated/engine_commands.json @@ -417,7 +417,7 @@ { "keys": "<C-R>", "class": "com.maddyhome.idea.vim.action.change.RedoAction", - "modes": "N" + "modes": "NX" }, { "keys": "<C-R>", @@ -957,7 +957,7 @@ { "keys": "<Undo>", "class": "com.maddyhome.idea.vim.action.change.UndoAction", - "modes": "N" + "modes": "NX" }, { "keys": "<Up>", @@ -1176,8 +1176,8 @@ }, { "keys": "U", - "class": "com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction", - "modes": "X" + "class": "com.maddyhome.idea.vim.action.change.RedoAction", + "modes": "NX" }, { "keys": "V", @@ -1962,12 +1962,7 @@ { "keys": "u", "class": "com.maddyhome.idea.vim.action.change.UndoAction", - "modes": "N" - }, - { - "keys": "u", - "class": "com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction", - "modes": "X" + "modes": "NX" }, { "keys": "v",