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

Improve isEndAllowed

This commit is contained in:
Matt Ellis 2024-12-27 23:36:51 +00:00 committed by Alex Pláte
parent 8b8ef80a5e
commit 0e587211d9

View File

@ -15,7 +15,6 @@ import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.isSingleModeActive
import java.util.*
inline fun <reified T : Enum<T>> noneOfEnum(): EnumSet<T> = EnumSet.noneOf(T::class.java)
@ -32,13 +31,27 @@ val VimEditor.usesVirtualSpace: Boolean
val VimEditor.isEndAllowed: Boolean
get() = this.isEndAllowed(this.mode)
/**
* Returns true if the end of line character is allowed as part of motion or selection
*
* This is mostly needed for the `$` motion, which can behave differently in different modes, and isn't explicitly
* documented. The motion is really only valid in Normal and Visual modes. In Normal, it moves to the last character of
* the current line, not including the end of line character. In Visual (as documented) it moves to the end of line
* char.
*
* The motion obviously doesn't work in Insert or Replace modes, but requires `<C-O>` to enter "Insert Normal" mode.
* In this case, `$` should move to the end of line char, just like in insert/replace mode. AIUI, this is because Vim
* will switch to Normal mode with `<C-O>`, set the current column to the "end of line" magic value, return to insert or
* replace, and then finally update the screen. Because the update happens in Insert/Replace, the "Insert Normal"
* position for "end of line" becomes the end of line char.
*/
fun VimEditor.isEndAllowed(mode: Mode): Boolean {
// Technically, we should look at the "ultimate" current mode and skip anything like Command-line or Operator-pending,
// but for our usages, this isn't necessary
return when (mode) {
is Mode.INSERT, is Mode.VISUAL, is Mode.SELECT -> true
is Mode.NORMAL, is Mode.CMD_LINE, Mode.REPLACE, is Mode.OP_PENDING -> {
// One day we'll use a proper insert_normal mode
if (mode.isSingleModeActive) true else usesVirtualSpace
}
Mode.INSERT, Mode.REPLACE, is Mode.VISUAL, is Mode.SELECT -> true
is Mode.NORMAL -> if (mode.isInsertPending || mode.isReplacePending) true else usesVirtualSpace
is Mode.CMD_LINE, is Mode.OP_PENDING -> usesVirtualSpace
}
}