Skip to content

Commit

Permalink
Encapsulate the command builder's state flag
Browse files Browse the repository at this point in the history
This also gets rid of BAD_COMMAND, which was set but never checked - the function that set the flag would immediately reset the command builder
  • Loading branch information
citizenmatt committed Aug 29, 2024
1 parent 7c4a2ca commit 06ff832
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 13 deletions.
12 changes: 3 additions & 9 deletions vim-engine/src/main/kotlin/com/maddyhome/idea/vim/KeyHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.command.MappingProcessor
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.CurrentCommandState
import com.maddyhome.idea.vim.diagnostic.VimLogger
import com.maddyhome.idea.vim.diagnostic.trace
import com.maddyhome.idea.vim.diagnostic.vimLogger
Expand Down Expand Up @@ -197,10 +196,9 @@ class KeyHandler {
}

private fun onUnknownKey(editor: VimEditor, keyState: KeyHandlerState) {
logger.trace("Command builder is set to BAD")
keyState.commandBuilder.commandState = CurrentCommandState.BAD_COMMAND
editor.resetOpPending()
editor.isReplaceCharacter = false
// Note that this will also reset the CommandBuilder to NEW_COMMAND
reset(keyState, editor.mode)
}

Expand Down Expand Up @@ -328,8 +326,7 @@ class KeyHandler {
) : Runnable {
override fun run() {
val editorState = injector.vimState
// TODO: This seems an unexpected place to reset command builder state
keyState.commandBuilder.commandState = CurrentCommandState.NEW_COMMAND

val register = cmd.register
if (register != null) {
injector.registerGroup.selectRegister(register)
Expand Down Expand Up @@ -357,10 +354,7 @@ class KeyHandler {
}
}

// TODO: Surely the command builder is always empty at this point?
if (keyState.commandBuilder.isEmpty) {
instance.reset(keyState, editorState.mode)
}
instance.reset(keyState, editorState.mode)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class CommandBuilder private constructor(
constructor(rootNode: RootNode<LazyVimCommand>, initialUncommittedRawCount: Int = 0)
: this(rootNode, mutableListOf(initialUncommittedRawCount), mutableListOf())

private var commandState: CurrentCommandState = CurrentCommandState.NEW_COMMAND
private var selectedRegister: Char? = null
private var action: EditorActionHandlerBase? = null
private var argument: Argument? = null
Expand All @@ -49,9 +50,6 @@ class CommandBuilder private constructor(
counts[counts.size - 1] = value
}

// TODO: Encapsulate this
var commandState: CurrentCommandState = CurrentCommandState.NEW_COMMAND

/** Provide the typed keys for `'showcmd'` */
val keys: Iterable<KeyStroke> get() = keyList

Expand Down Expand Up @@ -204,6 +202,12 @@ class CommandBuilder private constructor(
keyList.add(key)
}

/**
* Add an action to the command
*
* This can be an action such as delete the current character - `x`, a motion like `w`, an operator like `d` or a
* motion that will be used as the argument of an operator - the `w` in `dw`.
*/
fun addAction(action: EditorActionHandlerBase) {
logger.trace { "addAction is executed. action = $action" }

Expand All @@ -230,13 +234,23 @@ class CommandBuilder private constructor(
}
}

/**
* Add an argument to the command
*
* This might be a simple character argument, such as `x` in `fx`, or an ex-string argument to a search motion, like
* `d/foo`. If the command is an operator+motion, the motion is both an action and an argument. While it is simpler
* to use [addAction], it will still work if the motion action can also be wrapped in an [Argument.Motion] and passed
* to [addArgument].
*/
fun addArgument(argument: Argument) {
logger.trace("addArgument is executed")

// If the command's action is an operator, the argument will be a motion, which might be waiting for its argument.
// If so, update the motion argument to include the given argument
this.argument = motionArgument?.withArgument(argument) ?: argument

fallbackArgumentType = null

if (!isAwaitingArgument) {
logger.trace("Argument is simple type, or motion with own argument. No further argument required. Setting command state to READY")
commandState = CurrentCommandState.READY
Expand Down Expand Up @@ -310,6 +324,11 @@ class CommandBuilder private constructor(
return isMultikey
}

/**
* Build the command with the current counts, register, actions and arguments
*
* The command builder is reset after the command is built.
*/
fun buildCommand(): Command {
val rawCount = calculateCount0Snapshot()
val command = Command(selectedRegister, rawCount, action!!, argument, action!!.type, action?.flags ?: noneOfEnum())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ package com.maddyhome.idea.vim.common
enum class CurrentCommandState {
NEW_COMMAND,
READY,
BAD_COMMAND,
}

0 comments on commit 06ff832

Please sign in to comment.