1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-06-02 13:34:07 +02:00
IntelliJ-IdeaVim/src/main/java/com/maddyhome/idea/vim/helper/ModeExtensions.kt
Alex Plate e7a8b45c10
[VIM-3051] Refactor the way we store modes in IdeaVim
Now we have a single variable with current mode instead of stack of modes.
2023-08-25 11:38:21 +03:00

100 lines
3.3 KiB
Kotlin

/*
* 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.
*/
@file:JvmName("ModeHelper")
package com.maddyhome.idea.vim.helper
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.getLineEndForOffset
import com.maddyhome.idea.vim.api.getLineStartForOffset
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
import com.maddyhome.idea.vim.newapi.IjVimCaret
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.ReturnTo
import com.maddyhome.idea.vim.state.mode.inSelectMode
import com.maddyhome.idea.vim.state.mode.returnTo
/** [adjustCaretPosition] - if true, caret will be moved one char left if it's on the line end */
internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
if (!this.vim.inSelectMode) return
val returnTo = this.vim.vimStateMachine.mode.returnTo
when (returnTo) {
ReturnTo.INSERT -> {
this.vim.vimStateMachine.mode = Mode.INSERT
}
ReturnTo.REPLACE -> {
this.vim.vimStateMachine.mode = Mode.REPLACE
}
null -> {
this.vim.vimStateMachine.mode = Mode.NORMAL()
}
}
SelectionVimListenerSuppressor.lock().use {
this.caretModel.allCarets.forEach {
it.removeSelection()
it.vim.vimSelectionStartClear()
if (adjustCaretPosition) {
val lineEnd = IjVimEditor(this).getLineEndForOffset(it.offset)
val lineStart = IjVimEditor(this).getLineStartForOffset(it.offset)
if (it.offset == lineEnd && it.offset != lineStart) {
it.moveToInlayAwareOffset(it.offset - 1)
}
}
}
}
}
/** [adjustCaretPosition] - if true, caret will be moved one char left if it's on the line end */
internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
if (!this.inSelectMode) return
val returnTo = this.vimStateMachine.mode.returnTo
when (returnTo) {
ReturnTo.INSERT -> {
this.vimStateMachine.mode = Mode.INSERT
}
ReturnTo.REPLACE -> {
this.vimStateMachine.mode = Mode.REPLACE
}
null -> {
this.vimStateMachine.mode = Mode.NORMAL()
}
}
SelectionVimListenerSuppressor.lock().use {
this.carets().forEach { vimCaret ->
val caret = (vimCaret as IjVimCaret).caret
caret.removeSelection()
caret.vim.vimSelectionStartClear()
if (adjustCaretPosition) {
val lineEnd = IjVimEditor((this as IjVimEditor).editor).getLineEndForOffset(caret.offset)
val lineStart = IjVimEditor(this.editor).getLineStartForOffset(caret.offset)
if (caret.offset == lineEnd && caret.offset != lineStart) {
caret.moveToInlayAwareOffset(caret.offset - 1)
}
}
}
}
}
internal fun Editor.exitInsertMode(context: DataContext, operatorArguments: OperatorArguments) {
VimPlugin.getChange().processEscape(IjVimEditor(this), IjEditorExecutionContext(context), operatorArguments)
}