diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/CopyActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/CopyActionTest.kt index 3f783753f1..26335dae0c 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/CopyActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/CopyActionTest.kt @@ -19,6 +19,7 @@ import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.waitAndAssert import org.junit.jupiter.api.Test +import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -145,12 +146,33 @@ class CopyActionTest : VimTestCase() { one two three four - + """.trimIndent(), ) assertTrue(KeyHandler.getInstance().keyHandlerState.commandBuilder.isEmpty) } + // Regression test: CommandBuilder.isEmpty must return false while waiting for a register character. + // Previously, isRegisterPending was not checked in isEmpty, so `"` would incorrectly trigger + // an error indicator (beep) because EditorResetConsumer treated the builder as empty. + @TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING) + @Test + fun `test command builder is not empty while register is pending`() { + configureByText("hello world") + // Typing `"` starts register selection - command builder should NOT be empty + typeText("\"") + assertFalse( + KeyHandler.getInstance().keyHandlerState.commandBuilder.isEmpty, + "Command builder must not be empty while waiting for register character", + ) + // Pressing Escape cancels register selection - command builder should be empty again + typeText("") + assertTrue( + KeyHandler.getInstance().keyHandlerState.commandBuilder.isEmpty, + "Command builder must be empty after cancelling register selection", + ) + } + @Test fun testWrongYankQuoteYankLine() { assertPluginError(false) diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/command/CommandBuilder.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/command/CommandBuilder.kt index 41f04d8960..98bdd5aea0 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/command/CommandBuilder.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/command/CommandBuilder.kt @@ -55,6 +55,7 @@ class CommandBuilder private constructor( /** Returns true if the command builder is clean and ready to start building */ val isEmpty get() = commandState == CurrentCommandState.NEW_COMMAND + && !isRegisterPending && selectedRegister == null && counts.size == 1 && counts[0] == 0 && action == null @@ -398,6 +399,7 @@ class CommandBuilder private constructor( if (keyStrokeTrie != other.keyStrokeTrie) return false if (counts != other.counts) return false + if (isRegisterPending != other.isRegisterPending) return false if (selectedRegister != other.selectedRegister) return false if (action != other.action) return false if (argument != other.argument) return false @@ -412,6 +414,7 @@ class CommandBuilder private constructor( override fun hashCode(): Int { var result = keyStrokeTrie.hashCode() result = 31 * result + counts.hashCode() + result = 31 * result + isRegisterPending.hashCode() result = 31 * result + selectedRegister.hashCode() result = 31 * result + action.hashCode() result = 31 * result + argument.hashCode() @@ -430,6 +433,7 @@ class CommandBuilder private constructor( commandKeyStrokes.toMutableList() ) result.selectedRegister = selectedRegister + result.isRegisterPending = isRegisterPending result.action = action result.argument = argument result.commandState = commandState