Skip to content

Commit

Permalink
Fix(VIM-696): Vim selection issue after undo
Browse files Browse the repository at this point in the history
  • Loading branch information
lippfi committed Oct 25, 2023
1 parent fdd32cb commit a9ba978
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 79 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/maddyhome/idea/vim/group/IjOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public object IjOptions {
"lookupkeys",
"<Tab>,<Down>,<Up>,<Enter>,<Left>,<Right>,<C-Down>,<C-Up>,<PageUp>,<PageDown>,<C-J>,<C-Q>")
)
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true))
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", false))
public val trackactionids: ToggleOption = addOption(ToggleOption("trackactionids", GLOBAL, "tai", false))
public val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true))
public val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true))
Expand Down
41 changes: 2 additions & 39 deletions src/main/java/com/maddyhome/idea/vim/helper/UndoRedoHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ package com.maddyhome.idea.vim.helper
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.impl.UndoManagerImpl
import com.intellij.openapi.command.undo.UndoManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.ChangesListener
import com.maddyhome.idea.vim.group.IjOptions
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.ij
Expand All @@ -30,15 +27,6 @@ import com.maddyhome.idea.vim.undo.UndoRedoBase
*/
@Service
internal class UndoRedoHelper : UndoRedoBase() {
init {
fun onOldUndoChanged() {
UndoManagerImpl.ourNeverAskUser = !injector.globalIjOptions().oldundo
}

injector.optionGroup.addGlobalOptionChangeListener(IjOptions.oldundo, ::onOldUndoChanged)
onOldUndoChanged()
}

override fun undo(editor: VimEditor, context: ExecutionContext): Boolean {
val ijContext = context.context as DataContext
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
Expand All @@ -51,8 +39,7 @@ internal class UndoRedoHelper : UndoRedoBase() {
if (injector.globalIjOptions().oldundo) {
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
} else {
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })

undoManager.undo(fileEditor)
editor.carets().forEach {
val ijCaret = it.ij
val hasSelection = ijCaret.hasSelection()
Expand Down Expand Up @@ -82,7 +69,7 @@ internal class UndoRedoHelper : UndoRedoBase() {
if (injector.globalIjOptions().oldundo) {
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
} else {
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
undoManager.redo(fileEditor)
CommandProcessor.getInstance().runUndoTransparentAction {
editor.carets().forEach { it.ij.removeSelection() }
}
Expand All @@ -91,28 +78,4 @@ internal class UndoRedoHelper : UndoRedoBase() {
}
return false
}

private fun performUntilFileChanges(editor: VimEditor?, check: () -> Boolean, action: Runnable) {
if (editor == null) return
val vimDocument = editor.document

val changeListener = object : ChangesListener {
var hasChanged = false

override fun documentChanged(change: ChangesListener.Change) {
hasChanged = true
}
}

val oldPath = editor.getPath()
vimDocument.addChangeListener(changeListener)
while (check() && !changeListener.hasChanged && !ifFilePathChanged(editor, oldPath)) {
action.run()
}
vimDocument.removeChangeListener(changeListener)
}

private fun ifFilePathChanged(editor: VimEditor, oldPath: String?): Boolean {
return editor.getPath() != oldPath
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.jetbrains.plugins.ideavim.action.change

import com.intellij.idea.TestFor
import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
Expand All @@ -30,7 +31,8 @@ class UndoActionTest : VimTestCase() {
kotlin.test.assertFalse(editor.caretModel.primaryCaret.hasSelection())
}

// Not yet supported
@Test
@TestFor(issues = ["VIM-696"])
fun `undo after selection`() {
val keys = listOf("v3eld", "u")
val before = """
Expand Down Expand Up @@ -69,30 +71,31 @@ class UndoActionTest : VimTestCase() {
kotlin.test.assertFalse(hasSelection())
}

@Test
fun `test cursor movements do not require additional undo`() {
if (!optionsIjNoEditor().oldundo) {
val keys = listOf("a1<Esc>ea2<Esc>ea3<Esc>", "uu")
val before = """
Lorem Ipsum
${c}Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
val after = """
Lorem Ipsum
I1 found$c it in a legendary land
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
doTest(keys, before, after, Mode.NORMAL())
kotlin.test.assertFalse(hasSelection())
}
}
// @Test
// @TestFor(issues = ["VIM-308"])
// fun `test cursor movements do not require additional undo`() {
// if (!optionsIjNoEditor().oldundo) {
// val keys = listOf("a1<Esc>ea2<Esc>ea3<Esc>", "uu")
// val before = """
// Lorem Ipsum
//
// ${c}Lorem ipsum dolor sit amet,
// consectetur adipiscing elit
// Sed in orci mauris.
// Cras id tellus in ex imperdiet egestas.
// """.trimIndent()
// val after = """
// Lorem Ipsum
//
// I1 found$c it in a legendary land
// consectetur adipiscing elit
// Sed in orci mauris.
// Cras id tellus in ex imperdiet egestas.
// """.trimIndent()
// doTest(keys, before, after, Mode.NORMAL())
// kotlin.test.assertFalse(hasSelection())
// }
// }

private fun hasSelection(): Boolean {
val editor = fixture.editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class SetCommandTest : VimTestCase() {
|nohlsearch noNERDTree showmode virtualedit=
|noideaglobalmode nrformats=hex sidescroll=0 novisualbell
|noideajoin nonumber sidescrolloff=0 visualdelay=100
| ideamarks oldundo nosmartcase whichwrap=b,s
| ideamarks nooldundo nosmartcase whichwrap=b,s
| ideastrictmode norelativenumber startofline wrapscan
| clipboard=ideaput,autoselect,exclude:cons\|linux
| excommandannotation
Expand Down Expand Up @@ -261,7 +261,7 @@ class SetCommandTest : VimTestCase() {
|noNERDTree
| nrformats=hex
|nonumber
| oldundo
|nooldundo
|norelativenumber
|noReplaceWithRegister
| scroll=0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ class SetglobalCommandTest : VimTestCase() {
|nohlsearch noNERDTree showmode virtualedit=
|noideaglobalmode nrformats=hex sidescroll=0 novisualbell
|noideajoin nonumber sidescrolloff=0 visualdelay=100
| ideamarks oldundo nosmartcase whichwrap=b,s
| ideamarks nooldundo nosmartcase whichwrap=b,s
| ideastrictmode norelativenumber startofline wrapscan
| clipboard=ideaput,autoselect,exclude:cons\|linux
| excommandannotation
Expand Down Expand Up @@ -443,7 +443,7 @@ class SetglobalCommandTest : VimTestCase() {
|noNERDTree
| nrformats=hex
|nonumber
| oldundo
|nooldundo
|norelativenumber
|noReplaceWithRegister
| scroll=0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ class SetlocalCommandTest : VimTestCase() {
|noideaglobalmode noNERDTree showmode novisualbell
|--ideajoin nrformats=hex sidescroll=0 visualdelay=100
| ideamarks nonumber sidescrolloff=-1 whichwrap=b,s
| idearefactormode= oldundo nosmartcase wrapscan
| idearefactormode= nooldundo nosmartcase wrapscan
| clipboard=ideaput,autoselect,exclude:cons\|linux
| excommandannotation
| guicursor=n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175
Expand Down Expand Up @@ -481,7 +481,7 @@ class SetlocalCommandTest : VimTestCase() {
|noNERDTree
| nrformats=hex
|nonumber
| oldundo
|nooldundo
|norelativenumber
|noReplaceWithRegister
| scroll=0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
import com.maddyhome.idea.vim.state.VimStateMachine
import com.maddyhome.idea.vim.state.mode.selectionType
Expand All @@ -32,7 +31,6 @@ import com.maddyhome.idea.vim.group.visual.VimSelection.Companion.create
import com.maddyhome.idea.vim.helper.VimNlsSafe
import com.maddyhome.idea.vim.state.mode.mode
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
import java.awt.event.KeyEvent
Expand Down Expand Up @@ -224,13 +222,12 @@ public class ToHandlerMappingInfo(
} else {
startOffset = (startOffset.point - 1).offset
}
val vimSelection = create(startOffset.point, endOffset.point, SelectionType.CHARACTER_WISE, editor)
val vimSelection = create(startOffset.point, endOffset.point, CHARACTER_WISE, editor)
offsets[caret] = vimSelection
SelectionVimListenerSuppressor.lock().use {
// Move caret to the initial offset for better undo action
// This is not a necessary thing, but without it undo action look less convenient
editor.currentCaret().moveToOffset(startOffset.point)
}
// FIXME: what is the comment below about?...
// Move caret to the initial offset for better undo action
// This is not a necessary thing, but without it undo action look less convenient
editor.currentCaret().moveToOffset(startOffset.point)
}
}
if (offsets.isNotEmpty()) {
Expand Down

0 comments on commit a9ba978

Please sign in to comment.