1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-07-05 15:04:33 +02:00

Compare commits

..

24 Commits

Author SHA1 Message Date
e096b803c5
Set plugin version to chylex-48 2025-05-16 18:48:52 +02:00
ba9d89caed
Implement pumvisible() function 2025-05-16 18:47:48 +02:00
a62a356dfb
Make gj/gk jump over soft wraps 2025-05-16 12:39:56 +02:00
5a25c53808
Make camelCase motions adjust based on direction of visual selection 2025-05-16 12:39:56 +02:00
19cd5bf53d
Make search highlights temporary 2025-05-16 12:39:56 +02:00
799a2271bd
Exit insert mode after refactoring 2025-05-16 12:39:56 +02:00
46314beaa7
Add action to run last macro in all opened files 2025-05-16 12:39:56 +02:00
aa0b299d1a
Stop macro execution after a failed search 2025-05-16 12:39:56 +02:00
b5ca0b57fe
Revert per-caret registers 2025-05-16 12:39:56 +02:00
be69de15b4
Apply scrolloff after executing native IDEA actions 2025-05-16 12:39:56 +02:00
d9bb4a581e
Stay on same line after reindenting 2025-05-16 12:39:56 +02:00
4f4ec08958
Update search register when using f/t 2025-05-16 12:39:55 +02:00
b4ed59b08f
Automatically add unambiguous imports after running a macro 2025-05-16 12:39:55 +02:00
c6174f4395
Fix(VIM-3179): Respect virtual space below editor (imperfectly) 2025-05-16 12:39:55 +02:00
b5416da9a4
Fix(VIM-3178): Workaround to support "Jump to Source" action mapping 2025-05-16 12:39:55 +02:00
9474364910
Add support for count for visual and line motion surround 2025-05-16 12:39:55 +02:00
afb7d29871
Fix vim-surround not working with multiple cursors
Fixes multiple cursors with vim-surround commands `cs, ds, S` (but not `ys`).
2025-05-16 12:39:55 +02:00
6afd363731
Fix(VIM-696) Restore visual mode after undo/redo, and disable incompatible actions 2025-05-16 12:39:55 +02:00
0880a78bfe
Respect count with <Action> mappings 2025-05-16 12:39:55 +02:00
e6c506811f
Change matchit plugin to use HTML patterns in unrecognized files 2025-05-16 12:39:55 +02:00
d3142f4574
Reset insert mode when switching active editor 2025-05-16 12:39:55 +02:00
bf54c86622
Remove notifications about configuration options 2025-05-16 12:06:25 +02:00
9aed3c4eb6
Remove update checker 2025-05-16 12:06:25 +02:00
cd3c40c855
Set custom plugin version 2025-05-16 12:06:25 +02:00
75 changed files with 689 additions and 6957 deletions

2
.gitignore vendored
View File

@ -33,5 +33,3 @@ vim-engine/src/main/java/com/maddyhome/idea/vim/regexp/parser/generated
settings.xml settings.xml
.kotlin .kotlin
.claude/settings.local.json

View File

@ -610,10 +610,6 @@ Contributors:
[![icon][github]](https://github.com/vumi19) [![icon][github]](https://github.com/vumi19)
&nbsp; &nbsp;
Mia Vucinic Mia Vucinic
* [![icon][mail]](mailto:canava.thomas@gmail.com)
[![icon][github]](https://github.com/Malandril)
&nbsp;
Thomas Canava
Previous contributors: Previous contributors:

View File

@ -29,8 +29,8 @@ IdeaVim is a Vim engine for JetBrains IDEs.
#### Compatibility #### Compatibility
IntelliJ IDEA, PyCharm, GoLand, CLion, PhpStorm, WebStorm, RubyMine, DataGrip, DataSpell, Rider, Cursive, IntelliJ IDEA, PyCharm, CLion, PhpStorm, WebStorm, RubyMine, DataGrip, GoLand, Rider, Cursive,
Android Studio, and other [JetBrains IDEs](https://www.jetbrains.com/ides/). Android Studio and other IntelliJ platform based IDEs.
Setup Setup
------------ ------------
@ -89,12 +89,35 @@ Here are some examples of supported vim features and commands:
* Full Vim regexps for search and search/replace * Full Vim regexps for search and search/replace
* Vim web help * Vim web help
* `~/.ideavimrc` configuration file * `~/.ideavimrc` configuration file
* Vim script
* IdeaVim plugins [IdeaVim plugins](https://github.com/JetBrains/ideavim/wiki/IdeaVim-Plugins):
* argtextobj
* commentary
* easymotion
* exchange
* FunctionTextObj
* highlightedyank
* indent-object
* matchit.vim
* Mini.ai
* multiple-cursors
* NERDTree
* paragraph-motion
* Peekaboo
* quick-scope
* ReplaceWithRegister
* sneak
* surround
* Switch
* textobj-entire
* Which-Key
See also: See also:
* [Top feature requests and bugs](https://youtrack.jetbrains.com/issues/VIM?q=%23Unresolved+sort+by%3A+votes) * [Top feature requests and bugs](https://youtrack.jetbrains.com/issues/VIM?q=%23Unresolved+sort+by%3A+votes)
* [Vimscript support roadmap](vimscript-info/VIMSCRIPT_ROADMAP.md)
* [List of supported in-build functions](vimscript-info/FUNCTIONS_INFO.MD)
Files Files
----- -----
@ -248,7 +271,8 @@ IdeaVim can execute custom scripts that are written with Vim Script.
At the moment we support all language features, but not all of the built-in functions and options are supported. At the moment we support all language features, but not all of the built-in functions and options are supported.
Additionally, you may be interested in the Additionally, you may be interested in the
[Vim Script Discussion](https://github.com/JetBrains/ideavim/discussions/357). [Vim Script Discussion](https://github.com/JetBrains/ideavim/discussions/357) or
[Vim Script Roadmap](https://github.com/JetBrains/ideavim/blob/master/vimscript-info/VIMSCRIPT_ROADMAP.md).
### IDE specific options ### IDE specific options

View File

@ -51,7 +51,7 @@ buildscript {
classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r") classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
// This is needed for jgit to connect to ssh // This is needed for jgit to connect to ssh
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.1.202505142326-r") classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.0.202503040940-r")
classpath("org.kohsuke:github-api:1.305") classpath("org.kohsuke:github-api:1.305")
classpath("io.ktor:ktor-client-core:3.1.3") classpath("io.ktor:ktor-client-core:3.1.3")
@ -74,7 +74,7 @@ plugins {
// NOTE: Unignore "test block comment falls back to line comment when not available" test // NOTE: Unignore "test block comment falls back to line comment when not available" test
// After changing this version. It supposed to work on the next version of the gradle plugin // After changing this version. It supposed to work on the next version of the gradle plugin
// Or go report to the devs that this test still fails. // Or go report to the devs that this test still fails.
id("org.jetbrains.intellij.platform") version "2.6.0" id("org.jetbrains.intellij.platform") version "2.5.0"
id("org.jetbrains.changelog") version "2.2.1" id("org.jetbrains.changelog") version "2.2.1"
id("org.jetbrains.kotlinx.kover") version "0.6.1" id("org.jetbrains.kotlinx.kover") version "0.6.1"
@ -139,7 +139,7 @@ dependencies {
plugin("AceJump", "3.8.19") plugin("AceJump", "3.8.19")
plugin("com.intellij.classic.ui", "251.23774.318") plugin("com.intellij.classic.ui", "251.23774.318")
bundledPlugins("org.jetbrains.plugins.terminal") bundledPlugins("org.jetbrains.plugins.terminal", "com.intellij.modules.json")
} }
moduleSources(project(":vim-engine", "sourcesJarArtifacts")) moduleSources(project(":vim-engine", "sourcesJarArtifacts"))
@ -161,17 +161,17 @@ dependencies {
// https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin // https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin
testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0") testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.12.2")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.0") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.12.2")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.13.0") testImplementation("org.junit.jupiter:junit-jupiter-params:5.12.2")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0") testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.12.2")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.0") testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.12.2")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.13.0") testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.12.2")
// Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4 // Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4
// Can be removed when IJPL-159134 is fixed // Can be removed when IJPL-159134 is fixed
// testRuntimeOnly("junit:junit:4.13.2") // testRuntimeOnly("junit:junit:4.13.2")
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0") testImplementation("org.junit.vintage:junit-vintage-engine:5.12.2")
// testFixturesImplementation("org.junit.vintage:junit-vintage-engine:5.10.3") // testFixturesImplementation("org.junit.vintage:junit-vintage-engine:5.10.3")
} }
@ -199,9 +199,12 @@ tasks {
useJUnitPlatform() useJUnitPlatform()
// Set teamcity env variable locally to run additional tests for leaks. // Set teamcity env variable locally to run additional tests for leaks.
println("Project leak checks: If you experience project leaks on TeamCity that doesn't reproduce locally") // By default, this test runs on TC only, but this test doesn't take a lot of time,
println("Uncomment the following line in build.gradle to enable leak checks (see build.gradle config)") // so we can turn it on for local development
// environment("TEAMCITY_VERSION" to "X") if (environment["TEAMCITY_VERSION"] == null) {
println("Set env TEAMCITY_VERSION to X to enable project leak checks from the platform")
environment("TEAMCITY_VERSION" to "X")
}
systemProperty("ideavim.nvim.test", System.getProperty("nvim") ?: false) systemProperty("ideavim.nvim.test", System.getProperty("nvim") ?: false)

View File

@ -20,7 +20,7 @@ ideaVersion=2025.1
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type # Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC ideaType=IC
instrumentPluginCode=true instrumentPluginCode=true
version=chylex-49 version=chylex-48
javaVersion=21 javaVersion=21
remoteRobotVersion=0.11.23 remoteRobotVersion=0.11.23
antlrVersion=4.10.1 antlrVersion=4.10.1

View File

@ -30,7 +30,7 @@ dependencies {
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r") implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
// This is needed for jgit to connect to ssh // This is needed for jgit to connect to ssh
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.1.202505142326-r") implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.0.202503040940-r")
implementation("com.vdurmont:semver4j:3.1.0") implementation("com.vdurmont:semver4j:3.1.0")
} }

View File

@ -88,7 +88,7 @@ class VimTypedActionHandler(origHandler: TypedActionHandler) : TypedActionHandle
LOG.info("VimTypedAction '$charTyped': $duration ms") LOG.info("VimTypedAction '$charTyped': $duration ms")
} }
} catch (e: ProcessCanceledException) { } catch (e: ProcessCanceledException) {
throw e // Nothing
} catch (e: Throwable) { } catch (e: Throwable) {
LOG.error(e) LOG.error(e)
} }

View File

@ -59,8 +59,11 @@ import javax.swing.KeyStroke
* *
* *
* These keys are not passed to [com.maddyhome.idea.vim.VimTypedActionHandler] and should be handled by actions. * These keys are not passed to [com.maddyhome.idea.vim.VimTypedActionHandler] and should be handled by actions.
*
* This class is used in Which-Key plugin, so don't make it internal. Generally, we should provide a proper
* way to get ideavim keys for this plugin. See VIM-3085
*/ */
internal class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ { class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ {
init { init {
initInjector() initInjector()
@ -89,10 +92,9 @@ internal class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatib
val duration = System.currentTimeMillis() - start val duration = System.currentTimeMillis() - start
LOG.info("VimShortcut execution '$keyStroke': $duration ms") LOG.info("VimShortcut execution '$keyStroke': $duration ms")
} }
} catch (e: ProcessCanceledException) { } catch (_: ProcessCanceledException) {
// Control-flow exceptions (like ProcessCanceledException) should never be logged and should be rethrown // Control-flow exceptions (like ProcessCanceledException) should never be logged
// See {@link com.intellij.openapi.diagnostic.Logger.checkException} // See {@link com.intellij.openapi.diagnostic.Logger.checkException}
throw e
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
LOG.error(throwable) LOG.error(throwable)
} }
@ -196,6 +198,10 @@ internal class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatib
VimPlugin.getChange().tabAction = true VimPlugin.getChange().tabAction = true
return ActionEnableStatus.no("Tab action in insert mode", LogLevel.INFO) return ActionEnableStatus.no("Tab action in insert mode", LogLevel.INFO)
} }
// Debug watch, Python console, etc.
if (keyStroke in NON_FILE_EDITOR_KEYS && !EditorHelper.isFileEditor(editor)) {
return ActionEnableStatus.no("Non file editor keys", LogLevel.INFO)
}
} }
if (keyStroke in VIM_ONLY_EDITOR_KEYS) { if (keyStroke in VIM_ONLY_EDITOR_KEYS) {
@ -343,6 +349,14 @@ internal class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatib
private const val ACTION_ID = "VimShortcutKeyAction" private const val ACTION_ID = "VimShortcutKeyAction"
private val NON_FILE_EDITOR_KEYS: Set<KeyStroke> = ImmutableSet.builder<KeyStroke>()
.addAll(getKeyStrokes(KeyEvent.VK_ENTER, 0))
.addAll(getKeyStrokes(KeyEvent.VK_ESCAPE, 0))
.addAll(getKeyStrokes(KeyEvent.VK_TAB, 0))
.addAll(getKeyStrokes(KeyEvent.VK_UP, 0))
.addAll(getKeyStrokes(KeyEvent.VK_DOWN, 0))
.build()
private val LOG = logger<VimShortcutKeyAction>() private val LOG = logger<VimShortcutKeyAction>()
@JvmStatic @JvmStatic

View File

@ -1,74 +0,0 @@
/*
* Copyright 2003-2025 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.command
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.state.VimStateMachine
import org.jetbrains.annotations.ApiStatus
@Deprecated("Use `injector.vimState`")
@ApiStatus.ScheduledForRemoval
class CommandState(private val machine: VimStateMachine) {
val mode: Mode
get() {
val myMode = machine.mode
return when (myMode) {
is com.maddyhome.idea.vim.state.mode.Mode.CMD_LINE -> Mode.CMD_LINE
com.maddyhome.idea.vim.state.mode.Mode.INSERT -> Mode.INSERT
is com.maddyhome.idea.vim.state.mode.Mode.NORMAL -> Mode.COMMAND
is com.maddyhome.idea.vim.state.mode.Mode.OP_PENDING -> Mode.OP_PENDING
com.maddyhome.idea.vim.state.mode.Mode.REPLACE -> Mode.REPLACE
is com.maddyhome.idea.vim.state.mode.Mode.SELECT -> Mode.SELECT
is com.maddyhome.idea.vim.state.mode.Mode.VISUAL -> Mode.VISUAL
}
}
@get:Deprecated(
"Use `KeyHandler.keyHandlerState.commandBuilder", ReplaceWith(
"KeyHandler.getInstance().keyHandlerState.commandBuilder",
"com.maddyhome.idea.vim.KeyHandler"
)
)
@get:ApiStatus.ScheduledForRemoval
val commandBuilder: CommandBuilder
get() = KeyHandler.getInstance().keyHandlerState.commandBuilder
@Deprecated(
"Use `KeyHandler.keyHandlerState.mappingState", ReplaceWith(
"KeyHandler.getInstance().keyHandlerState.mappingState",
"com.maddyhome.idea.vim.KeyHandler"
)
)
val mappingState: MappingState
get() = KeyHandler.getInstance().keyHandlerState.mappingState
enum class Mode {
// Basic modes
COMMAND, VISUAL, SELECT, INSERT, CMD_LINE, /*EX*/
// Additional modes
OP_PENDING, REPLACE /*, VISUAL_REPLACE*/, INSERT_NORMAL, INSERT_VISUAL, INSERT_SELECT
}
enum class SubMode {
NONE, VISUAL_CHARACTER, VISUAL_LINE, VISUAL_BLOCK
}
companion object {
@JvmStatic
@Deprecated("Use `injector.vimState`")
@ApiStatus.ScheduledForRemoval
fun getInstance(editor: Editor): CommandState {
return CommandState(injector.vimState)
}
}
}

View File

@ -146,7 +146,7 @@ object VimExtensionFacade {
fun executeNormalWithoutMapping(keys: List<KeyStroke>, editor: Editor) { fun executeNormalWithoutMapping(keys: List<KeyStroke>, editor: Editor) {
val context = injector.executionContextManager.getEditorExecutionContext(editor.vim) val context = injector.executionContextManager.getEditorExecutionContext(editor.vim)
val keyHandler = KeyHandler.getInstance() val keyHandler = KeyHandler.getInstance()
keys.forEach { keyHandler.handleKey(editor.vim, it, context, false, keyHandler.keyHandlerState) } keys.forEach { keyHandler.handleKey(editor.vim, it, context, false, false, keyHandler.keyHandlerState) }
} }
/** Returns a single key stroke from the user input similar to 'getchar()'. */ /** Returns a single key stroke from the user input similar to 'getchar()'. */

View File

@ -89,9 +89,6 @@ internal class MotionGroup : VimMotionGroupBase() {
} }
override fun moveCaretToCurrentDisplayLineStart(editor: VimEditor, caret: ImmutableVimCaret): Motion { override fun moveCaretToCurrentDisplayLineStart(editor: VimEditor, caret: ImmutableVimCaret): Motion {
if (editor.ij.softWrapModel.isSoftWrappingEnabled) {
return AbsoluteOffset(caret.ij.visualLineStart)
}
val col = EditorHelper.getVisualColumnAtLeftOfDisplay(editor.ij, caret.getVisualPosition().line) val col = EditorHelper.getVisualColumnAtLeftOfDisplay(editor.ij, caret.getVisualPosition().line)
return moveCaretToColumn(editor, caret, col, false) return moveCaretToColumn(editor, caret, col, false)
} }
@ -100,15 +97,6 @@ internal class MotionGroup : VimMotionGroupBase() {
editor: VimEditor, editor: VimEditor,
caret: ImmutableVimCaret, caret: ImmutableVimCaret,
): @Range(from = 0, to = Int.MAX_VALUE.toLong()) Int { ): @Range(from = 0, to = Int.MAX_VALUE.toLong()) Int {
if (editor.ij.softWrapModel.isSoftWrappingEnabled) {
val offset = caret.ij.visualLineStart
val line = editor.offsetToBufferPosition(offset).line
return if (offset == editor.getLineStartOffset(line)) {
editor.getLeadingCharacterOffset(line, 0)
} else {
offset
}
}
val col = EditorHelper.getVisualColumnAtLeftOfDisplay(editor.ij, caret.getVisualPosition().line) val col = EditorHelper.getVisualColumnAtLeftOfDisplay(editor.ij, caret.getVisualPosition().line)
val bufferLine = caret.getLine() val bufferLine = caret.getLine()
return editor.getLeadingCharacterOffset(bufferLine, col) return editor.getLeadingCharacterOffset(bufferLine, col)
@ -119,9 +107,6 @@ internal class MotionGroup : VimMotionGroupBase() {
caret: ImmutableVimCaret, caret: ImmutableVimCaret,
allowEnd: Boolean, allowEnd: Boolean,
): Motion { ): Motion {
if (editor.ij.softWrapModel.isSoftWrappingEnabled) {
return AbsoluteOffset(caret.ij.visualLineEnd - 1)
}
val col = EditorHelper.getVisualColumnAtRightOfDisplay(editor.ij, caret.getVisualPosition().line) val col = EditorHelper.getVisualColumnAtRightOfDisplay(editor.ij, caret.getVisualPosition().line)
return moveCaretToColumn(editor, caret, col, allowEnd) return moveCaretToColumn(editor, caret, col, allowEnd)
} }

View File

@ -12,6 +12,7 @@ import com.intellij.icons.AllIcons
import com.intellij.ide.BrowserUtil import com.intellij.ide.BrowserUtil
import com.intellij.ide.actions.OpenFileAction import com.intellij.ide.actions.OpenFileAction
import com.intellij.ide.actions.RevealFileAction import com.intellij.ide.actions.RevealFileAction
import com.intellij.notification.ActionCenter
import com.intellij.notification.Notification import com.intellij.notification.Notification
import com.intellij.notification.NotificationGroup import com.intellij.notification.NotificationGroup
import com.intellij.notification.NotificationGroupManager import com.intellij.notification.NotificationGroupManager
@ -254,7 +255,7 @@ internal class NotificationService(private val project: Project?) {
append("</ul></p>") append("</ul></p>")
} }
} }
} + "<small>See the Notifications tool window for previous IDs</small>" } + "<small>See the ${ActionCenter.getToolwindowName()} tool window for previous IDs</small>"
notification = notification =
Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).also { Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).also {

View File

@ -44,30 +44,11 @@ internal val Editor.isIdeaVimDisabledHere: Boolean
!ClientId.isCurrentlyUnderLocalId || // CWM-927 !ClientId.isCurrentlyUnderLocalId || // CWM-927
(ideaVimDisabledForSingleLine(ideaVimSupportValue) && isSingleLine()) || (ideaVimDisabledForSingleLine(ideaVimSupportValue) && isSingleLine()) ||
IdeaVimDisablerExtensionPoint.isDisabledForEditor(this) || IdeaVimDisablerExtensionPoint.isDisabledForEditor(this) ||
isNotFileEditorExceptAllowed() isAiChat() // VIM-3786
} }
/** private fun Editor.isAiChat(): Boolean {
* Almost every non-file-based editor should not use Vim mode. These editors are debug watch, Python console, AI chats, return EditorHelper.getVirtualFile(this)?.name?.contains("AIAssistantInput") == true
* and other fields that are smart.
*
* We may support IdeaVim in these editors, but this will require a focused work and a lot of testing.
*
* Here are issues when non-file editors were supported:
* AI Chat VIM-3786
* Debug evaluate console VIM-3929
*
* However, we still support IdeaVim in a commit window because it works fine there, and removing vim from this place will
* be quite a visible change for users.
* We detect the commit window by the name of the editor (Dummy.txt). If this causes issues, let's disable IdeaVim
* in the commit window as well.
*
* Also, we support IdeaVim in diff viewers.
*/
private fun Editor.isNotFileEditorExceptAllowed(): Boolean {
if (EditorHelper.getVirtualFile(this)?.name?.contains("Dummy.txt") == true) return false
if (EditorHelper.isDiffEditor(this)) return false
return !EditorHelper.isFileEditor(this)
} }
private fun ideaVimDisabledInDialog(ideaVimSupportValue: StringListOptionValue): Boolean { private fun ideaVimDisabledInDialog(ideaVimSupportValue: StringListOptionValue): Boolean {

View File

@ -35,8 +35,8 @@ import com.maddyhome.idea.vim.api.VimFoldRegion
import com.maddyhome.idea.vim.api.VimIndentConfig import com.maddyhome.idea.vim.api.VimIndentConfig
import com.maddyhome.idea.vim.api.VimScrollingModel import com.maddyhome.idea.vim.api.VimScrollingModel
import com.maddyhome.idea.vim.api.VimSelectionModel import com.maddyhome.idea.vim.api.VimSelectionModel
import com.maddyhome.idea.vim.api.VimVirtualFile
import com.maddyhome.idea.vim.api.VimVisualPosition import com.maddyhome.idea.vim.api.VimVisualPosition
import com.maddyhome.idea.vim.api.VimVirtualFile
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.IndentConfig import com.maddyhome.idea.vim.common.IndentConfig
import com.maddyhome.idea.vim.common.LiveRange import com.maddyhome.idea.vim.common.LiveRange
@ -514,10 +514,6 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
} }
} }
override fun getSoftWrapStartAtOffset(offset: Int): Int? {
return editor.softWrapModel.getSoftWrap(offset)?.start
}
override fun <T : ImmutableVimCaret> findLastVersionOfCaret(caret: T): T { override fun <T : ImmutableVimCaret> findLastVersionOfCaret(caret: T): T {
return caret return caret
} }

View File

@ -15,6 +15,7 @@ import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
/** /**
@ -113,8 +114,10 @@ class ChangeActionTest : VimTestCase() {
) )
} }
// Turn it on after typing via handlers are implemented for tests
// VIM-620 |i_CTRL-O| // VIM-620 |i_CTRL-O|
@Test @Test
@Disabled
fun testInsertSingleCommandAndNewLineInserting8() { fun testInsertSingleCommandAndNewLineInserting8() {
doTest( doTest(
listOf("i", "<C-O>", "gh", "d"), listOf("i", "<C-O>", "gh", "d"),
@ -139,44 +142,24 @@ class ChangeActionTest : VimTestCase() {
// VIM-321 |d| |count| // VIM-321 |d| |count|
@Test @Test
fun testDeleteEmptyRange() { fun testDeleteEmptyRange() {
doTest( doTest("d0", "${c}hello\n", "hello\n", Mode.NORMAL())
"d0",
"${c}hello\n",
"hello\n",
Mode.NORMAL(),
)
} }
// VIM-157 |~| // VIM-157 |~|
@Test @Test
fun testToggleCharCase() { fun testToggleCharCase() {
doTest( doTest("~~", "${c}hello world\n", "HEllo world\n", Mode.NORMAL())
"~~",
"${c}hello world\n",
"HEllo world\n",
Mode.NORMAL(),
)
} }
// VIM-157 |~| // VIM-157 |~|
@Test @Test
fun testToggleCharCaseLineEnd() { fun testToggleCharCaseLineEnd() {
doTest( doTest("~~", "hello wor${c}ld\n", "hello worLD\n", Mode.NORMAL())
"~~",
"hello wor${c}ld\n",
"hello worLD\n",
Mode.NORMAL(),
)
} }
@Test @Test
fun testToggleCaseMotion() { fun testToggleCaseMotion() {
doTest( doTest("g~w", "${c}FooBar Baz\n", "fOObAR Baz\n", Mode.NORMAL())
"g~w",
"${c}FooBar Baz\n",
"fOObAR Baz\n",
Mode.NORMAL(),
)
} }
@Test @Test
@ -191,12 +174,7 @@ class ChangeActionTest : VimTestCase() {
@Test @Test
fun testChangeLowerCase() { fun testChangeLowerCase() {
doTest( doTest("guw", "${c}FooBar Baz\n", "foobar Baz\n", Mode.NORMAL())
"guw",
"${c}FooBar Baz\n",
"foobar Baz\n",
Mode.NORMAL(),
)
} }
@Test @Test
@ -315,14 +293,12 @@ class ChangeActionTest : VimTestCase() {
fun testDeleteLastWordBeforeEOLAndWhitespace() { fun testDeleteLastWordBeforeEOLAndWhitespace() {
doTest( doTest(
"dw", "dw",
""" """one ${c}two
one ${c}two
three three
""".trimIndent(), """,
""" """one
one
three three
""".trimIndent(), """,
Mode.NORMAL(), Mode.NORMAL(),
) )
assertOffset(3) assertOffset(3)
@ -566,16 +542,14 @@ quux
fun testDeleteJoinVisualLinesSpaces() { fun testDeleteJoinVisualLinesSpaces() {
doTest( doTest(
"v2jJ", "v2jJ",
""" """ a$c 1
a$c 1
b 2 b 2
c 3 c 3
quux quux
""".trimIndent(), """,
""" """ a 1 b 2 c 3
a 1 b 2 c 3
quux quux
""".trimIndent(), """,
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@ -685,35 +659,20 @@ quux
// |r| // |r|
@Test @Test
fun testReplaceOneChar() { fun testReplaceOneChar() {
doTest( doTest("rx", "b${c}ar\n", "b${c}xr\n", Mode.NORMAL())
"rx",
"b${c}ar\n",
"b${c}xr\n",
Mode.NORMAL(),
)
} }
// |r| // |r|
@VimBehaviorDiffers(originalVimAfter = "foXX${c}Xr\n") @VimBehaviorDiffers(originalVimAfter = "foXX${c}Xr\n")
@Test @Test
fun testReplaceMultipleCharsWithCount() { fun testReplaceMultipleCharsWithCount() {
doTest( doTest("3rX", "fo${c}obar\n", "fo${c}XXXr\n", Mode.NORMAL())
"3rX",
"fo${c}obar\n",
"fo${c}XXXr\n",
Mode.NORMAL(),
)
} }
// |r| // |r|
@Test @Test
fun testReplaceMultipleCharsWithCountPastEndOfLine() { fun testReplaceMultipleCharsWithCountPastEndOfLine() {
doTest( doTest("6rX", "fo${c}obar\n", "fo${c}obar\n", Mode.NORMAL())
"6rX",
"fo${c}obar\n",
"fo${c}obar\n",
Mode.NORMAL(),
)
} }
// |r| // |r|
@ -741,15 +700,13 @@ quux
fun testReplaceOneCharWithNewline() { fun testReplaceOneCharWithNewline() {
doTest( doTest(
"r<Enter>", "r<Enter>",
""" """ fo${c}obar
fo${c}obar
foobaz foobaz
""".trimIndent(), """,
""" """ fo
fo
bar bar
foobaz foobaz
""".trimIndent(), """,
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@ -760,15 +717,13 @@ quux
fun testReplaceCharWithNewlineAndCountAddsOnlySingleNewline() { fun testReplaceCharWithNewlineAndCountAddsOnlySingleNewline() {
doTest( doTest(
"3r<Enter>", "3r<Enter>",
""" """ fo${c}obar
fo${c}obar
foobaz foobaz
""".trimIndent(), """,
""" """ fo
fo
r r
foobaz foobaz
""".trimIndent(), """,
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@ -776,12 +731,7 @@ quux
// |s| // |s|
@Test @Test
fun testReplaceOneCharWithText() { fun testReplaceOneCharWithText() {
doTest( doTest("sxy<Esc>", "b${c}ar\n", "bx${c}yr\n", Mode.NORMAL())
"sxy<Esc>",
"b${c}ar\n",
"bx${c}yr\n",
Mode.NORMAL(),
)
} }
// |s| // |s|
@ -817,12 +767,7 @@ quux
// |R| // |R|
@Test @Test
fun testReplaceMode() { fun testReplaceMode() {
doTest( doTest("Rbaz<Esc>", "foo${c}bar\n", "fooba${c}z\n", Mode.NORMAL())
"Rbaz<Esc>",
"foo${c}bar\n",
"fooba${c}z\n",
Mode.NORMAL(),
)
} }
// |R| |i_<Insert>| // |R| |i_<Insert>|

View File

@ -284,206 +284,4 @@ class MacroActionTest : VimTestCase() {
assertTrue(KeyHandler.getInstance().keyStack.isEmpty()) assertTrue(KeyHandler.getInstance().keyStack.isEmpty())
} }
// Undo tests for macros
@Test
fun `test undo after simple macro execution`() {
configureByText("${c}Hello world")
typeText(injector.parser.parseKeys("qa" + "dw" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState(c)
// Single undo should restore the state after a simple macro
typeText("u")
assertState("${c}world")
}
@Test
fun `test undo after macro with insert mode`() {
val initialText = "${c}test"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "A" + " added" + "<Esc>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("test added adde${c}d")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "test" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState("test$c")
}
@Test
fun `test undo after executing macro multiple times`() {
val initialText = "${c}one two three four"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "dw" + "q"))
typeText(injector.parser.parseKeys("3@a"))
assertState(c)
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "one two three four" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
// Verify that multiple undos were needed (one for each macro execution)
assertTrue(undoCount == 2, "Expected 2 undos for 2 macro executions, but needed $undoCount")
}
@Test
fun `test undo after nested macro execution`() {
val initialText = "${c}line1\nline2\nline3"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "dd" + "q"))
typeText(injector.parser.parseKeys("qb" + "j@a" + "q"))
typeText(injector.parser.parseKeys("@b"))
assertState("${c}line2")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "line1\nline2\nline3" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
}
@Test
fun `test undo macro with multiple operations`() {
val initialText = "${c}foo bar baz"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "dw" + "A" + "!" + "<Esc>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("bar baz${c}!")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "foo bar baz" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
// Verify that multiple undos were needed for the multiple operations in the macro
assertTrue(undoCount > 1, "Expected multiple undos for macro with multiple operations")
}
@Test
fun `test undo macro with visual mode operations`() {
val initialText = "${c}select this text"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "viw" + "d" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("${c}this text")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "select this text" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
}
@Test
fun `test undo macro with change operation`() {
val initialText = "${c}change(this)"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "ci(" + "that" + "<Esc>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("change(tha${c}t)")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "change(this)" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
}
@Test
fun `test undo after repeating last macro`() {
val initialText = "${c}word1 word2 word3"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "dw" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("${c}word3")
typeText(injector.parser.parseKeys("@@"))
assertState(c)
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "word1 word2 word3" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
// Each macro execution should create its own undo entry
assertTrue(undoCount == 3, "Expected 3 undos for 3 macro executions, but was $undoCount")
}
@Test
fun `test undo macro with ex command`() {
val initialText = "${c}line1\nline2\nline3"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + ":d<CR>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("${c}line3")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "line1\nline2\nline3" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
}
@Test
fun `test undo macro with substitute command`() {
val initialText = "${c}hello world hello"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + ":s/hello/goodbye<CR>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("${c}goodbye world goodbye")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "hello world hello" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
}
@Test
fun `test multiple undo after macro`() {
val initialText = "${c}one two three"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "dw" + "i" + "first " + "<Esc>" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("firstfirst${c} two three")
typeText(injector.parser.parseKeys("w"))
typeText(injector.parser.parseKeys("@a"))
assertState("firstfirst first${c} three")
// Verify that undo can restore the original state
var undoCount = 0
while (fixture.editor.document.text != "one two three" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState(initialText)
// Should need multiple undos since we executed the macro twice
assertTrue(undoCount >= 2, "Expected at least 2 undos for 2 macro executions")
}
@Test
fun `test undo restores cursor position after macro`() {
val initialText = "${c}start middle end"
configureByText(initialText)
typeText(injector.parser.parseKeys("qa" + "w" + "dw" + "q"))
typeText(injector.parser.parseKeys("@a"))
assertState("start en${c}d")
// Verify that undo can restore both text and cursor position
var undoCount = 0
while (fixture.editor.document.text != "start middle end" && undoCount < 10) {
typeText("u")
undoCount++
}
assertState("start ${c}middle end")
}
} }

View File

@ -875,6 +875,15 @@ class MotionActionTest : VimTestCase() {
assertOffset(9) assertOffset(9)
} }
// VIM-965 |[m|
@TestWithoutNeovim(reason = SkipNeovimReason.DIFFERENT, "File type specific")
@Test
fun testMethodMovingInNonJavaFile() {
configureByJsonText("{\"foo\": \"${c}bar\"}\n")
typeText(injector.parser.parseKeys("[m"))
assertState("{\"foo\": \"${c}bar\"}\n")
}
// VIM-331 |w| // VIM-331 |w|
@TestWithoutNeovim(reason = SkipNeovimReason.UNCLEAR) @TestWithoutNeovim(reason = SkipNeovimReason.UNCLEAR)
@Test @Test

View File

@ -18,6 +18,7 @@ import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
@ -1821,6 +1822,7 @@ $c five six se${c}ven eight
) )
} }
@Disabled("Action execution in tests is broken for 2024.2")
@Test @Test
fun testInsertNewLineAboveAction() { fun testInsertNewLineAboveAction() {
typeTextInFile( typeTextInFile(
@ -1847,6 +1849,7 @@ $c five six se${c}ven eight
) )
} }
@Disabled("Action execution in tests is broken for 2024.2")
@VimBehaviorDiffers(originalVimAfter = "${c}\n${c}\nabcde\n${c}\n${c}\nabcde\n") @VimBehaviorDiffers(originalVimAfter = "${c}\n${c}\nabcde\n${c}\n${c}\nabcde\n")
@Test @Test
fun testInsertNewLineAboveActionWithMultipleCaretsInLine() { fun testInsertNewLineAboveActionWithMultipleCaretsInLine() {
@ -1861,6 +1864,7 @@ $c five six se${c}ven eight
assertState("${c}\nabcde\n${c}\nabcde\n") assertState("${c}\nabcde\n${c}\nabcde\n")
} }
@Disabled("Action execution in tests is broken for 2024.2")
@Test @Test
fun testInsertNewLineBelowAction() { fun testInsertNewLineBelowAction() {
typeTextInFile( typeTextInFile(
@ -2181,7 +2185,6 @@ rtyfg${c}hzxc"""
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh") injector.registerGroup.storeText(vimEditor, context, '*', "fgh")
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
VimPlugin.getRegister() VimPlugin.getRegister()
.storeText( .storeText(
@ -2193,7 +2196,6 @@ rtyfg${c}hzxc"""
false false
) )
} }
}
typeText(injector.parser.parseKeys("\"*P")) typeText(injector.parser.parseKeys("\"*P"))
val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn" val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn"
assertState(after) assertState(after)

View File

@ -1,557 +0,0 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package org.jetbrains.plugins.ideavim.action.change
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
/**
* Tests for complex undo scenarios involving motion and change operations
* These tests verify that undo correctly restores both text and cursor position
*/
class ComplexUndoTest : VimTestCase() {
@Test
fun `test undo change inside parentheses with cursor movement`() {
// This is the example from the user's request
configureByText("a${c}bc(xxx)def")
typeText("ci(")
typeText("yyy")
typeText("<Esc>")
assertState("abc(yy${c}y)def")
typeText("u")
assertState("a${c}bc(xxx)def")
}
@Test
fun `test undo change inside parentheses with cursor movement with oldundo`() {
// This is the example from the user's request
configureByText("a${c}bc(xxx)def")
try {
enterCommand("set oldundo")
typeText("ci(")
typeText("yyy")
typeText("<Esc>")
assertState("abc(yy${c}y)def")
typeText("u")
assertState("abc(yyy${c})def")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo delete inside brackets with cursor movement`() {
configureByText("fo${c}o[bar]baz")
typeText("di[")
assertState("foo[${c}]baz")
typeText("u")
assertState("fo${c}o[bar]baz")
}
@Test
fun `test undo delete inside brackets with cursor movement with oldundo`() {
configureByText("fo${c}o[bar]baz")
try {
enterCommand("set oldundo")
typeText("di[")
assertState("foo[${c}]baz")
typeText("u")
assertState("fo${c}o[bar]baz")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change inside quotes with cursor movement`() {
configureByText("Say ${c}hello \"world\" today")
typeText("ci\"")
typeText("universe")
typeText("<Esc>")
assertState("Say hello \"univers${c}e\" today")
typeText("u")
assertState("Say ${c}hello \"world\" today")
}
@Test
fun `test undo change inside quotes with cursor movement with oldundo`() {
configureByText("Say ${c}hello \"world\" today")
try {
enterCommand("set oldundo")
typeText("ci\"")
typeText("universe")
typeText("<Esc>")
assertState("Say hello \"univers${c}e\" today")
typeText("u")
assertState("Say hello \"universe${c}\" today")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo delete word with cursor at different position`() {
configureByText("The qu${c}ick brown fox")
typeText("daw") // Delete a word (including surrounding spaces)
assertState("The ${c}brown fox")
typeText("u")
assertState("The qu${c}ick brown fox")
}
@Test
fun `test undo delete word with cursor at different position with oldundo`() {
configureByText("The qu${c}ick brown fox")
try {
enterCommand("set oldundo")
typeText("daw") // Delete a word (including surrounding spaces)
assertState("The ${c}brown fox")
typeText("u")
assertState("The qu${c}ick brown fox")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change paragraph with cursor movement`() {
configureByText(
"""
First paragraph.
Sec${c}ond paragraph
with multiple lines.
Third paragraph.
""".trimIndent()
)
typeText("cip")
typeText("New content")
typeText("<Esc>")
assertState(
"""
First paragraph.
New conten${c}t
Third paragraph.
""".trimIndent()
)
typeText("u")
assertState(
"""
First paragraph.
Sec${c}ond paragraph
with multiple lines.
Third paragraph.
""".trimIndent()
)
}
@Test
fun `test undo change paragraph with cursor movement with oldundo`() {
configureByText(
"""
First paragraph.
Sec${c}ond paragraph
with multiple lines.
Third paragraph.
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("cip")
typeText("New content")
typeText("<Esc>")
assertState(
"""
First paragraph.
New conten${c}t
Third paragraph.
""".trimIndent()
)
typeText("u")
assertState(
"""
First paragraph.
New content${c}
Third paragraph.
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo delete to search result`() {
configureByText("abc${c}defghijklmnop")
typeText("d/jkl<CR>") // Delete to search result
assertState("abc${c}jklmnop")
typeText("u")
assertState("abc${c}defghijklmnop")
}
@Test
fun `test undo delete to search result with oldundo`() {
configureByText("abc${c}defghijklmnop")
try {
enterCommand("set oldundo")
typeText("d/jkl<CR>") // Delete to search result
assertState("abc${c}jklmnop")
typeText("u")
assertState("abc${c}defghijklmnop")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change to mark with cursor movement`() {
configureByText(
"""
Li${c}ne 1
Line 2
Line 3
Line 4
""".trimIndent()
)
typeText("ma") // Set mark 'a'
typeText("2j") // Move down 2 lines
assertState(
"""
Line 1
Line 2
Li${c}ne 3
Line 4
""".trimIndent()
)
typeText("c'a") // Change to mark 'a'
typeText("Changed")
typeText("<Esc>")
assertState(
"""
Change${c}d
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line 2
Li${c}ne 3
Line 4
""".trimIndent()
)
}
@Test
fun `test undo change to mark with cursor movement with oldundo`() {
configureByText(
"""
Li${c}ne 1
Line 2
Line 3
Line 4
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("ma") // Set mark 'a'
typeText("2j") // Move down 2 lines
assertState(
"""
Line 1
Line 2
Li${c}ne 3
Line 4
""".trimIndent()
)
typeText("c'a") // Change to mark 'a'
typeText("Changed")
typeText("<Esc>")
assertState(
"""
Change${c}d
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Changed${c}
Line 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo substitute with cursor movement`() {
configureByText("${c}Hello world hello")
typeText(":s/hello/goodbye/gi<CR>") // Substitute with flags
assertState("${c}goodbye world goodbye")
typeText("u")
assertState("${c}Hello world hello")
}
@Test
fun `test undo substitute with cursor movement with oldundo`() {
configureByText("${c}Hello world hello")
try {
enterCommand("set oldundo")
typeText(":s/hello/goodbye/gi<CR>") // Substitute with flags
assertState("${c}goodbye world goodbye")
typeText("u")
assertState("${c}Hello world hello")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo multiple operations in sequence`() {
configureByText("${c}abc def ghi")
// First operation: delete word
typeText("dw")
assertState("${c}def ghi")
// Second operation: change word
typeText("cw")
typeText("xyz")
typeText("<Esc>")
assertState("xy${c}z ghi")
// Third operation: append at end
typeText("A")
typeText(" jkl")
typeText("<Esc>")
assertState("xyz ghi jk${c}l")
// Undo all operations
typeText("u")
assertState("xyz ghi${c}")
typeText("u")
assertState("${c}def ghi")
typeText("u")
assertState("${c}abc def ghi")
}
@Test
fun `test undo multiple operations in sequence with oldundo`() {
configureByText("${c}abc def ghi")
try {
enterCommand("set oldundo")
// First operation: delete word
typeText("dw")
assertState("${c}def ghi")
// Second operation: change word
typeText("cw")
typeText("xyz")
typeText("<Esc>")
assertState("xy${c}z ghi")
// Third operation: append at end
typeText("A")
typeText(" jkl")
typeText("<Esc>")
assertState("xyz ghi jk${c}l")
// Undo all operations
typeText("u")
assertState("xyz ghi jkl${c}")
typeText("u")
assertState("xyz ghi${c}")
typeText("u")
assertState("xyz${c} ghi")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo with text objects and counts`() {
configureByText("function(${c}arg1, arg2, arg3)")
typeText("d2f,") // Delete to 2nd comma
assertState("function(${c} arg3)")
typeText("u")
assertState("function(${c}arg1, arg2, arg3)")
}
@Test
fun `test undo with text objects and counts with oldundo`() {
configureByText("function(${c}arg1, arg2, arg3)")
try {
enterCommand("set oldundo")
typeText("d2f,") // Delete to 2nd comma
assertState("function(${c} arg3)")
typeText("u")
assertState("function(${c}arg1, arg2, arg3)")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo inner word at end of word`() {
configureByText("The quic${c}k brown fox")
typeText("diw")
assertState("The ${c} brown fox")
typeText("u")
assertState("The quic${c}k brown fox")
}
@Test
fun `test undo inner word at end of word with oldundo`() {
configureByText("The quic${c}k brown fox")
try {
enterCommand("set oldundo")
typeText("diw")
assertState("The ${c} brown fox")
typeText("u")
assertState("The quic${c}k brown fox")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change with register and motion`() {
configureByText("${c}Hello world")
typeText("\"aciw") // Change inner word into register 'a'
typeText("Goodbye")
typeText("<Esc>")
assertState("Goodby${c}e world")
typeText("u")
assertState("${c}Hello world")
}
@Test
fun `test undo change with register and motion with oldundo`() {
configureByText("${c}Hello world")
try {
enterCommand("set oldundo")
typeText("\"aciw") // Change inner word into register 'a'
typeText("Goodbye")
typeText("<Esc>")
assertState("Goodby${c}e world")
typeText("u")
assertState("Goodbye${c} world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo join with indentation handling`() {
configureByText(
"""
if (condition) {
${c}doSomething();
doMore();
}
""".trimIndent()
)
typeText("J")
assertState(
"""
if (condition) {
doSomething();${c} doMore();
}
""".trimIndent()
)
typeText("u")
assertState(
"""
if (condition) {
${c}doSomething();
doMore();
}
""".trimIndent()
)
}
@Test
fun `test undo join with indentation handling with oldundo`() {
configureByText(
"""
if (condition) {
${c}doSomething();
doMore();
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("J")
assertState(
"""
if (condition) {
doSomething();${c} doMore();
}
""".trimIndent()
)
typeText("u")
assertState(
"""
if (condition) {
${c}doSomething();
doMore();
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo replace mode changes`() {
configureByText("${c}Hello world")
typeText("R")
typeText("Goodbye")
typeText("<Esc>")
assertState("Goodby${c}eorld")
typeText("u")
assertState("${c}Hello world")
}
@Test
fun `test undo replace mode changes with oldundo`() {
configureByText("${c}Hello world")
try {
enterCommand("set oldundo")
typeText("R")
typeText("Goodbye")
typeText("<Esc>")
assertState("Goodby${c}eorld")
typeText("u")
assertState("Goodbye${c}orld")
} finally {
enterCommand("set nooldundo")
}
}
}

View File

@ -9,6 +9,7 @@
package org.jetbrains.plugins.ideavim.action.change package org.jetbrains.plugins.ideavim.action.change
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class OperatorActionTest : VimTestCase() { class OperatorActionTest : VimTestCase() {
@ -153,6 +154,7 @@ class OperatorActionTest : VimTestCase() {
} }
@Test @Test
@Disabled(":set does not correctly parse the quotes in the lambda syntax")
// The parser is treating the second double-quote char as a comment. The argument to the command is parsed as: // The parser is treating the second double-quote char as a comment. The argument to the command is parsed as:
// opfunc={ arg -> execute "`[v`]rx // opfunc={ arg -> execute "`[v`]rx
// The map command is properly handled - the `<CR>g@` is correctly understood, and the full lambda is passed to the // The map command is properly handled - the `<CR>g@` is correctly understood, and the full lambda is passed to the

View File

@ -85,239 +85,4 @@ class ChangeCaseToggleCharacterActionTest : VimTestCase() {
this.enterCommand("set whichwrap=~") this.enterCommand("set whichwrap=~")
} }
} }
@Test
fun `test undo after toggle case single character`() {
configureByText("Hello ${c}World")
typeText("~")
assertState("Hello w${c}orld")
typeText("u")
assertState("Hello ${c}World")
}
@Test
fun `test undo after toggle case single character with oldundo`() {
configureByText("Hello ${c}World")
try {
enterCommand("set oldundo")
typeText("~")
assertState("Hello w${c}orld")
typeText("u")
assertState("Hello ${c}World")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after toggle case multiple characters`() {
configureByText("${c}hello WORLD")
typeText("5~")
assertState("HELLO${c} WORLD")
typeText("u")
assertState("${c}hello WORLD")
}
@Test
fun `test undo after toggle case multiple characters with oldundo`() {
configureByText("${c}hello WORLD")
try {
enterCommand("set oldundo")
typeText("5~")
assertState("HELLO${c} WORLD")
typeText("u")
assertState("${c}hello WORLD")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential toggle case`() {
configureByText("${c}aBc")
typeText("~")
assertState("A${c}Bc")
typeText("~")
assertState("Ab${c}c")
typeText("~")
assertState("Ab${c}C")
// Undo third toggle
typeText("u")
assertState("Ab${c}c")
// Undo second toggle
typeText("u")
assertState("A${c}Bc")
// Undo first toggle
typeText("u")
assertState("${c}aBc")
}
@Test
fun `test multiple undo after sequential toggle case with oldundo`() {
configureByText("${c}aBc")
try {
enterCommand("set oldundo")
typeText("~")
assertState("A${c}Bc")
typeText("~")
assertState("Ab${c}c")
typeText("~")
assertState("Ab${c}C")
// Undo third toggle
typeText("u")
assertState("Ab${c}c")
// Undo second toggle
typeText("u")
assertState("A${c}Bc")
// Undo first toggle
typeText("u")
assertState("${c}aBc")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo toggle case motion`() {
configureByText("${c}hello world")
typeText("g~w")
assertState("${c}HELLO world")
typeText("u")
assertState("${c}hello world")
}
@Test
fun `test undo toggle case motion with oldundo`() {
configureByText("${c}hello world")
try {
enterCommand("set oldundo")
typeText("g~w")
assertState("${c}HELLO world")
typeText("u")
assertState("${c}hello world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo uppercase motion`() {
configureByText("${c}hello world")
typeText("gUw")
assertState("${c}HELLO world")
typeText("u")
assertState("${c}hello world")
}
@Test
fun `test undo uppercase motion with oldundo`() {
configureByText("${c}hello world")
try {
enterCommand("set oldundo")
typeText("gUw")
assertState("${c}HELLO world")
typeText("u")
assertState("${c}hello world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo lowercase motion`() {
configureByText("${c}HELLO WORLD")
typeText("guw")
assertState("${c}hello WORLD")
typeText("u")
assertState("${c}HELLO WORLD")
}
@Test
fun `test undo lowercase motion with oldundo`() {
configureByText("${c}HELLO WORLD")
try {
enterCommand("set oldundo")
typeText("guw")
assertState("${c}hello WORLD")
typeText("u")
assertState("${c}HELLO WORLD")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo toggle case line`() {
configureByText("${c}Hello World")
typeText("g~~")
assertState("${c}hELLO wORLD")
typeText("u")
assertState("${c}Hello World")
}
@Test
fun `test undo toggle case line with oldundo`() {
configureByText("${c}Hello World")
try {
enterCommand("set oldundo")
typeText("g~~")
assertState("${c}hELLO wORLD")
typeText("u")
assertState("${c}Hello World")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo uppercase line`() {
configureByText("${c}Hello World")
typeText("gUU")
assertState("${c}HELLO WORLD")
typeText("u")
assertState("${c}Hello World")
}
@Test
fun `test undo uppercase line with oldundo`() {
configureByText("${c}Hello World")
try {
enterCommand("set oldundo")
typeText("gUU")
assertState("${c}HELLO WORLD")
typeText("u")
assertState("${c}Hello World")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo lowercase line`() {
configureByText("${c}HELLO WORLD")
typeText("guu")
assertState("${c}hello world")
typeText("u")
assertState("${c}HELLO WORLD")
}
@Test
fun `test undo lowercase line with oldundo`() {
configureByText("${c}HELLO WORLD")
try {
enterCommand("set oldundo")
typeText("guu")
assertState("${c}hello world")
typeText("u")
assertState("${c}HELLO WORLD")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -12,6 +12,7 @@ package org.jetbrains.plugins.ideavim.action.change.change
import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class ChangeMotionActionTest : VimTestCase() { class ChangeMotionActionTest : VimTestCase() {
@ -149,7 +150,9 @@ class ChangeMotionActionTest : VimTestCase() {
} }
// VIM-276 |c| |F| // VIM-276 |c| |F|
@Suppress("unused")
@Test @Test
@Disabled
fun testChangeLinesToBackwards() { fun testChangeLinesToBackwards() {
doTest( doTest(
"cFc", "cFc",
@ -205,280 +208,4 @@ class ChangeMotionActionTest : VimTestCase() {
""".trimIndent() """.trimIndent()
) )
} }
@Test
fun `test undo after change word`() {
configureByText("Hello ${c}world and more")
typeText("cw")
typeText("Vim")
typeText("<Esc>")
assertState("Hello Vi${c}m and more")
typeText("u")
assertState("Hello ${c}world and more")
}
@Test
fun `test undo after change word with oldundo`() {
configureByText("Hello ${c}world and more")
try {
enterCommand("set oldundo")
typeText("cw")
typeText("Vim")
typeText("<Esc>")
assertState("Hello Vi${c}m and more")
typeText("u")
assertState("Hello Vim${c} and more")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after change line`() {
configureByText(
"""
First line
${c}Second line with text
Third line
""".trimIndent()
)
typeText("cc")
typeText("Changed line")
typeText("<Esc>")
assertState(
"""
First line
Changed lin${c}e
Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line with text
Third line
""".trimIndent()
)
}
@Test
fun `test undo after change line with oldundo`() {
configureByText(
"""
First line
${c}Second line with text
Third line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("cc")
typeText("Changed line")
typeText("<Esc>")
assertState(
"""
First line
Changed lin${c}e
Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
Changed line${c}
Third line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after change to end of line`() {
configureByText("Start ${c}middle end")
typeText("C")
typeText("new ending")
typeText("<Esc>")
assertState("Start new endin${c}g")
typeText("u")
assertState("Start ${c}middle end")
}
@Test
fun `test undo after change to end of line with oldundo`() {
configureByText("Start ${c}middle end")
try {
enterCommand("set oldundo")
typeText("C")
typeText("new ending")
typeText("<Esc>")
assertState("Start new endin${c}g")
typeText("u")
assertState("Start new ending${c}")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after change with motion`() {
configureByText("The ${c}quick brown fox")
typeText("c3w")
typeText("slow")
typeText("<Esc>")
assertState("The slo${c}w")
typeText("u")
assertState("The ${c}quick brown fox")
}
@Test
fun `test undo after change with motion with oldundo`() {
configureByText("The ${c}quick brown fox")
try {
enterCommand("set oldundo")
typeText("c3w")
typeText("slow")
typeText("<Esc>")
assertState("The slo${c}w")
typeText("u")
assertState("The slow${c}")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change with motion and caret movement`() {
configureByText("a${c}bc(xxx)def")
typeText("ci(")
typeText("yyy")
typeText("<Esc>")
assertState("abc(yy${c}y)def")
typeText("u")
assertState("a${c}bc(xxx)def")
}
@Test
fun `test undo change with motion and caret movement with oldundo`() {
configureByText("a${c}bc(xxx)def")
try {
enterCommand("set oldundo")
typeText("ci(")
typeText("yyy")
typeText("<Esc>")
assertState("abc(yy${c}y)def")
typeText("u")
assertState("abc(yyy${c})def")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential changes`() {
configureByText("${c}one two three")
typeText("cw")
typeText("ONE")
typeText("<Esc>")
assertState("ON${c}E two three")
typeText("w")
typeText("cw")
typeText("TWO")
typeText("<Esc>")
assertState("ONE TW${c}O three")
// Undo second change
typeText("u")
assertState("ONE ${c}two three")
// Undo first change
typeText("u")
assertState("${c}one two three")
}
@Test
fun `test multiple undo after sequential changes with oldundo`() {
configureByText("${c}one two three")
try {
enterCommand("set oldundo")
typeText("cw")
typeText("ONE")
typeText("<Esc>")
assertState("ON${c}E two three")
typeText("w")
typeText("cw")
typeText("TWO")
typeText("<Esc>")
assertState("ONE TW${c}O three")
// Undo second change
typeText("u")
assertState("ONE TWO${c} three")
// Undo first change
typeText("u")
assertState("ONE ${c} three")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change character`() {
configureByText("a${c}bcdef")
typeText("s")
typeText("X")
typeText("<Esc>")
assertState("a${c}Xcdef")
typeText("u")
assertState("a${c}bcdef")
}
@Test
fun `test undo change character with oldundo`() {
configureByText("a${c}bcdef")
try {
enterCommand("set oldundo")
typeText("s")
typeText("X")
typeText("<Esc>")
assertState("a${c}Xcdef")
typeText("u")
assertState("aX${c}cdef")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo change multiple characters`() {
configureByText("abc${c}defghijk")
typeText("3s")
typeText("XXX")
typeText("<Esc>")
assertState("abcXX${c}Xghijk")
typeText("u")
assertState("abc${c}defghijk")
}
@Test
fun `test undo change multiple characters with oldundo`() {
configureByText("abc${c}defghijk")
try {
enterCommand("set oldundo")
typeText("3s")
typeText("XXX")
typeText("<Esc>")
assertState("abcXX${c}Xghijk")
typeText("u")
assertState("abcXXX${c}ghijk")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -47,245 +47,4 @@ class ChangeNumberDecActionTest : VimTestCase() {
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@Test
fun `test undo after decrement number`() {
configureByText("The answer is ${c}42")
typeText("<C-X>")
assertState("The answer is 4${c}1")
typeText("u")
assertState("The answer is ${c}42")
}
@Test
fun `test undo after decrement number with oldundo`() {
configureByText("The answer is ${c}42")
try {
enterCommand("set oldundo")
typeText("<C-X>")
assertState("The answer is 4${c}1")
typeText("u")
assertState("The answer is ${c}42")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after decrement number with caret move`() {
configureByText("The answer ${c}is 42")
typeText("<C-X>")
assertState("The answer is 4${c}1")
typeText("u")
assertState("The answer ${c}is 42")
}
@Test
fun `test undo after decrement number with caret move with oldundo`() {
configureByText("The answer ${c}is 42")
try {
enterCommand("set oldundo")
typeText("<C-X>")
assertState("The answer is 4${c}1")
typeText("u")
assertState("The answer ${c}is 42")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after decrement with count`() {
configureByText("Count: ${c}20")
typeText("5<C-X>")
assertState("Count: 1${c}5")
typeText("u")
assertState("Count: ${c}20")
}
@Test
fun `test undo after decrement with count with oldundo`() {
configureByText("Count: ${c}20")
try {
enterCommand("set oldundo")
typeText("5<C-X>")
assertState("Count: 1${c}5")
typeText("u")
assertState("Count: ${c}20")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after decrement negative number`() {
configureByText("Temperature: ${c}-5 degrees")
typeText("<C-X>")
assertState("Temperature: -${c}6 degrees")
typeText("u")
assertState("Temperature: ${c}-5 degrees")
}
@Test
fun `test undo after decrement negative number with oldundo`() {
configureByText("Temperature: ${c}-5 degrees")
try {
enterCommand("set oldundo")
typeText("<C-X>")
assertState("Temperature: -${c}6 degrees")
typeText("u")
assertState("Temperature: ${c}-5 degrees")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential decrements`() {
configureByText("Value: ${c}100")
typeText("<C-X>")
assertState("Value: 9${c}9")
typeText("<C-X>")
assertState("Value: 9${c}8")
typeText("<C-X>")
assertState("Value: 9${c}7")
// Undo third decrement
typeText("u")
assertState("Value: 9${c}8")
// Undo second decrement
typeText("u")
assertState("Value: 9${c}9")
// Undo first decrement
typeText("u")
assertState("Value: ${c}100")
}
@Test
fun `test multiple undo after sequential decrements with oldundo`() {
configureByText("Value: ${c}100")
try {
enterCommand("set oldundo")
typeText("<C-X>")
assertState("Value: 9${c}9")
typeText("<C-X>")
assertState("Value: 9${c}8")
typeText("<C-X>")
assertState("Value: 9${c}7")
// Undo third decrement
typeText("u")
assertState("Value: 9${c}8")
// Undo second decrement
typeText("u")
assertState("Value: 9${c}9")
// Undo first decrement
typeText("u")
assertState("Value: ${c}100")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo decrement with visual selection`() {
configureByText("""
${c}10
20
30
""".trimIndent())
typeText("Vj<C-X>") // Visual select first two lines and decrement
assertState("""
${c}9
19
30
""".trimIndent())
typeText("u")
assertState("""
${c}10
20
30
""".trimIndent())
}
@Test
fun `test undo decrement with visual selection with oldundo`() {
configureByText("""
${c}10
20
30
""".trimIndent())
try {
enterCommand("set oldundo")
typeText("Vj<C-X>") // Visual select first two lines and decrement
assertState("""
${c}9
19
30
""".trimIndent())
typeText("u")
assertState("""
${c}10
20
30
""".trimIndent())
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo increment and decrement combination`() {
configureByText("Number: ${c}50")
typeText("<C-A>")
assertState("Number: 5${c}1")
typeText("<C-X>")
assertState("Number: 5${c}0")
typeText("<C-X>")
assertState("Number: 4${c}9")
// Undo second decrement
typeText("u")
assertState("Number: 5${c}0")
// Undo first decrement
typeText("u")
assertState("Number: 5${c}1")
// Undo increment
typeText("u")
assertState("Number: ${c}50")
}
@Test
fun `test undo increment and decrement combination with oldundo`() {
configureByText("Number: ${c}50")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("Number: 5${c}1")
typeText("<C-X>")
assertState("Number: 5${c}0")
typeText("<C-X>")
assertState("Number: 4${c}9")
// Undo second decrement
typeText("u")
assertState("Number: 5${c}0")
// Undo first decrement
typeText("u")
assertState("Number: 5${c}1")
// Undo increment
typeText("u")
assertState("Number: ${c}50")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -19,231 +19,4 @@ class ChangeNumberIncActionTest : VimTestCase() {
fun `test inc fancy number`() { fun `test inc fancy number`() {
doTest("<C-A>", "1${c}0X0", "10X1", Mode.NORMAL()) doTest("<C-A>", "1${c}0X0", "10X1", Mode.NORMAL())
} }
@Test
fun `test undo after increment number`() {
configureByText("The answer is ${c}42")
typeText("<C-A>")
assertState("The answer is 4${c}3")
typeText("u")
assertState("The answer is ${c}42")
}
@Test
fun `test undo after increment number with oldundo`() {
configureByText("The answer is ${c}42")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("The answer is 4${c}3")
typeText("u")
assertState("The answer is ${c}42")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after increment with count`() {
configureByText("Count: ${c}10")
typeText("5<C-A>")
assertState("Count: 1${c}5")
typeText("u")
assertState("Count: ${c}10")
}
@Test
fun `test undo after increment with count with oldundo`() {
configureByText("Count: ${c}10")
try {
enterCommand("set oldundo")
typeText("5<C-A>")
assertState("Count: 1${c}5")
typeText("u")
assertState("Count: ${c}10")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after increment negative number`() {
configureByText("Temperature: ${c}-5 degrees")
typeText("<C-A>")
assertState("Temperature: -${c}4 degrees")
typeText("u")
assertState("Temperature: ${c}-5 degrees")
}
@Test
fun `test undo after increment negative number with oldundo`() {
configureByText("Temperature: ${c}-5 degrees")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("Temperature: -${c}4 degrees")
typeText("u")
assertState("Temperature: ${c}-5 degrees")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential increments`() {
configureByText("Value: ${c}100")
typeText("<C-A>")
assertState("Value: 10${c}1")
typeText("<C-A>")
assertState("Value: 10${c}2")
typeText("<C-A>")
assertState("Value: 10${c}3")
// Undo third increment
typeText("u")
assertState("Value: 10${c}2")
// Undo second increment
typeText("u")
assertState("Value: 10${c}1")
// Undo first increment
typeText("u")
assertState("Value: ${c}100")
}
@Test
fun `test multiple undo after sequential increments with oldundo`() {
configureByText("Value: ${c}100")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("Value: 10${c}1")
typeText("<C-A>")
assertState("Value: 10${c}2")
typeText("<C-A>")
assertState("Value: 10${c}3")
// Undo third increment
typeText("u")
assertState("Value: 10${c}2")
// Undo second increment
typeText("u")
assertState("Value: 10${c}1")
// Undo first increment
typeText("u")
assertState("Value: ${c}100")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo increment with visual selection`() {
configureByText(
"""
${c}10
20
30
""".trimIndent()
)
typeText("Vj<C-A>") // Visual select first two lines and increment
assertState(
"""
${c}11
21
30
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}10
20
30
""".trimIndent()
)
}
@Test
fun `test undo increment with visual selection with oldundo`() {
configureByText(
"""
${c}10
20
30
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("Vj<C-A>") // Visual select first two lines and increment
assertState(
"""
${c}11
21
30
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}10
20
30
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo increment octal number`() {
// OCT is disabled by default
configureByText("Octal: ${c}0777")
typeText("<C-A>")
assertState("Octal: 077${c}8")
typeText("u")
assertState("Octal: ${c}0777")
}
@Test
fun `test undo increment octal number with oldundo`() {
// OCT is disabled by default
configureByText("Octal: ${c}0777")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("Octal: 077${c}8")
typeText("u")
assertState("Octal: ${c}0777")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo increment hex number`() {
configureByText("Hex: ${c}0xff")
typeText("<C-A>")
assertState("Hex: 0x10${c}0")
typeText("u")
assertState("Hex: ${c}0xff")
}
@Test
fun `test undo increment hex number with oldundo`() {
configureByText("Hex: ${c}0xff")
try {
enterCommand("set oldundo")
typeText("<C-A>")
assertState("Hex: 0x10${c}0")
typeText("u")
assertState("Hex: ${c}0xff")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -130,81 +130,4 @@ class DeleteCharacterLeftActionTest : VimTestCase() {
assertVisualPosition(0, 55) assertVisualPosition(0, 55)
assertVisibleLineBounds(0, 15, 94) assertVisibleLineBounds(0, 15, 94)
} }
@Test
fun `test undo after deleting character left`() {
configureByText("foo f${c}oo")
typeText("X")
assertState("foo ${c}oo")
typeText("u")
assertState("foo f${c}oo")
}
@Test
fun `test undo after deleting character left with oldundo`() {
configureByText("foo f${c}oo")
try {
enterCommand("set oldundo")
typeText("X")
assertState("foo ${c}oo")
typeText("u")
assertState("foo f${c}oo")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after deleting multiple characters left`() {
configureByText("abcdef${c}ghijk")
typeText("3X")
assertState("abc${c}ghijk")
typeText("u")
assertState("abcdef${c}ghijk")
}
@Test
fun `test undo after deleting multiple characters left with oldundo`() {
configureByText("abcdef${c}ghijk")
try {
enterCommand("set oldundo")
typeText("3X")
assertState("abc${c}ghijk")
typeText("u")
assertState("abcdef${c}ghijk")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential deletes`() {
configureByText("foo bar ${c}baz")
typeText("XXX")
assertState("foo b${c}baz")
typeText("u")
assertState("foo ba${c}baz")
typeText("u")
assertState("foo bar${c}baz")
typeText("u")
assertState("foo bar ${c}baz")
}
@Test
fun `test multiple undo after sequential deletes with oldundo`() {
configureByText("foo bar ${c}baz")
try {
enterCommand("set oldundo")
typeText("XXX")
assertState("foo b${c}baz")
typeText("u")
assertState("foo ba${c}baz")
typeText("u")
assertState("foo bar${c}baz")
typeText("u")
assertState("foo bar ${c}baz")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -113,31 +113,4 @@ class DeleteCharacterRightActionTest : VimTestCase() {
// type annotation // type annotation
assertVisualPosition(0, 4) assertVisualPosition(0, 4)
} }
@Test
fun `undo after deleting character`() {
configureByText("foo ${c}foo")
typeText("xx")
assertState("foo ${c}o")
typeText("u")
assertState("foo ${c}oo")
typeText("u")
assertState("foo ${c}foo")
}
@Test
fun `undo after deleting character with oldundo`() {
configureByText("foo ${c}foo")
try {
enterCommand("set oldundo")
typeText("xx")
assertState("foo ${c}o")
typeText("u")
assertState("foo ${c}oo")
typeText("u")
assertState("foo ${c}foo")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -32,230 +32,4 @@ class DeleteEndOfLineActionTest : VimTestCase() {
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@Test
fun `test undo after delete to end of line`() {
configureByText("Hello ${c}world and more text")
typeText("D")
assertState("Hello$c ")
typeText("u")
assertState("Hello ${c}world and more text")
}
@Test
fun `test undo after delete to end of line with count`() {
configureByText(
"""
First ${c}line with text
Second line
Third line
Fourth line
""".trimIndent()
)
typeText("2D")
assertState(
"""
First$c
Third line
Fourth line
""".trimIndent()
)
typeText("u")
assertState(
"""
First ${c}line with text
Second line
Third line
Fourth line
""".trimIndent()
)
}
@Test
fun `test undo after delete to end of line at different positions`() {
configureByText("abc${c}defghijk")
typeText("D")
assertState("ab${c}c")
typeText("u")
assertState("abc${c}defghijk")
// Move to different position and delete again
typeText("0")
assertState("${c}abcdefghijk")
typeText("D")
assertState("$c")
typeText("u")
assertState("${c}abcdefghijk")
}
@Test
fun `test multiple undo after sequential delete to end of line`() {
configureByText(
"""
${c}First line
Second line
Third line
""".trimIndent()
)
typeText("D")
assertState(
"""
$c
Second line
Third line
""".trimIndent()
)
typeText("j")
typeText("D")
assertState(
"""
$c
Third line
""".trimIndent()
)
// Undo second delete
typeText("u")
assertState(
"""
${c}Second line
Third line
""".trimIndent()
)
// Undo first delete
typeText("u")
assertState(
"""
${c}First line
Second line
Third line
""".trimIndent()
)
}
@Test
fun `test undo after delete to end of line with oldundo`() {
configureByText("Hello ${c}world and more text")
try {
enterCommand("set oldundo")
typeText("D")
assertState("Hello$c ")
typeText("u")
assertState("Hello ${c}world and more text")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete to end of line with count with oldundo`() {
configureByText(
"""
First ${c}line with text
Second line
Third line
Fourth line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("2D")
assertState(
"""
First$c
Third line
Fourth line
""".trimIndent()
)
typeText("u")
assertState(
"""
First ${c}line with text
Second line
Third line
Fourth line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete to end of line at different positions with oldundo`() {
configureByText("abc${c}defghijk")
try {
enterCommand("set oldundo")
typeText("D")
assertState("ab${c}c")
typeText("u")
assertState("abc${c}defghijk")
// Move to different position and delete again
typeText("0")
assertState("${c}abcdefghijk")
typeText("D")
assertState("$c")
typeText("u")
assertState("${c}abcdefghijk")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential delete to end of line with oldundo`() {
configureByText(
"""
${c}First line
Second line
Third line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("D")
assertState(
"""
$c
Second line
Third line
""".trimIndent()
)
typeText("j")
typeText("D")
assertState(
"""
$c
Third line
""".trimIndent()
)
// Undo second delete
typeText("u")
assertState(
"""
${c}Second line
Third line
""".trimIndent()
)
// Undo first delete
typeText("u")
assertState(
"""
${c}
Second line
Third line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -16,7 +16,6 @@ import org.jetbrains.plugins.ideavim.VimTestCase
import org.jetbrains.plugins.ideavim.impl.OptionTest import org.jetbrains.plugins.ideavim.impl.OptionTest
import org.jetbrains.plugins.ideavim.impl.TraceOptions import org.jetbrains.plugins.ideavim.impl.TraceOptions
import org.jetbrains.plugins.ideavim.impl.VimOption import org.jetbrains.plugins.ideavim.impl.VimOption
import org.junit.jupiter.api.Test
@TraceOptions @TraceOptions
class DeleteJoinLinesSpacesActionTest : VimTestCase() { class DeleteJoinLinesSpacesActionTest : VimTestCase() {
@ -89,280 +88,4 @@ class DeleteJoinLinesSpacesActionTest : VimTestCase() {
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@Test
fun `test undo after join lines`() {
configureByText(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
typeText("J")
assertState(
"""
First line
Second line${c} Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
}
@Test
fun `test undo after join multiple lines`() {
configureByText(
"""
${c}Line 1
Line 2
Line 3
Line 4
""".trimIndent()
)
typeText("3J")
assertState(
"""
Line 1 Line 2$c Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}Line 1
Line 2
Line 3
Line 4
""".trimIndent()
)
}
@Test
fun `test undo after multiple sequential joins`() {
configureByText(
"""
${c}One
Two
Three
Four
""".trimIndent()
)
typeText("J")
assertState(
"""
One${c} Two
Three
Four
""".trimIndent()
)
typeText("J")
assertState(
"""
One Two${c} Three
Four
""".trimIndent()
)
// Undo second join
typeText("u")
assertState(
"""
One${c} Two
Three
Four
""".trimIndent()
)
// Undo first join
typeText("u")
assertState(
"""
${c}One
Two
Three
Four
""".trimIndent()
)
}
@Test
fun `test undo join with special whitespace handling`() {
configureByText(
"""
${c}foo {
bar
}
""".trimIndent()
)
typeText("J")
assertState(
"""
foo {${c} bar
}
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}foo {
bar
}
""".trimIndent()
)
}
@Test
fun `test undo after join lines with oldundo`() {
configureByText(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("J")
assertState(
"""
First line
Second line${c} Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after join multiple lines with oldundo`() {
configureByText(
"""
${c}Line 1
Line 2
Line 3
Line 4
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("3J")
assertState(
"""
Line 1 Line 2$c Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}Line 1
Line 2
Line 3
Line 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after multiple sequential joins with oldundo`() {
configureByText(
"""
${c}One
Two
Three
Four
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("J")
assertState(
"""
One${c} Two
Three
Four
""".trimIndent()
)
typeText("J")
assertState(
"""
One Two${c} Three
Four
""".trimIndent()
)
// Undo second join
typeText("u")
assertState(
"""
One${c} Two
Three
Four
""".trimIndent()
)
// Undo first join
typeText("u")
assertState(
"""
${c}One
Two
Three
Four
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo join with special whitespace handling with oldundo`() {
configureByText(
"""
${c}foo {
bar
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("J")
assertState(
"""
foo {${c} bar
}
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}foo {
bar
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -257,298 +257,4 @@ class DeleteMotionActionTest : VimTestCase() {
typeText("dd") typeText("dd")
assertStatusLineCleared() assertStatusLineCleared()
} }
@Test
fun `test undo after delete motion with word`() {
configureByText("Hello ${c}world and more text")
typeText("dw")
assertState("Hello ${c}and more text")
typeText("u")
assertState("Hello ${c}world and more text")
}
@Test
fun `test undo after delete motion with word with oldundo`() {
configureByText("Hello ${c}world and more text")
try {
enterCommand("set oldundo")
typeText("dw")
assertState("Hello ${c}and more text")
typeText("u")
assertState("Hello ${c}world and more text")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete line`() {
configureByText(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
typeText("dd")
assertState(
"""
First line
${c}Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
}
@Test
fun `test undo after delete line with oldundo`() {
configureByText(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("dd")
assertState(
"""
First line
${c}Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete multiple lines`() {
configureByText(
"""
First line
${c}Second line
Third line
Fourth line
Fifth line
""".trimIndent()
)
typeText("3dd")
assertState(
"""
First line
${c}Fifth line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
Fourth line
Fifth line
""".trimIndent()
)
}
@Test
fun `test undo after delete multiple lines with oldundo`() {
configureByText(
"""
First line
${c}Second line
Third line
Fourth line
Fifth line
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("3dd")
assertState(
"""
First line
${c}Fifth line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
${c}Second line
Third line
Fourth line
Fifth line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete with different motions`() {
configureByText("The ${c}quick brown fox jumps")
typeText("d3w")
assertState("The ${c}jumps")
typeText("u")
assertState("The ${c}quick brown fox jumps")
// Test with $ motion
typeText("d$")
assertState("The$c ")
typeText("u")
assertState("The ${c}quick brown fox jumps")
// Test with 0 motion
typeText("d0")
assertState("${c}quick brown fox jumps")
typeText("u")
assertState("The ${c}quick brown fox jumps")
}
@Test
fun `test undo after delete with different motions with oldundo`() {
configureByText("The ${c}quick brown fox jumps")
try {
enterCommand("set oldundo")
typeText("d3w")
assertState("The ${c}jumps")
typeText("u")
assertState("The ${c}quick brown fox jumps")
// Test with $ motion
typeText("d$")
assertState("The$c ")
typeText("u")
assertState("The ${c}quick brown fox jumps")
// Test with 0 motion
typeText("d0")
assertState("${c}quick brown fox jumps")
typeText("u")
assertState("The ${c}quick brown fox jumps")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo delete with motion that includes caret movement`() {
configureByText("a${c}bc(xxx)def")
typeText("di(")
assertState("abc(${c})def")
typeText("u")
assertState("a${c}bc(xxx)def")
}
@Test
fun `test undo delete with motion that includes caret movement with oldundo`() {
configureByText("a${c}bc(xxx)def")
try {
enterCommand("set oldundo")
typeText("di(")
assertState("abc(${c})def")
typeText("u")
assertState("a${c}bc(xxx)def")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after delete to mark`() {
configureByText(
"""
Line 1
Li${c}ne 2
Line 3
Line 4
""".trimIndent()
)
typeText("ma") // Set mark a
typeText("jj")
assertState(
"""
Line 1
Line 2
Line 3
Li${c}ne 4
""".trimIndent()
)
typeText("d'a") // Delete to mark a
assertState(
"""
${c}Line 1
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line 2
Line 3
Li${c}ne 4
""".trimIndent()
)
}
@Test
fun `test undo after delete to mark with oldundo`() {
configureByText(
"""
Line 1
Li${c}ne 2
Line 3
Line 4
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("ma") // Set mark a
typeText("jj")
assertState(
"""
Line 1
Line 2
Line 3
Li${c}ne 4
""".trimIndent()
)
typeText("d'a") // Delete to mark a
assertState(
"""
${c}Line 1
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line 2
Line 3
Li${c}ne 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -52,76 +52,4 @@ class InsertDeleteInsertedTextActionTest : VimTestCase() {
Mode.NORMAL(), Mode.NORMAL(),
) )
} }
@Test
fun `test undo after delete inserted text in insert mode`() {
configureByText("Hello ${c}world")
typeText("i")
typeText("beautiful ")
assertState("Hello beautiful ${c}world")
assertMode(Mode.INSERT)
typeText("<C-U>")
assertState("Hello ${c}world")
assertMode(Mode.INSERT)
typeText("<Esc>")
typeText("u")
assertState("Hello ${c}world")
}
@Test
fun `test undo after delete inserted text in insert mode with oldundo`() {
configureByText("Hello ${c}world")
try {
enterCommand("set oldundo")
typeText("i")
typeText("beautiful ")
assertState("Hello beautiful ${c}world")
assertMode(Mode.INSERT)
typeText("<C-U>")
assertState("Hello ${c}world")
assertMode(Mode.INSERT)
typeText("<Esc>")
typeText("u")
assertState("Hello ${c}world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo preserves text before insertion point`() {
configureByText("Start${c}End")
typeText("i")
typeText(" Middle ")
assertState("Start Middle ${c}End")
assertMode(Mode.INSERT)
typeText("<C-U>")
assertState("Start${c}End")
assertMode(Mode.INSERT)
typeText("<Esc>")
assertState("Star${c}tEnd")
typeText("u")
assertState("Start${c}End")
}
@Test
fun `test undo preserves text before insertion point with oldundo`() {
configureByText("Start${c}End")
try {
enterCommand("set oldundo")
typeText("i")
typeText(" Middle ")
assertState("Start Middle ${c}End")
assertMode(Mode.INSERT)
typeText("<C-U>")
assertState("Start${c}End")
assertMode(Mode.INSERT)
typeText("<Esc>")
assertState("Star${c}tEnd")
typeText("u")
assertState("Start${c}End")
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -15,6 +15,7 @@ import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.SkipNeovimReason import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -84,6 +85,7 @@ class InsertNewLineAboveActionTest : VimTestCase() {
doTest("O", before, after, Mode.INSERT) doTest("O", before, after, Mode.INSERT)
} }
@Disabled("Action execution in tests is broken for 2024.2")
@Test @Test
fun `test insert new line above with multiple carets`() { fun `test insert new line above with multiple carets`() {
val before = """ I fou${c}nd it in a legendary land val before = """ I fou${c}nd it in a legendary land

View File

@ -12,6 +12,7 @@ import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.SkipNeovimReason import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class InsertNewLineBelowActionTest : VimTestCase() { class InsertNewLineBelowActionTest : VimTestCase() {
@ -79,6 +80,7 @@ class InsertNewLineBelowActionTest : VimTestCase() {
doTest("o", before, after, Mode.INSERT) doTest("o", before, after, Mode.INSERT)
} }
@Disabled("Action execution in tests is broken for 2024.2")
@Test @Test
fun `test insert new line below with multiple carets`() { fun `test insert new line below with multiple carets`() {
val before = """ I fou${c}nd it in a legendary land val before = """ I fou${c}nd it in a legendary land

View File

@ -136,266 +136,4 @@ class ShiftLeftTest : VimTestCase() {
""".trimIndent(), """.trimIndent(),
) )
} }
@Test
fun `test undo after shift left single line`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<<")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
}
@Test
fun `test undo after shift left with motion`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("<2j") // Shift left 3 lines
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
}
@Test
fun `test undo after shift left visual mode`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("Vj<") // Visual select 2 lines and shift left
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c} line1()
line2()
line3()
}
""".trimIndent()
)
}
@Test
fun `test undo shift left in insert mode`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("i<C-D>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<Esc>")
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
}
@Test
fun `test undo after shift left single line with oldundo`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("<<")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after shift left with motion with oldundo`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("<2j") // Shift left 3 lines
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after shift left visual mode with oldundo`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("Vj<") // Visual select 2 lines and shift left
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c} line1()
line2()
line3()
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo shift left in insert mode with oldundo`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("i<C-D>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<Esc>")
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -208,416 +208,4 @@ class ShiftRightTest : VimTestCase() {
""".trimIndent(), """.trimIndent(),
) )
} }
@Test
fun `test undo after shift right single line`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText(">>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
}
@Test
fun `test undo after shift right with motion`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText(">2j") // Shift right 3 lines
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
}
@Test
fun `test undo after shift right visual mode`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("Vj>") // Visual select 2 lines and shift right
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
}
@Test
fun `test multiple undo after sequential shifts right`() {
configureByText("${c}unindented line")
typeText(">>")
assertState(" ${c}unindented line")
typeText(">>")
assertState(" ${c}unindented line")
typeText(">>")
assertState(" ${c}unindented line")
// Undo third shift
typeText("u")
assertState(" ${c}unindented line")
// Undo second shift
typeText("u")
assertState(" ${c}unindented line")
// Undo first shift
typeText("u")
assertState("${c}unindented line")
}
@Test
fun `test undo shift right in insert mode`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("i<C-T>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<Esc>")
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
}
@Test
fun `test undo shift right and left combination`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText(">>") // Shift right
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<<") // Shift left
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
// Undo shift left
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
// Undo shift right
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
}
@Test
fun `test undo after shift right single line with oldundo`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText(">>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after shift right with motion with oldundo`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText(">2j") // Shift right 3 lines
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after shift right visual mode with oldundo`() {
configureByText(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("Vj>") // Visual select 2 lines and shift right
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
typeText("u")
assertState(
"""
func main() {
${c}line1()
line2()
line3()
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential shifts right with oldundo`() {
configureByText("${c}unindented line")
try {
enterCommand("set oldundo")
typeText(">>")
assertState(" ${c}unindented line")
typeText(">>")
assertState(" ${c}unindented line")
typeText(">>")
assertState(" ${c}unindented line")
// Undo third shift
typeText("u")
assertState(" ${c}unindented line")
// Undo second shift
typeText("u")
assertState(" ${c}unindented line")
// Undo first shift
typeText("u")
assertState("${c}unindented line")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo shift right in insert mode with oldundo`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("i<C-T>")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<Esc>")
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo shift right and left combination with oldundo`() {
configureByText(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText(">>") // Shift right
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
typeText("<<") // Shift left
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
// Undo shift left
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
// Undo shift right
typeText("u")
assertState(
"""
func main() {
${c}println("Hello")
}
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -80,7 +80,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
kotlin.test.assertTrue(notifications.isEmpty() || notifications.last().isExpired || OptionConstants.clipboard_ideaput !in notifications.last().content) kotlin.test.assertTrue(notifications.isEmpty() || notifications.last().isExpired || OptionConstants.clipboard_ideaput !in notifications.last().content)
} }
private fun notifications(): List<Notification> { private fun notifications(): MutableList<Notification> {
return ActionCenter.getNotifications(fixture.project) return ActionCenter.getNotifications(fixture.project)
} }

View File

@ -216,294 +216,4 @@ class PutTestAfterCursorActionTest : VimTestCase() {
) )
} }
} }
@Test
fun `test undo after put after cursor`() {
configureByText("Hello ${c}world")
typeText("yy")
typeText("p")
assertState(
"""
Hello world
${c}Hello world
""".trimIndent()
)
typeText("u")
assertState("Hello ${c}world")
}
@Test
fun `test undo after put character after cursor`() {
configureByText("abc${c}def")
typeText("yl") // Yank 'd'
typeText("h") // Move left
assertState("ab${c}cdef")
typeText("p")
assertState("abc${c}ddef")
typeText("u")
assertState("ab${c}cdef")
}
@Test
fun `test undo after put word after cursor`() {
configureByText("The ${c}quick brown fox")
typeText("yiw") // Yank "quick"
typeText("w") // Move to "brown"
assertState("The quick ${c}brown fox")
typeText("p")
assertState("The quick bquic${c}krown fox")
typeText("u")
assertState("The quick ${c}brown fox")
}
@Test
fun `test multiple undo after sequential puts after cursor`() {
configureByText("${c}Hello")
typeText("yy")
typeText("p")
assertState(
"""
Hello
${c}Hello
""".trimIndent()
)
typeText("p")
assertState(
"""
Hello
Hello
${c}Hello
""".trimIndent()
)
// Undo second put
typeText("u")
assertState(
"""
Hello
${c}Hello
""".trimIndent()
)
// Undo first put
typeText("u")
assertState(
"""
${c}Hello
""".trimIndent()
)
}
@Test
fun `test undo put and move cursor`() {
configureByText("${c}abc def")
typeText("yiw") // Yank "abc"
typeText("w") // Move to "def"
assertState("abc ${c}def")
typeText("gp") // Put and move cursor after pasted text
assertState("abc dabc${c}ef")
typeText("u")
assertState("abc ${c}def")
}
@Test
fun `test undo put visual block after cursor`() {
configureByText(
"""
${c}abc
def
ghi
""".trimIndent()
)
typeText("<C-V>jjl") // Visual block select first 2 columns of all lines
typeText("y")
typeText("$")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
typeText("p")
assertState(
"""
abc${c}ab
defde
ghigh
""".trimIndent()
)
typeText("u")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
}
@Test
fun `test undo after put after cursor with oldundo`() {
configureByText("Hello ${c}world")
try {
enterCommand("set oldundo")
typeText("yy")
typeText("p")
assertState(
"""
Hello world
${c}Hello world
""".trimIndent()
)
typeText("u")
assertState("Hello ${c}world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after put character after cursor with oldundo`() {
configureByText("abc${c}def")
try {
enterCommand("set oldundo")
typeText("yl") // Yank 'd'
typeText("h") // Move left
assertState("ab${c}cdef")
typeText("p")
assertState("abc${c}ddef")
typeText("u")
assertState("ab${c}cdef")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after put word after cursor with oldundo`() {
configureByText("The ${c}quick brown fox")
try {
enterCommand("set oldundo")
typeText("yiw") // Yank "quick"
typeText("w") // Move to "brown"
assertState("The quick ${c}brown fox")
typeText("p")
assertState("The quick bquic${c}krown fox")
typeText("u")
assertState("The quick ${c}brown fox")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential puts after cursor with oldundo`() {
configureByText("${c}Hello")
try {
enterCommand("set oldundo")
typeText("yy")
typeText("p")
assertState(
"""
Hello
${c}Hello
""".trimIndent()
)
typeText("p")
assertState(
"""
Hello
Hello
${c}Hello
""".trimIndent()
)
// Undo second put
typeText("u")
assertState(
"""
Hello
${c}Hello
""".trimIndent()
)
// Undo first put
typeText("u")
assertState(
"""
${c}Hello
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo put and move cursor with oldundo`() {
configureByText("${c}abc def")
try {
enterCommand("set oldundo")
typeText("yiw") // Yank "abc"
typeText("w") // Move to "def"
assertState("abc ${c}def")
typeText("gp") // Put and move cursor after pasted text
assertState("abc dabc${c}ef")
typeText("u")
assertState("abc ${c}def")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo put visual block after cursor with oldundo`() {
configureByText(
"""
${c}abc
def
ghi
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("<C-V>jjl") // Visual block select first 2 columns of all lines
typeText("y")
typeText("$")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
typeText("p")
assertState(
"""
abc${c}ab
defde
ghigh
""".trimIndent()
)
typeText("u")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -56,257 +56,4 @@ class PutTextBeforeCursorActionTest : VimTestCase() {
""".trimIndent() """.trimIndent()
assertState(after) assertState(after)
} }
@Test
fun `test undo after put before cursor`() {
configureByText("Hello ${c}world")
typeText("yy")
typeText("P")
assertState(
"""
${c}Hello world
Hello world
""".trimIndent()
)
typeText("u")
assertState("Hello ${c}world")
}
@Test
fun `test undo after put character before cursor`() {
configureByText("abc${c}def")
typeText("yl") // Yank 'd'
typeText("h") // Move left
assertState("ab${c}cdef")
typeText("P")
assertState("ab${c}dcdef")
typeText("u")
assertState("ab${c}cdef")
}
@Test
fun `test undo after put word before cursor`() {
configureByText("The ${c}quick brown fox")
typeText("yiw") // Yank "quick"
typeText("w") // Move to "brown"
assertState("The quick ${c}brown fox")
typeText("P")
assertState("The quick quic${c}kbrown fox")
typeText("u")
assertState("The quick ${c}brown fox")
}
@Test
fun `test multiple undo after sequential puts`() {
configureByText("${c}Hello")
typeText("yy")
typeText("P")
assertState(
"""
${c}Hello
Hello
""".trimIndent()
)
typeText("P")
assertState(
"""
${c}Hello
Hello
Hello
""".trimIndent()
)
// Undo second put
typeText("u")
assertState(
"""
${c}Hello
Hello
""".trimIndent()
)
// Undo first put
typeText("u")
assertState(
"""
${c}Hello
""".trimIndent()
)
}
@Test
fun `test undo put visual block`() {
configureByText(
"""
${c}abc
def
ghi
""".trimIndent()
)
typeText("<C-V>jjl") // Visual block select first 2 columns of all lines
typeText("y")
typeText("$")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
typeText("P")
assertState(
"""
ab${c}abc
dedef
ghghi
""".trimIndent()
)
typeText("u")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
}
@Test
fun `test undo after put before cursor with oldundo`() {
configureByText("Hello ${c}world")
try {
enterCommand("set oldundo")
typeText("yy")
typeText("P")
assertState(
"""
${c}Hello world
Hello world
""".trimIndent()
)
typeText("u")
assertState("Hello ${c}world")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after put character before cursor with oldundo`() {
configureByText("abc${c}def")
try {
enterCommand("set oldundo")
typeText("yl") // Yank 'd'
typeText("h") // Move left
assertState("ab${c}cdef")
typeText("P")
assertState("ab${c}dcdef")
typeText("u")
assertState("ab${c}cdef")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo after put word before cursor with oldundo`() {
configureByText("The ${c}quick brown fox")
try {
enterCommand("set oldundo")
typeText("yiw") // Yank "quick"
typeText("w") // Move to "brown"
assertState("The quick ${c}brown fox")
typeText("P")
assertState("The quick quic${c}kbrown fox")
typeText("u")
assertState("The quick ${c}brown fox")
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test multiple undo after sequential puts with oldundo`() {
configureByText("${c}Hello")
try {
enterCommand("set oldundo")
typeText("yy")
typeText("P")
assertState(
"""
${c}Hello
Hello
""".trimIndent()
)
typeText("P")
assertState(
"""
${c}Hello
Hello
Hello
""".trimIndent()
)
// Undo second put
typeText("u")
assertState(
"""
${c}Hello
Hello
""".trimIndent()
)
// Undo first put
typeText("u")
assertState(
"""
${c}Hello
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test undo put visual block with oldundo`() {
configureByText(
"""
${c}abc
def
ghi
""".trimIndent()
)
try {
enterCommand("set oldundo")
typeText("<C-V>jjl") // Visual block select first 2 columns of all lines
typeText("y")
typeText("$")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
typeText("P")
assertState(
"""
ab${c}abc
dedef
ghghi
""".trimIndent()
)
typeText("u")
assertState(
"""
ab${c}c
def
ghi
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -79,7 +79,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -90,7 +89,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = "legendar${c}y it in a legendary land" val after = "legendar${c}y it in a legendary land"
assertState(after) assertState(after)
@ -106,7 +104,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -117,7 +114,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("v2e" + "2p")) typeText(injector.parser.parseKeys("v2e" + "2p"))
val after = "legendarylegendar${c}y in a legendary land" val after = "legendarylegendar${c}y in a legendary land"
assertState(after) assertState(after)
@ -133,7 +129,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -144,7 +139,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("v$" + "2p")) typeText(injector.parser.parseKeys("v$" + "2p"))
val after = "legendarylegendar${c}y" val after = "legendarylegendar${c}y"
assertState(after) assertState(after)
@ -186,7 +180,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -197,7 +190,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("vb" + "p")) typeText(injector.parser.parseKeys("vb" + "p"))
val after = "I legendar${c}y it in a legendary land" val after = "I legendar${c}y it in a legendary land"
assertState(after) assertState(after)
@ -222,7 +214,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -233,7 +224,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -265,7 +255,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -276,7 +265,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -308,7 +296,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -319,7 +306,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -351,7 +337,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -362,7 +347,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("v$" + "p")) typeText(injector.parser.parseKeys("v$" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -595,7 +579,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -606,7 +589,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -646,7 +628,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -657,7 +638,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "p")) typeText(injector.parser.parseKeys("ve" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -699,7 +679,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -710,7 +689,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("ve" + "2p")) typeText(injector.parser.parseKeys("ve" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -749,11 +727,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
} }
}
// registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) // registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "\"+p")) typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """ val after = """
@ -793,11 +769,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
} }
}
// registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) // registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "\"+p")) typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """ val after = """
@ -837,7 +811,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -848,7 +821,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -878,7 +850,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -889,7 +860,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "2p")) typeText(injector.parser.parseKeys("V" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -930,7 +900,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -941,7 +910,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -979,11 +947,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '*', "Discovery", SelectionType.CHARACTER_WISE) injector.registerGroup.storeText(vimEditor, context, '*', "Discovery", SelectionType.CHARACTER_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"*p")) typeText(injector.parser.parseKeys("V" + "\"*p"))
val after = """ val after = """
A Discovery A Discovery
@ -1021,11 +987,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1063,11 +1027,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1105,11 +1067,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "Discovery", SelectionType.CHARACTER_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1142,7 +1102,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1153,7 +1112,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1183,7 +1141,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1194,7 +1151,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "2p")) typeText(injector.parser.parseKeys("V" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -1235,7 +1191,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1246,7 +1201,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1284,11 +1238,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '*', "A Discovery\n", SelectionType.LINE_WISE) injector.registerGroup.storeText(vimEditor, context, '*', "A Discovery\n", SelectionType.LINE_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"*p")) typeText(injector.parser.parseKeys("V" + "\"*p"))
val after = """ val after = """
A Discovery A Discovery
@ -1326,11 +1278,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1368,11 +1318,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1410,11 +1358,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "A Discovery\n", SelectionType.LINE_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1452,7 +1398,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1463,7 +1408,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1522,7 +1466,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1533,7 +1476,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "p")) typeText(injector.parser.parseKeys("V" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1598,7 +1540,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1609,7 +1550,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("V" + "2p")) typeText(injector.parser.parseKeys("V" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -1670,11 +1610,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1737,11 +1675,9 @@ class PutVisualTextActionTest : VimTestCase() {
configureByText(before) configureByText(before)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) injector.registerGroup.storeText(vimEditor, context, '+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
} }
}
typeText(injector.parser.parseKeys("V" + "\"+p")) typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """ val after = """
A Discovery A Discovery
@ -1801,7 +1737,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1812,7 +1747,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1842,7 +1776,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1853,7 +1786,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>3e2k" + "p")) typeText(injector.parser.parseKeys("<C-V>3e2k" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1883,7 +1815,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1894,7 +1825,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -1924,7 +1854,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1935,7 +1864,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>3j$" + "p")) typeText(injector.parser.parseKeys("<C-V>3j$" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -1978,7 +1906,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -1989,7 +1916,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2021,7 +1947,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2032,7 +1957,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "P")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "P"))
val after = """ val after = """
A Discovery A Discovery
@ -2075,7 +1999,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2086,7 +2009,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """ val after = """
A Discovery A Discovery
@ -2130,7 +2052,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2141,7 +2062,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p")) typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2184,7 +2104,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2195,7 +2114,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2j$" + "p")) typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2234,7 +2152,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2245,7 +2162,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p")) typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2285,7 +2201,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2296,7 +2211,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p")) typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2336,7 +2250,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2347,7 +2260,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2ej" + "p")) typeText(injector.parser.parseKeys("<C-V>2ej" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2386,7 +2298,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2397,7 +2308,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>elj" + "p")) typeText(injector.parser.parseKeys("<C-V>elj" + "p"))
val after = """ val after = """
A Discovery A Discovery
@ -2438,7 +2348,6 @@ class PutVisualTextActionTest : VimTestCase() {
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup val registerService = injector.registerGroup
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
registerService.storeText( registerService.storeText(
vimEditor, vimEditor,
@ -2449,7 +2358,6 @@ class PutVisualTextActionTest : VimTestCase() {
false false
) )
} }
}
typeText(injector.parser.parseKeys("<C-V>2j$" + "p")) typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """ val after = """
A Discovery A Discovery

View File

@ -136,6 +136,7 @@ class MotionDownActionTest : VimTestCase() {
} }
@Test @Test
@Disabled
fun `test motion down in visual block mode with dollar motion2`() { fun `test motion down in visual block mode with dollar motion2`() {
val keys = "i<C-O>d<ESC>" val keys = "i<C-O>d<ESC>"
val before = """ val before = """

View File

@ -9,10 +9,12 @@
package org.jetbrains.plugins.ideavim.action.motion.updown package org.jetbrains.plugins.ideavim.action.motion.updown
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class MotionUpCtrlPAction : VimTestCase() { class MotionUpCtrlPAction : VimTestCase() {
@Test @Test
@Disabled("This one should be fixed")
fun `test last column empty`() { fun `test last column empty`() {
val keys = "o<Esc><End><C-P>" val keys = "o<Esc><End><C-P>"
val before = """ val before = """

View File

@ -132,18 +132,9 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
VimPlugin.getRegister() VimPlugin.getRegister()
.storeText( .storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
vimEditor,
context,
vimEditor.primaryCaret(),
TextRange(16, 19),
SelectionType.CHARACTER_WISE,
false
)
}
} }
typeText(commandToKeys("pu")) typeText(commandToKeys("pu"))
val after = """ val after = """
@ -179,18 +170,9 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
VimPlugin.getRegister() VimPlugin.getRegister()
.storeText( .storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
vimEditor,
context,
vimEditor.primaryCaret(),
TextRange(16, 19),
SelectionType.CHARACTER_WISE,
false
)
}
} }
typeText(commandToKeys("pu")) typeText(commandToKeys("pu"))
val after = """ val after = """
@ -227,18 +209,9 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
VimPlugin.getRegister() VimPlugin.getRegister()
.storeText( .storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
vimEditor,
context,
vimEditor.primaryCaret(),
TextRange(16, 19),
SelectionType.CHARACTER_WISE,
false
)
}
} }
typeText(commandToKeys("4pu")) typeText(commandToKeys("4pu"))
val after = """ val after = """
@ -275,18 +248,9 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor) val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
ApplicationManager.getApplication().invokeAndWait {
ApplicationManager.getApplication().runWriteAction { ApplicationManager.getApplication().runWriteAction {
VimPlugin.getRegister() VimPlugin.getRegister()
.storeText( .storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
vimEditor,
context,
vimEditor.primaryCaret(),
TextRange(16, 19),
SelectionType.CHARACTER_WISE,
false
)
}
} }
typeText(commandToKeys("4pu")) typeText(commandToKeys("4pu"))
val after = """ val after = """

View File

@ -202,219 +202,4 @@ class CopyCommandTest : VimTestCase() {
) )
assertPluginError(false) assertPluginError(false)
} }
@Test
fun `test copy line and undo`() {
configureByText(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non ${c}scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
enterCommand("copy .")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non scelerisque.
${c}Nunc tincidunt viverra ligula non scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
typeText("u")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non ${c}scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
}
@Test
fun `test copy range and undo`() {
configureByText(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi nec luctus tortor, id venenatis lacus.
Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
Ut id dapibus augue.
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
""".trimIndent()
)
enterCommand("2,3copy $")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|""".trimMargin()
)
typeText("u")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi nec luctus tortor, id venenatis lacus.
Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
Ut id dapibus augue.
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
""".trimIndent()
)
}
@Test
fun `test t command synonym and undo`() {
configureByText(
"""
Line 1
Line 2
Line ${c}3
Line 4
""".trimIndent()
)
enterCommand("t-1")
assertState(
"""
Line 1
Line 2
${c}Line 3
Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line 2
Line ${c}3
Line 4
""".trimIndent()
)
}
@Test
fun `test copy line and undo with oldundo`() {
configureByText(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non ${c}scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("copy .")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non scelerisque.
${c}Nunc tincidunt viverra ligula non scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
typeText("u")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc tincidunt viverra ligula non ${c}scelerisque.
Fusce sit amet mi ut purus volutpat vulputate vitae sed tortor.
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test copy range and undo with oldundo`() {
configureByText(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi nec luctus tortor, id venenatis lacus.
Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
Ut id dapibus augue.
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("2,3copy $")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|""".trimMargin()
)
typeText("u")
assertState(
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Morbi nec luctus tortor, id venenatis lacus.
Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
Ut id dapibus augue.
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test t command synonym and undo with oldundo`() {
configureByText(
"""
Line 1
Line 2
Line ${c}3
Line 4
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("t-1")
assertState(
"""
Line 1
Line 2
${c}Line 3
Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line 2
Line ${c}3
Line 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -441,233 +441,4 @@ class DeleteLinesCommandTest : VimTestCase() {
"Ut id dapibus augue.^J" "Ut id dapibus augue.^J"
) )
} }
@Test
fun `test delete line and undo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus${c} augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
enterCommand("d")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus${c} augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
}
@Test
fun `test delete multiple lines with range and undo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
enterCommand("2,4d")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
}
@Test
fun `test delete with count and undo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
enterCommand("d 3")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
}
@Test
fun `test delete line and undo with oldundo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus${c} augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("d")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus${c} augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test delete multiple lines with range and undo with oldundo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("2,4d")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel ${c}purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test delete with count and undo with oldundo`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("d 3")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
typeText("u")
assertState(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|Nunc sit amet tellus vel purus cursus posuere et at purus.
|Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -251,207 +251,4 @@ class JoinLinesCommandTest : VimTestCase() {
""".trimIndent(), """.trimIndent(),
) )
} }
@Test
fun `test join lines and undo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
enterCommand("j")
assertState(
"""
Line 1
${c}Line 2 Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
}
@Test
fun `test join range and undo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
Line 5
""".trimIndent()
)
enterCommand("2,4j")
assertState(
"""
Line 1
${c}Line 2 Line 3 Line 4
Line 5
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
Line 5
""".trimIndent()
)
}
@Test
fun `test join with count and undo`() {
configureByText(
"""
${c}Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
enterCommand("j 3")
assertState(
"""
${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
}
@Test
fun `test join lines and undo with oldundo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("j")
assertState(
"""
Line 1
${c}Line 2 Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test join range and undo with oldundo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
Line 5
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("2,4j")
assertState(
"""
Line 1
${c}Line 2 Line 3 Line 4
Line 5
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
Line 5
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test join with count and undo with oldundo`() {
configureByText(
"""
${c}Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
try {
enterCommand("set oldundo")
enterCommand("j 3")
assertState(
"""
${c}Lorem ipsum dolor sit amet, consectetur adipiscing elit Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
typeText("u")
assertState(
"""
${c}Lorem ipsum dolor sit amet,
consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -14,42 +14,6 @@ import org.junit.jupiter.api.Test
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
class MoveCommandTest : VimTestCase() { class MoveCommandTest : VimTestCase() {
@Test
fun `test move line up and undo`() {
configureByText(
"""
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
For example: homewor${c}k, homework, homework, homework, homework, homework, homework, homework, homework.
See, nothing.
""".trimIndent(),
)
enterCommand("m 0")
assertState(
"""
${c}For example: homework, homework, homework, homework, homework, homework, homework, homework, homework.
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
See, nothing.
""".trimIndent(),
)
typeText("u")
assertState(
"""
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
For example: homewor${c}k, homework, homework, homework, homework, homework, homework, homework, homework.
See, nothing.
""".trimIndent(),
)
}
@Test @Test
fun `test selection marks after moving line up`() { fun `test selection marks after moving line up`() {
configureByText( configureByText(
@ -373,45 +337,4 @@ class MoveCommandTest : VimTestCase() {
enterCommand("set nostartofline") enterCommand("set nostartofline")
} }
} }
@Test
fun `test move line up and undo with oldundo`() {
configureByText(
"""
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
For example: homewor${c}k, homework, homework, homework, homework, homework, homework, homework, homework.
See, nothing.
""".trimIndent(),
)
try {
enterCommand("set oldundo")
enterCommand("m 0")
assertState(
"""
${c}For example: homework, homework, homework, homework, homework, homework, homework, homework, homework.
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
See, nothing.
""".trimIndent(),
)
typeText("u")
assertState(
"""
====
My mother taught me this trick: if you repeat something over and over again it loses its meaning.
For example: homewor${c}k, homework, homework, homework, homework, homework, homework, homework, homework.
See, nothing.
""".trimIndent(),
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -211,250 +211,4 @@ class NormalCommandTest : VimTestCase() {
enterCommand("""exe "norm ^dei-\<C-R>\"-"""") enterCommand("""exe "norm ^dei-\<C-R>\"-"""")
assertState("""-myprop-: "my value"""") assertState("""-myprop-: "my value"""")
} }
@Test
fun `test normal command delete and undo`() {
configureByText(
"""
|Line 1
|Line ${c}2
|Line 3
""".trimMargin()
)
enterCommand("normal x")
assertState(
"""
|Line 1
|Line
|Line 3
""".trimMargin()
)
typeText("u")
assertState(
"""
|Line 1
|Line ${c}2
|Line 3
""".trimMargin()
)
}
@Test
fun `test normal command with range and undo`() {
configureByText(
"""
|First ${c}line
|Second line
|Third line
|Fourth line
""".trimMargin()
)
enterCommand("2,3normal A!")
assertState(
"""
|First line
|Second line!
|Third line${c}!
|Fourth line
""".trimMargin()
)
typeText("u")
assertState(
"""
|First ${c}line
|Second line
|Third line
|Fourth line
""".trimMargin()
)
}
@Test
fun `test normal command insert and undo`() {
configureByText(
"""
|${c}Hello world
""".trimMargin()
)
enterCommand("normal iTest ")
assertState(
"""
|Test${c} Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world
""".trimMargin()
)
}
@Test
fun `test normal command complex operation and undo`() {
configureByText(
"""
|Line ${c}1
|Line 2
|Line 3
""".trimMargin()
)
enterCommand("normal ddp")
assertState(
"""
|Line 2
|${c}Line 1
|Line 3
""".trimMargin()
)
typeText("u")
assertState(
"""
|Line ${c}1
|Line 2
|Line 3
""".trimMargin()
)
}
@Test
fun `test normal command delete and undo with oldundo`() {
configureByText(
"""
|Line 1
|Line ${c}2
|Line 3
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("normal x")
assertState(
"""
|Line 1
|Line
|Line 3
""".trimMargin()
)
typeText("u")
assertState(
"""
|Line 1
|Line ${c}2
|Line 3
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test normal command with range and undo with oldundo`() {
configureByText(
"""
|First ${c}line
|Second line
|Third line
|Fourth line
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("2,3normal A!")
assertState(
"""
|First line
|Second line!
|Third line${c}!
|Fourth line
""".trimMargin()
)
typeText("u")
assertState(
"""
|First ${c}line
|Second line
|Third line
|Fourth line
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test normal command insert and undo with oldundo`() {
configureByText(
"""
|${c}Hello world
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("normal iTest ")
assertState(
"""
|Test${c} Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test normal command complex operation and undo with oldundo`() {
configureByText(
"""
|Line ${c}1
|Line 2
|Line 3
""".trimMargin()
)
try {
enterCommand("set oldundo")
enterCommand("normal ddp")
assertState(
"""
|Line 2
|${c}Line 1
|Line 3
""".trimMargin()
)
typeText("u")
assertState(
"""
|Line ${c}1
|Line 2
|Line 3
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -1,106 +0,0 @@
/*
* Copyright 2003-2025 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package org.jetbrains.plugins.ideavim.ex.implementation.commands
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
class PrintLineNumberTest : VimTestCase() {
@Test
fun `test print last line number`() {
configureByLines(10, "Lorem ipsum dolor sit amet")
enterCommand("=")
assertStatusLineMessageContains("10")
}
@Test
fun `test print current line number`() {
configureByLines(10, "Lorem ipsum dolor sit amet")
typeText("4j")
enterCommand(".=")
assertStatusLineMessageContains("5")
}
@Test
fun `test print specific line number`() {
configureByLines(10, "Lorem ipsum dolor sit amet")
enterCommand("7=")
assertStatusLineMessageContains("7")
}
@Test
fun `test print line number of last part of range`() {
configureByLines(10, "Lorem ipsum dolor sit amet")
enterCommand("1,5=")
assertStatusLineMessageContains("5")
}
@Test
fun `test trailing characters raises an error`() {
configureByLines(10, "Lorem ipsum dolor sit amet")
enterCommand("=foo")
assertPluginError(true)
assertPluginErrorMessageContains("E488: Trailing characters: foo")
}
@Test
fun `test # flag prints line content and number`() {
configureByText("""
|Lorem ipsum dolor sit amet
|...consectetur adipiscing elit
|Maecenas efficitur nec odio vel malesuada
""".trimMargin().dotToTab())
enterCommand("2=#")
assertStatusLineMessageContains("2 \t\t\tconsectetur adipiscing elit")
}
@Test
fun `test l flag prints line content as printable string and number`() {
configureByText("""
|Lorem ipsum dolor sit amet
|...consectetur adipiscing elit
|Maecenas efficitur nec odio vel malesuada
""".trimMargin().dotToTab())
enterCommand("2=l")
assertStatusLineMessageContains("2 ^I^I^Iconsectetur adipiscing elit")
}
@Test
fun `test l and p flags print line content as printable string and number`() {
configureByText("""
|Lorem ipsum dolor sit amet
|...consectetur adipiscing elit
|Maecenas efficitur nec odio vel malesuada
""".trimMargin().dotToTab())
enterCommand("2=lp")
assertStatusLineMessageContains("2 ^I^I^Iconsectetur adipiscing elit")
}
@Test
fun `test p flag prints line content and number`() {
configureByText("""
|Lorem ipsum dolor sit amet
|...consectetur adipiscing elit
|Maecenas efficitur nec odio vel malesuada
""".trimMargin().dotToTab())
enterCommand("2=p")
assertStatusLineMessageContains("2 \t\t\tconsectetur adipiscing elit")
}
@Test
fun `test p and # flag prints line content and number`() {
configureByText("""
|Lorem ipsum dolor sit amet
|...consectetur adipiscing elit
|Maecenas efficitur nec odio vel malesuada
""".trimMargin().dotToTab())
enterCommand("2=p#")
assertStatusLineMessageContains("2 \t\t\tconsectetur adipiscing elit")
}
}

View File

@ -37,205 +37,4 @@ class PutCommandTest : VimTestCase() {
typeText(commandToKeys("put")) typeText(commandToKeys("put"))
assertState("Hello World!\n" + "<caret>Hello \n") assertState("Hello World!\n" + "<caret>Hello \n")
} }
@Test
fun `test put and undo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
""".trimIndent()
)
typeText(injector.parser.parseKeys("yy"))
enterCommand("put")
assertState(
"""
Line 1
Line 2
${c}Line 2
Line 3
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
""".trimIndent()
)
}
@Test
fun `test put from register and undo`() {
configureByText(
"""
First line
Second ${c}line
Third line
""".trimIndent()
)
typeText(injector.parser.parseKeys("\"ayy"))
enterCommand("put a")
assertState(
"""
First line
Second line
${c}Second line
Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
Second ${c}line
Third line
""".trimIndent()
)
}
@Test
fun `test put with line number and undo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
typeText(injector.parser.parseKeys("yy"))
enterCommand("1put")
assertState(
"""
Line 1
${c}Line 2
Line 2
Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
}
@Test
fun `test put and undo with oldundo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
""".trimIndent()
)
typeText(injector.parser.parseKeys("yy"))
try {
enterCommand("set oldundo")
enterCommand("put")
assertState(
"""
Line 1
Line 2
${c}Line 2
Line 3
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test put from register and undo with oldundo`() {
configureByText(
"""
First line
Second ${c}line
Third line
""".trimIndent()
)
typeText(injector.parser.parseKeys("\"ayy"))
try {
enterCommand("set oldundo")
enterCommand("put a")
assertState(
"""
First line
Second line
${c}Second line
Third line
""".trimIndent()
)
typeText("u")
assertState(
"""
First line
Second ${c}line
Third line
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test put with line number and undo with oldundo`() {
configureByText(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
typeText(injector.parser.parseKeys("yy"))
try {
enterCommand("set oldundo")
enterCommand("1put")
assertState(
"""
Line 1
${c}Line 2
Line 2
Line 3
Line 4
""".trimIndent()
)
typeText("u")
assertState(
"""
Line 1
Line ${c}2
Line 3
Line 4
""".trimIndent()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -110,7 +110,7 @@ class RegistersCommandTest : VimTestCase() {
assertExOutput( assertExOutput(
""" """
|Type Name Content |Type Name Content
| c "a ^IHello World^J^[ | c "a ^IHello World^M^[
""".trimMargin(), """.trimMargin(),
) )
} }

View File

@ -839,292 +839,4 @@ class SortCommandTest : VimTestCase() {
typeText(commandToKeys("sort")) typeText(commandToKeys("sort"))
assertState(" a\n b\n c\n whatever\n zee") assertState(" a\n b\n c\n whatever\n zee")
} }
@Test
fun `test sort and undo`() {
configureByText(
"""
|zebra
|${c}apple
|banana
|cherry
""".trimMargin()
)
typeText(commandToKeys("sort"))
assertState(
"""
|${c}apple
|banana
|cherry
|zebra
""".trimMargin()
)
typeText("u")
assertState(
"""
|zebra
|${c}apple
|banana
|cherry
""".trimMargin()
)
}
@Test
fun `test sort with range and undo`() {
configureByText(
"""
|header
|zebra
|${c}apple
|banana
|cherry
|footer
""".trimMargin()
)
typeText(commandToKeys("2,5sort"))
assertState(
"""
|header
|${c}apple
|banana
|cherry
|zebra
|footer
""".trimMargin()
)
typeText("u")
assertState(
"""
|header
|zebra
|${c}apple
|banana
|cherry
|footer
""".trimMargin()
)
}
@Test
fun `test sort with options and undo`() {
configureByText(
"""
|${c}10
|2
|100
|20
""".trimMargin()
)
typeText(commandToKeys("sort n"))
assertState(
"""
|${c}2
|10
|20
|100
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}10
|2
|100
|20
""".trimMargin()
)
}
@Test
fun `test reverse sort and undo`() {
configureByText(
"""
|${c}apple
|banana
|cherry
|date
""".trimMargin()
)
typeText(commandToKeys("sort!"))
assertState(
"""
|${c}date
|cherry
|banana
|apple
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}apple
|banana
|cherry
|date
""".trimMargin()
)
}
@Test
fun `test sort and undo with oldundo`() {
configureByText(
"""
|zebra
|${c}apple
|banana
|cherry
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("sort"))
assertState(
"""
|${c}apple
|banana
|cherry
|zebra
""".trimMargin()
)
typeText("u")
assertState(
"""
|zebra
|${c}apple
|banana
|cherry
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test sort with range and undo with oldundo`() {
configureByText(
"""
|header
|zebra
|${c}apple
|banana
|cherry
|footer
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("2,5sort"))
assertState(
"""
|header
|${c}apple
|banana
|cherry
|zebra
|footer
""".trimMargin()
)
typeText("u")
assertState(
"""
|header
|zebra
|${c}apple
|banana
|cherry
|footer
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test sort with options and undo with oldundo`() {
configureByText(
"""
|${c}10
|2
|100
|20
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("sort n"))
assertState(
"""
|${c}2
|10
|20
|100
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}10
|2
|100
|20
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@Test
fun `test reverse sort and undo with oldundo`() {
configureByText(
"""
|${c}apple
|banana
|cherry
|date
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("sort!"))
assertState(
"""
|${c}date
|cherry
|banana
|apple
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}apple
|banana
|cherry
|date
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -17,7 +17,6 @@ import org.jetbrains.plugins.ideavim.impl.OptionTest
import org.jetbrains.plugins.ideavim.impl.TraceOptions import org.jetbrains.plugins.ideavim.impl.TraceOptions
import org.jetbrains.plugins.ideavim.impl.VimOption import org.jetbrains.plugins.ideavim.impl.VimOption
import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
/** /**
* @author Alex Plate * @author Alex Plate
@ -1411,294 +1410,4 @@ class SubstituteCommandTest : VimTestCase() {
"a fooBar", "a fooBar",
) )
} }
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute and undo`() {
configureByText(
"""
|Hello ${c}world
|Hello world
|Hello world
""".trimMargin()
)
typeText(commandToKeys("s/world/universe/"))
assertState(
"""
|${c}Hello universe
|Hello world
|Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|Hello ${c}world
|Hello world
|Hello world
""".trimMargin()
)
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute global and undo`() {
configureByText(
"""
|${c}Hello world world world
|Hello world
""".trimMargin()
)
typeText(commandToKeys("s/world/universe/g"))
assertState(
"""
|${c}Hello universe universe universe
|Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world world world
|Hello world
""".trimMargin()
)
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute with range and undo`() {
configureByText(
"""
|First line
|${c}Hello world
|Hello world
|Hello world
|Last line
""".trimMargin()
)
typeText(commandToKeys("2,4s/world/universe/"))
assertState(
"""
|First line
|Hello universe
|Hello universe
|${c}Hello universe
|Last line
""".trimMargin()
)
typeText("u")
assertState(
"""
|First line
|${c}Hello world
|Hello world
|Hello world
|Last line
""".trimMargin()
)
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute all lines and undo`() {
configureByText(
"""
|${c}Hello world
|Hello world
|Hello world
""".trimMargin()
)
typeText(commandToKeys("%s/world/universe/"))
assertState(
"""
|Hello universe
|Hello universe
|${c}Hello universe
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world
|Hello world
|Hello world
""".trimMargin()
)
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute and undo with oldundo`() {
configureByText(
"""
|Hello ${c}world
|Hello world
|Hello world
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("s/world/universe/"))
assertState(
"""
|${c}Hello universe
|Hello world
|Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|Hello ${c}world
|Hello world
|Hello world
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute global and undo with oldundo`() {
configureByText(
"""
|${c}Hello world world world
|Hello world
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("s/world/universe/g"))
assertState(
"""
|${c}Hello universe universe universe
|Hello world
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world world world
|Hello world
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute with range and undo with oldundo`() {
configureByText(
"""
|First line
|${c}Hello world
|Hello world
|Hello world
|Last line
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("2,4s/world/universe/"))
assertState(
"""
|First line
|Hello universe
|Hello universe
|${c}Hello universe
|Last line
""".trimMargin()
)
typeText("u")
assertState(
"""
|First line
|${c}Hello world
|Hello world
|Hello world
|Last line
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
@OptionTest(
VimOption(TestOptionConstants.smartcase, doesntAffectTest = true),
VimOption(TestOptionConstants.ignorecase, doesntAffectTest = true),
)
@TestWithoutNeovim(reason = SkipNeovimReason.OPTION)
fun `test substitute all lines and undo with oldundo`() {
configureByText(
"""
|${c}Hello world
|Hello world
|Hello world
""".trimMargin()
)
try {
enterCommand("set oldundo")
typeText(commandToKeys("%s/world/universe/"))
assertState(
"""
|Hello universe
|Hello universe
|${c}Hello universe
""".trimMargin()
)
typeText("u")
assertState(
"""
|${c}Hello world
|Hello world
|Hello world
""".trimMargin()
)
} finally {
enterCommand("set nooldundo")
}
}
} }

View File

@ -39,7 +39,7 @@ class ExecutableTextRangesTests : VimTestCase() {
val scriptString = """ val scriptString = """
set rnu set rnu
if 1 if 1
-0§a " some line that parser cannot recognize (it should be ignored) -0=a " some line that parser cannot recognize (it should be ignored)
let y = 76 let y = 76
endif endif
""".trimIndent() """.trimIndent()
@ -61,7 +61,7 @@ class ExecutableTextRangesTests : VimTestCase() {
oh, hi Mark oh, hi Mark
" ideavim ignore end " ideavim ignore end
if 1 if 1
-0§a " some line that parser cannot recognize (it should be ignored) -0=a " some line that parser cannot recognize (it should be ignored)
let y = 76 let y = 76
endif endif
""".trimIndent() """.trimIndent()

View File

@ -17,6 +17,7 @@ import com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
import com.maddyhome.idea.vim.vimscript.parser.errors.IdeavimErrorListener import com.maddyhome.idea.vim.vimscript.parser.errors.IdeavimErrorListener
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.jetbrains.plugins.ideavim.productForArguments import org.jetbrains.plugins.ideavim.productForArguments
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource import org.junit.jupiter.params.provider.MethodSource
@ -190,6 +191,7 @@ class FunctionDeclarationTests : VimTestCase() {
// https://youtrack.jetbrains.com/issue/VIM-2654 // https://youtrack.jetbrains.com/issue/VIM-2654
@Test @Test
@Disabled
fun `return with omitted expression`() { fun `return with omitted expression`() {
VimscriptParser.parse( VimscriptParser.parse(
""" """

View File

@ -1,34 +0,0 @@
/*
* Copyright 2003-2025 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package org.jetbrains.plugins.ideavim.register
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
class RegisterMacroTest : VimTestCase() {
@Test
fun `test that macros work correctly with arrows`() {
doTest(
"qa\$as<esc><down>as<esc>q<down>@a", // Register a macro that adds s at the end of two lines and reruns it
"""
1
2
3
4
""".trimMargin(),
"""
1s
2s
3s
4s
""".trimMargin()
)
}
}

View File

@ -16,6 +16,7 @@ import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInfo import org.junit.jupiter.api.TestInfo
import java.nio.file.Files import java.nio.file.Files
@ -43,6 +44,33 @@ class ReloadVimRcTest : VimTestCase() {
kotlin.test.assertTrue(VimRcFileState.equalTo(document)) kotlin.test.assertTrue(VimRcFileState.equalTo(document))
} }
// TODO
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
@Test
@Disabled
fun `test equalTo with whitespaces`() {
val s = " " // Just to see whitespaces in the following code
"""
map x y
set myPlugin
map z t
""".trimIndent()
"""
map x y
set myPlugin$s$s$s$s$s$s
map z t
""".trimIndent()
// val lines = convertFileToLines(origFile)
// VimRcFileState.saveFileState("", lines)
//
// val document = editorFactory.createDocument(changedFile)
//
// assertTrue(VimRcFileState.equalTo(document))
}
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING) @TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
@Test @Test
fun `test equalTo with whitespaces and comments`() { fun `test equalTo with whitespaces and comments`() {

View File

@ -11,6 +11,7 @@ import com.intellij.application.options.CodeStyle
import com.intellij.ide.ClipboardSynchronizer import com.intellij.ide.ClipboardSynchronizer
import com.intellij.ide.bookmark.BookmarksManager import com.intellij.ide.bookmark.BookmarksManager
import com.intellij.ide.highlighter.XmlFileType import com.intellij.ide.highlighter.XmlFileType
import com.intellij.json.JsonFileType
import com.intellij.lang.Language import com.intellij.lang.Language
import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces import com.intellij.openapi.actionSystem.ActionPlaces
@ -283,6 +284,8 @@ abstract class VimTestCase {
protected fun configureByText(content: String) = configureByText(PlainTextFileType.INSTANCE, content) protected fun configureByText(content: String) = configureByText(PlainTextFileType.INSTANCE, content)
protected fun configureByXmlText(content: String) = configureByText(XmlFileType.INSTANCE, content) protected fun configureByXmlText(content: String) = configureByText(XmlFileType.INSTANCE, content)
protected fun configureByJsonText(@Suppress("SameParameterValue") content: String) =
configureByText(JsonFileType.INSTANCE, content)
protected fun configureAndGuard(content: String) { protected fun configureAndGuard(content: String) {
val ranges = extractBrackets(content) val ranges = extractBrackets(content)

View File

@ -32,7 +32,7 @@ dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testImplementation(testFixtures(project(":"))) // The root project testImplementation(testFixtures(project(":"))) // The root project
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0") testImplementation("org.junit.vintage:junit-vintage-engine:5.12.2")
intellijPlatform { intellijPlatform {
// Snapshots don't use installers // Snapshots don't use installers
@ -59,9 +59,12 @@ tasks {
useJUnitPlatform() useJUnitPlatform()
// Set teamcity env variable locally to run additional tests for leaks. // Set teamcity env variable locally to run additional tests for leaks.
println("Project leak checks: If you experience project leaks on TeamCity that doesn't reproduce locally") // By default, this test runs on TC only, but this test doesn't take a lot of time,
println("Uncomment the following line in build.gradle to enable leak checks (see build.gradle config)") // so we can turn it on for local development
// environment("TEAMCITY_VERSION" to "X") if (environment["TEAMCITY_VERSION"] == null) {
println("Set env TEAMCITY_VERSION to X to enable project leak checks from the platform")
environment("TEAMCITY_VERSION" to "X")
}
} }
} }

View File

@ -202,121 +202,4 @@ class ShiftLeftCommandTest : VimJavaTestCase() {
""".trimMargin() """.trimMargin()
assertState(after) assertState(after)
} }
@Test
fun `test shift left and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| ${c}System.out.println("World");
| }
|}
""".trimMargin()
)
enterCommand("<")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| ${c}System.out.println("World");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| ${c}System.out.println("World");
| }
|}
""".trimMargin()
)
}
@Test
fun `test shift left with range and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| System.out.println("!");
| }
|}
""".trimMargin()
)
enterCommand("3,5<")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| System.out.println("World");
| ${c}System.out.println("!");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| System.out.println("!");
| }
|}
""".trimMargin()
)
}
@Test
fun `test shift left with count and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
enterCommand("< 2")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| ${c}System.out.println("World");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
}
} }

View File

@ -182,121 +182,4 @@ class ShiftRightCommandTest : VimJavaTestCase() {
""".trimMargin() """.trimMargin()
assertState(after) assertState(after)
} }
@Test
fun `test shift right and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
enterCommand(">")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
}
@Test
fun `test shift right with range and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| System.out.println("!");
| }
|}
""".trimMargin()
)
enterCommand("3,5>")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| System.out.println("World");
| ${c}System.out.println("!");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| System.out.println("!");
| }
|}
""".trimMargin()
)
}
@Test
fun `test shift right with count and undo`() {
configureByJavaText(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
enterCommand("> 2")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| System.out.println("Hello");
| ${c}System.out.println("World");
| }
|}
""".trimMargin()
)
typeText("u")
assertState(
"""
|public class Example {
| public static void main(String[] args) {
| ${c}System.out.println("Hello");
| System.out.println("World");
| }
|}
""".trimMargin()
)
}
} }

View File

@ -25,7 +25,7 @@ dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testImplementation(testFixtures(project(":"))) // The root project testImplementation(testFixtures(project(":"))) // The root project
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0") testImplementation("org.junit.vintage:junit-vintage-engine:5.12.2")
intellijPlatform { intellijPlatform {
// Snapshots don't use installers // Snapshots don't use installers

View File

@ -25,7 +25,7 @@ dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testImplementation(testFixtures(project(":"))) // The root project testImplementation(testFixtures(project(":"))) // The root project
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0") testImplementation("org.junit.vintage:junit-vintage-engine:5.12.2")
intellijPlatform { intellijPlatform {
// Snapshots don't use installers // Snapshots don't use installers

View File

@ -15,7 +15,7 @@ val javaVersion: String by project
val remoteRobotVersion: String by project val remoteRobotVersion: String by project
dependencies { dependencies {
testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.13.0") testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.12.2")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testFixturesImplementation(testFixtures(project(":"))) // The root project testFixturesImplementation(testFixtures(project(":"))) // The root project

View File

@ -45,13 +45,13 @@ afterEvaluate {
} }
dependencies { dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.12.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.13.0") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.12.2")
// Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4 // Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4
// Can be removed when IJPL-159134 is fixed // Can be removed when IJPL-159134 is fixed
// testRuntimeOnly("junit:junit:4.13.2") // testRuntimeOnly("junit:junit:4.13.2")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.13.0") testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.12.2")
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-test // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-test
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")

View File

@ -123,7 +123,6 @@ command:
| FILE | EXIT | E_LOWERCASE | EDIT_FILE | DUMP_LINE | DIGRAPH | DEL_MARKS | D_LOWERCASE | DEL_LINES | DELCMD | FILE | EXIT | E_LOWERCASE | EDIT_FILE | DUMP_LINE | DIGRAPH | DEL_MARKS | D_LOWERCASE | DEL_LINES | DELCMD
| T_LOWERCASE | COPY | CMD_CLEAR | BUFFER_LIST | BUFFER_CLOSE | B_LOWERCASE | BUFFER | ASCII | T_LOWERCASE | COPY | CMD_CLEAR | BUFFER_LIST | BUFFER_CLOSE | B_LOWERCASE | BUFFER | ASCII
| ACTIONLIST | ACTION | LOCKVAR | UNLOCKVAR | PACKADD | TABMOVE | ACTIONLIST | ACTION | LOCKVAR | UNLOCKVAR | PACKADD | TABMOVE
| ASSIGN // `:=` print last line number
) )
bangModifier = BANG? bangModifier = BANG?
WS* ((commandArgumentWithoutBars? inline_comment NEW_LINE) | (commandArgumentWithoutBars? NEW_LINE) | (commandArgumentWithoutBars? BAR)) (NEW_LINE | BAR)* WS* ((commandArgumentWithoutBars? inline_comment NEW_LINE) | (commandArgumentWithoutBars? NEW_LINE) | (commandArgumentWithoutBars? BAR)) (NEW_LINE | BAR)*

View File

@ -104,32 +104,15 @@ class KeyHandler {
*/ */
fun handleKey(editor: VimEditor, key: KeyStroke, context: ExecutionContext, keyState: KeyHandlerState) { fun handleKey(editor: VimEditor, key: KeyStroke, context: ExecutionContext, keyState: KeyHandlerState) {
commandListener.forEach { it() } commandListener.forEach { it() }
handleKey(editor, key, context, allowKeyMappings = true, keyState) handleKey(editor, key, context, allowKeyMappings = true, mappingCompleted = false, keyState)
} }
/** /**
* Handling input keys with additional parameters * Handling input keys with additional parameters
* *
* @param allowKeyMappings If we allow key mappings or not * @param allowKeyMappings If we allow key mappings or not
* @param mappingCompleted No longer used
*/ */
fun handleKey(
editor: VimEditor,
key: KeyStroke,
context: ExecutionContext,
allowKeyMappings: Boolean,
keyState: KeyHandlerState,
) {
val result = processKey(key, editor, allowKeyMappings, KeyProcessResult.SynchronousKeyProcessBuilder(keyState))
if (result is KeyProcessResult.Executable) {
result.execute(editor, context)
}
}
@Deprecated(
"Use `handleKey(editor, key, context, allowKeyMappings, keyState)` instead.",
replaceWith = ReplaceWith("handleKey(editor, key, context, allowKeyMappings, keyState)")
)
@ApiStatus.ScheduledForRemoval
fun handleKey( fun handleKey(
editor: VimEditor, editor: VimEditor,
key: KeyStroke, key: KeyStroke,
@ -138,7 +121,10 @@ class KeyHandler {
mappingCompleted: Boolean, mappingCompleted: Boolean,
keyState: KeyHandlerState, keyState: KeyHandlerState,
) { ) {
handleKey(editor, key, context, allowKeyMappings, keyState) val result = processKey(key, editor, allowKeyMappings, KeyProcessResult.SynchronousKeyProcessBuilder(keyState))
if (result is KeyProcessResult.Executable) {
result.execute(editor, context)
}
} }
/** /**
@ -269,12 +255,13 @@ class KeyHandler {
return return
} }
} }
if (injector.application.isMainThread()) {
val action: Runnable = ActionRunner(editor, context, command, keyState, operatorArguments) val action: Runnable = ActionRunner(editor, context, command, keyState, operatorArguments)
val cmdAction = command.action val cmdAction = command.action
val name = cmdAction.id val name = cmdAction.id
injector.actionExecutor.executeCommand(editor, action, name, action) injector.actionExecutor.executeCommand(editor, action, name, action)
} }
}
/** /**
* Partially resets the state of this handler. Resets the command count, clears the key list, resets the key tree * Partially resets the state of this handler. Resets the command count, clears the key list, resets the key tree
@ -399,6 +386,8 @@ class KeyHandler {
@JvmStatic @JvmStatic
fun getInstance(): KeyHandler = instance fun getInstance(): KeyHandler = instance
} }
data class MutableBoolean(var value: Boolean)
} }
/** /**

View File

@ -81,7 +81,7 @@ sealed class TillCharacterMotion(
else if (direction == Direction.FORWARDS) "s-1" else if (direction == Direction.FORWARDS) "s-1"
else "s+1" else "s+1"
injector.searchGroup.setLastSearchState(argument.character.let { if (it in "`^$.*[~/\\") "\\$it" else it.toString() }, offset, direction) injector.searchGroup.setLastSearchState(argument.character.let { if (it == '.') "\\." else it.toString() }, offset, direction)
return res.toMotionOrError() return res.toMotionOrError()
} }

View File

@ -211,7 +211,6 @@ interface VimEditor {
fun createIndentBySize(size: Int): String fun createIndentBySize(size: Int): String
fun getFoldRegionAtOffset(offset: Int): VimFoldRegion? fun getFoldRegionAtOffset(offset: Int): VimFoldRegion?
fun getSoftWrapStartAtOffset(offset: Int): Int?
/** /**
* Mostly related to Fleet. After the editor is modified, the carets are modified. You can't use the old caret * Mostly related to Fleet. After the editor is modified, the carets are modified. You can't use the old caret

View File

@ -280,7 +280,8 @@ internal object MappingProcessor : KeyConsumer {
// Replay the rest of the keys, with mapping applied, as though they were typed // Replay the rest of the keys, with mapping applied, as though they were typed
unhandledKeys.subList(subsequence.size, unhandledKeys.size).forEach { unhandledKeys.subList(subsequence.size, unhandledKeys.size).forEach {
KeyHandler.getInstance().handleKey(editor, it, context, allowKeyMappings = true, keyState) KeyHandler.getInstance()
.handleKey(editor, it, context, allowKeyMappings = true, mappingCompleted = false, keyState)
} }
return return
} }
@ -295,7 +296,7 @@ internal object MappingProcessor : KeyConsumer {
// though they were typed. // though they were typed.
val keyHandler = KeyHandler.getInstance() val keyHandler = KeyHandler.getInstance()
unhandledKeys.forEachIndexed { index, it -> unhandledKeys.forEachIndexed { index, it ->
keyHandler.handleKey(editor, it, context, allowKeyMappings = index != 0, keyState) keyHandler.handleKey(editor, it, context, allowKeyMappings = index != 0, mappingCompleted = false, keyState)
} }
} }
} }

View File

@ -13,7 +13,6 @@ import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimCaret import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimCaretListener import com.maddyhome.idea.vim.api.VimCaretListener
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.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.normalizeOffset import com.maddyhome.idea.vim.api.normalizeOffset
import com.maddyhome.idea.vim.command.Argument import com.maddyhome.idea.vim.command.Argument
@ -227,15 +226,7 @@ sealed class MotionActionHandler : EditorActionHandlerBase(false) {
StrictMode.assert(caret.isPrimary, "Block selection mode must only operate on primary caret") StrictMode.assert(caret.isPrimary, "Block selection mode must only operate on primary caret")
} }
val normalisedOffset = prepareMoveToAbsoluteOffset(editor, cmd, offset).let { val normalisedOffset = prepareMoveToAbsoluteOffset(editor, cmd, offset)
if (offset.intendedColumn == VimMotionGroupBase.LAST_COLUMN) {
val softWrapStart = editor.getSoftWrapStartAtOffset(it)
if (softWrapStart != null) softWrapStart - 1 else it
}
else {
it
}
}
StrictMode.assert(normalisedOffset == offset.offset, "Adjusted offset should be normalised by action") StrictMode.assert(normalisedOffset == offset.offset, "Adjusted offset should be normalised by action")
// Set before moving, so it can be applied during move, especially important for LAST_COLUMN and visual block mode // Set before moving, so it can be applied during move, especially important for LAST_COLUMN and visual block mode

View File

@ -102,7 +102,7 @@ class ToKeysMappingInfo(
while (keyHandler.keyStack.hasStroke()) { while (keyHandler.keyStack.hasStroke()) {
val keyStroke = keyHandler.keyStack.feedStroke() val keyStroke = keyHandler.keyStack.feedStroke()
val allowKeyMappings = isRecursive && !(first && lhsIsPrefixOfRhs) val allowKeyMappings = isRecursive && !(first && lhsIsPrefixOfRhs)
keyHandler.handleKey(editor, keyStroke, context, allowKeyMappings, keyState) keyHandler.handleKey(editor, keyStroke, context, allowKeyMappings, false, keyState)
first = false first = false
} }
} finally { } finally {
@ -144,7 +144,7 @@ class ToExpressionMappingInfo(
for (keyStroke in toKeys) { for (keyStroke in toKeys) {
val allowKeyMappings = isRecursive && !(first && lhsIsPrefixOfRhs) val allowKeyMappings = isRecursive && !(first && lhsIsPrefixOfRhs)
val keyHandler = KeyHandler.getInstance() val keyHandler = KeyHandler.getInstance()
keyHandler.handleKey(editor, keyStroke, context, allowKeyMappings, keyState) keyHandler.handleKey(editor, keyStroke, context, allowKeyMappings, false, keyState)
first = false first = false
} }
} }

View File

@ -21,8 +21,8 @@ import com.maddyhome.idea.vim.api.VimFoldRegion
import com.maddyhome.idea.vim.api.VimIndentConfig import com.maddyhome.idea.vim.api.VimIndentConfig
import com.maddyhome.idea.vim.api.VimScrollingModel import com.maddyhome.idea.vim.api.VimScrollingModel
import com.maddyhome.idea.vim.api.VimSelectionModel import com.maddyhome.idea.vim.api.VimSelectionModel
import com.maddyhome.idea.vim.api.VimVirtualFile
import com.maddyhome.idea.vim.api.VimVisualPosition import com.maddyhome.idea.vim.api.VimVisualPosition
import com.maddyhome.idea.vim.api.VimVirtualFile
import com.maddyhome.idea.vim.common.LiveRange import com.maddyhome.idea.vim.common.LiveRange
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.common.VimEditorReplaceMask import com.maddyhome.idea.vim.common.VimEditorReplaceMask
@ -788,10 +788,6 @@ class VimRegex(pattern: String) {
return null return null
} }
override fun getSoftWrapStartAtOffset(offset: Int): Int? {
return null
}
override fun <T : ImmutableVimCaret> findLastVersionOfCaret(caret: T): T? { override fun <T : ImmutableVimCaret> findLastVersionOfCaret(caret: T): T? {
return null return null
} }

View File

@ -54,7 +54,7 @@ data class NormalCommand(val range: Range, val modifier: CommandModifier, val ar
val keyHandler = KeyHandler.getInstance() val keyHandler = KeyHandler.getInstance()
keyHandler.reset(editor) keyHandler.reset(editor)
for (key in keys) { for (key in keys) {
keyHandler.handleKey(editor, key, context, useMappings, keyHandler.keyHandlerState) keyHandler.handleKey(editor, key, context, useMappings, false, keyHandler.keyHandlerState)
} }
// Exit if state leaves as insert or cmd_line // Exit if state leaves as insert or cmd_line

View File

@ -1,62 +0,0 @@
/*
* Copyright 2003-2025 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.vimscript.model.commands
import com.intellij.vim.annotations.ExCommand
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.command.OperatorArguments
import com.maddyhome.idea.vim.ex.exExceptionMessage
import com.maddyhome.idea.vim.ex.ranges.Range
import com.maddyhome.idea.vim.helper.EngineStringHelper
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
@ExCommand(command = "=")
data class PrintLineNumberCommand(val range: Range, val modifier: CommandModifier, val argument: String) :
Command.SingleExecution(range, modifier, argument) {
init {
defaultRange = "$"
}
override val argFlags: CommandHandlerFlags =
flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun processCommand(
editor: VimEditor,
context: ExecutionContext,
operatorArguments: OperatorArguments,
): ExecutionResult {
if (argument.isNotEmpty() && argument[0] !in "l#p") {
throw exExceptionMessage("E488", argument) // E488: Trailing characters: $argument
}
val line1 = range.getLineRange(editor, editor.currentCaret()).endLine1
// `l` means output the line like `:list` - show unprintable chars, and include `^` and `$`
// `#` means output the line with the line number
// `p` means output the line like `:print`
// The flags can be combined, so `l#` means line number and `:list`. Normally, Vim displays this over two lines.
// Since we're outputting to the single line status bar, if any flags are specified, we treat it like `#` was
// specified - we always show line number.
val content = if (argument.isNotEmpty()) {
val text = editor.getLineText(line1 - 1)
if (argument.contains("l")) {
val keys = injector.parser.stringToKeys(text)
EngineStringHelper.toPrintableCharacters(keys)
}
else text
}
else ""
injector.messages.showStatusBarMessage(editor, "$line1 $content")
return ExecutionResult.Success
}
}

View File

@ -1,7 +1,6 @@
{ {
"&": "com.maddyhome.idea.vim.vimscript.model.commands.SubstituteCommand", "&": "com.maddyhome.idea.vim.vimscript.model.commands.SubstituteCommand",
"<": "com.maddyhome.idea.vim.vimscript.model.commands.ShiftLeftCommand", "<": "com.maddyhome.idea.vim.vimscript.model.commands.ShiftLeftCommand",
"=": "com.maddyhome.idea.vim.vimscript.model.commands.PrintLineNumberCommand",
">": "com.maddyhome.idea.vim.vimscript.model.commands.ShiftRightCommand", ">": "com.maddyhome.idea.vim.vimscript.model.commands.ShiftRightCommand",
"@": "com.maddyhome.idea.vim.vimscript.model.commands.RepeatCommand", "@": "com.maddyhome.idea.vim.vimscript.model.commands.RepeatCommand",
"N[ext]": "com.maddyhome.idea.vim.vimscript.model.commands.PreviousFileCommand", "N[ext]": "com.maddyhome.idea.vim.vimscript.model.commands.PreviousFileCommand",

View File

@ -0,0 +1,72 @@
# Vimscript
## IdeaVim 1.7.0
- [x] expressions: binary, unary, ternary, function calls, sublists, options, registers, variables, lists, dictionaries
- [x] `if` condition
- [x] `for` and `while` loops
- [x] `try`/`catch`/`finally`
- [x] function definition (without flags)
- [x] `break`, `continue`, `throw`, `return`
- [x] scopes: `g:`, `s:`, `l:`, `a:`, `b:`, `w:`, `t:` (the `v:` scope is not supported yet)
- [x] `map <expr>`
### IdeaVim 1.8.0
- [x] move `s:` scoped variables to `Script` class
- [x] move `l:` and `a:` scoped variables to the `FunctionDeclaration` class
- [x] `closure` function flag
- [x] `..` as concatenation operator
- [x] falsy operator `??`
- [x] access dictionary value by `dict.key`
- [x] `abort` function flag
- [x] `range` function flag
- [x] `call` command
- [x] optional arguments `...`
- [x] funcref type
- [x] lambdas
- [x] function as method
- [x] `function` function
- [x] `funcref` function
- [x] `dict` function flag
- [x] anonymous functions
- [x] default value in functions e.g. `function F1(a, b = 10)`
- [x] `has("ide")` or "ide" option
- [x] reduce number of rules in grammar
- [x] classic package structure
### IdeaVim 1.9.0
- [x] support `for [a, b] in {expr}`
- [x] pass scopes to functions e.g. `for k in keys(s:)`
- [x] curly-braces-names
- [x] `finish` statement
- [x] pass Lists and Dictionaries by reference
- [x] variable locking
- [x] rewrite OptionManager to vim data types
- [x] scoped options
- [x] `normal` command
- [x] expression register (`<C-R>=`)
## Plans for the next releases:
### IdeaVim 1.10.0
- [ ] `Result` class that would store the exceptions
- [ ] throwing multiple exceptions at once
- [ ] exception wrapping in try/catch
- [ ] store exception messages in property file
- [ ] store vim exception stacktrace
### Pool of things that might be added soon
- [ ] executing context (script / command line) & better parent for executable
- [ ] classloading
- [ ] all the let command's cases (e.g. registers)
- [ ] vim "special" type
- [ ] `v:` scope
- [ ] update tests to JUnit 5
- [ ] rethink vimscript tests
- [ ] loggers
- [ ] todos, warnings
- [ ] expressions in substitute command (`\=`)
- [ ] vim status line and beautiful exceptions output
- [ ] improve `w:` and `t:` scopes
- [ ] context dependent parsing e.g. `dict.key`
- [ ] add `-range` option to `command` command
- [ ] better strings (e.g. `"\<Esc"`)