mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2024-11-24 22:42:53 +01:00
Compare commits
34 Commits
c79286b9b0
...
9101ca1afc
Author | SHA1 | Date | |
---|---|---|---|
9101ca1afc | |||
7e493e0188 | |||
78b5540636 | |||
97ba6ae997 | |||
9ac1a14604 | |||
3c20feba8d | |||
d23475818a | |||
7f5c9b56ef | |||
c3f5cb4866 | |||
7a25fbfd31 | |||
444880b153 | |||
0ae06e46da | |||
98e085e636 | |||
67c60ae8cc | |||
ffd2433da3 | |||
cfe219250c | |||
68bdae1afc | |||
77859e03e7 | |||
cfd05be288 | |||
|
c0419d6018 | ||
|
ea98e50f65 | ||
|
168174e383 | ||
|
53cd4e1b88 | ||
|
27e3561bb8 | ||
|
9bb9cb13e3 | ||
|
16455f7241 | ||
|
82225aa519 | ||
|
5f2baefc6c | ||
|
cedcf39723 | ||
|
4925d9aada | ||
|
f3e6df32d0 | ||
|
5aaa8752af | ||
|
a1d214316c | ||
|
8a1e3eb066 |
@ -21,7 +21,7 @@ ideaVersion=2024.1.1
|
||||
ideaType=IC
|
||||
downloadIdeaSources=true
|
||||
instrumentPluginCode=true
|
||||
version=chylex-36
|
||||
version=chylex-37
|
||||
javaVersion=17
|
||||
remoteRobotVersion=0.11.22
|
||||
antlrVersion=4.10.1
|
||||
|
@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.group.visual.VimSelection
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.helper.inRepeatMode
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
||||
@ -102,7 +102,7 @@ internal class OperatorAction : VimActionHandler.SingleExecution() {
|
||||
|
||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||
val argument = cmd.argument ?: return false
|
||||
if (!editor.vimStateMachine.isDotRepeatInProgress) {
|
||||
if (!editor.inRepeatMode) {
|
||||
argumentCaptured = argument
|
||||
}
|
||||
val range = getMotionRange(editor, context, argument, operatorArguments)
|
||||
|
@ -17,7 +17,6 @@ import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
|
||||
@CommandOrMotion(keys = ["."], modes = [Mode.NORMAL])
|
||||
@ -25,7 +24,7 @@ internal class RepeatChangeAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
||||
|
||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||
val state = editor.vimStateMachine
|
||||
val state = injector.vimState
|
||||
val lastCommand = VimRepeater.lastChangeCommand
|
||||
|
||||
if (lastCommand == null && Extension.lastExtensionHandler == null) return false
|
||||
|
@ -9,51 +9,75 @@ package com.maddyhome.idea.vim.ex
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.api.VimExOutputPanel
|
||||
import com.maddyhome.idea.vim.api.VimOutputPanel
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.helper.vimExOutput
|
||||
import com.maddyhome.idea.vim.ui.ExOutputPanel
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
// TODO: We need a nicer way to handle output, especially wrt testing, appending + clearing
|
||||
class ExOutputModel private constructor(private val myEditor: Editor) : VimExOutputPanel {
|
||||
class ExOutputModel(private val myEditor: WeakReference<Editor>) : VimOutputPanel {
|
||||
private var isActiveInTestMode = false
|
||||
|
||||
override val isActive: Boolean
|
||||
val editor get() = myEditor.get()
|
||||
|
||||
val isActive: Boolean
|
||||
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ExOutputPanel.isPanelActive(myEditor)
|
||||
editor?.let { ExOutputPanel.getNullablePanel(it) }?.myActive ?: false
|
||||
} else {
|
||||
isActiveInTestMode
|
||||
}
|
||||
|
||||
override var text: String? = null
|
||||
override fun addText(text: String, isNewLine: Boolean) {
|
||||
if (this.text.isNotEmpty() && isNewLine) this.text += "\n$text" else this.text += text
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
if (editor == null) return
|
||||
val currentPanel = injector.outputPanel.getCurrentOutputPanel()
|
||||
if (currentPanel != null && currentPanel != this) currentPanel.close()
|
||||
|
||||
editor!!.vimExOutput = this
|
||||
val exOutputPanel = ExOutputPanel.getInstance(editor!!)
|
||||
if (!exOutputPanel.myActive) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
isActiveInTestMode = true
|
||||
} else {
|
||||
exOutputPanel.activate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var text: String = ""
|
||||
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ExOutputPanel.getInstance(myEditor).text
|
||||
editor?.let { ExOutputPanel.getInstance(it).text } ?: ""
|
||||
} else {
|
||||
// ExOutputPanel always returns a non-null string
|
||||
field ?: ""
|
||||
field
|
||||
}
|
||||
set(value) {
|
||||
// ExOutputPanel will strip a trailing newline. We'll do it now so that tests have the same behaviour. We also
|
||||
// never pass null to ExOutputPanel, but we do store it for tests, so we know if we're active or not
|
||||
val newValue = value?.removeSuffix("\n")
|
||||
val newValue = value.removeSuffix("\n")
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ExOutputPanel.getInstance(myEditor).setText(newValue ?: "")
|
||||
editor?.let { ExOutputPanel.getInstance(it).setText(newValue) }
|
||||
} else {
|
||||
field = newValue
|
||||
isActiveInTestMode = !newValue.isNullOrEmpty()
|
||||
isActiveInTestMode = newValue.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
override fun output(text: String) {
|
||||
fun output(text: String) {
|
||||
this.text = text
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
text = null
|
||||
fun clear() {
|
||||
text = ""
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ExOutputPanel.getInstance(myEditor).close()
|
||||
editor?.let { ExOutputPanel.getInstance(it).close() }
|
||||
}
|
||||
else {
|
||||
isActiveInTestMode = false
|
||||
@ -65,7 +89,7 @@ class ExOutputModel private constructor(private val myEditor: Editor) : VimExOut
|
||||
fun getInstance(editor: Editor): ExOutputModel {
|
||||
var model = editor.vimExOutput
|
||||
if (model == null) {
|
||||
model = ExOutputModel(editor)
|
||||
model = ExOutputModel(WeakReference(editor))
|
||||
editor.vimExOutput = model
|
||||
}
|
||||
return model
|
||||
|
@ -24,8 +24,8 @@ import com.maddyhome.idea.vim.common.CommandAlias
|
||||
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
||||
import com.maddyhome.idea.vim.helper.inRepeatMode
|
||||
import com.maddyhome.idea.vim.helper.noneOfEnum
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.MappingOwner
|
||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
@ -151,7 +151,7 @@ object VimExtensionFacade {
|
||||
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
||||
@JvmStatic
|
||||
fun inputKeyStroke(editor: Editor): KeyStroke {
|
||||
if (editor.vim.vimStateMachine.isDotRepeatInProgress) {
|
||||
if (editor.vim.inRepeatMode) {
|
||||
val input = Extension.consumeKeystroke()
|
||||
LOG.trace("inputKeyStroke: dot repeat in progress. Input: $input")
|
||||
return input ?: error("Not enough keystrokes saved: ${Extension.lastExtensionHandler}")
|
||||
|
@ -46,7 +46,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissin
|
||||
import com.maddyhome.idea.vim.extension.exportOperatorFunction
|
||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
||||
import com.maddyhome.idea.vim.helper.PsiHelper
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
@ -65,7 +64,7 @@ internal class CommentaryExtension : VimExtension {
|
||||
selectionType: SelectionType,
|
||||
resetCaret: Boolean = true,
|
||||
): Boolean {
|
||||
val mode = editor.vimStateMachine.mode
|
||||
val mode = editor.mode
|
||||
if (mode !is Mode.VISUAL) {
|
||||
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||
}
|
||||
|
@ -218,45 +218,6 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
||||
editorEx.addPropertyChangeListener(FontSizeChangeListener.INSTANCE);
|
||||
}
|
||||
|
||||
// We add Vim bindings to all opened editors, including editors used as UI controls rather than just project file
|
||||
// editors. This includes editors used as part of the UI, such as the VCS commit message, or used as read-only
|
||||
// viewers for text output, such as log files in run configurations or the Git Console tab. And editors are used for
|
||||
// interactive stdin/stdout for console-based run configurations.
|
||||
// We want to provide an intuitive experience for working with these additional editors, so we automatically switch
|
||||
// to INSERT mode if they are interactive editors. Recognising these can be a bit tricky.
|
||||
// These additional interactive editors are not file-based, but must have a writable document. However, log output
|
||||
// documents are also writable (the IDE is writing new content as it becomes available) just not user-editable. So
|
||||
// we must also check that the editor is not in read-only "viewer" mode (this includes "rendered" mode, which is
|
||||
// read-only and also hides the caret).
|
||||
// Furthermore, interactive stdin/stdout console output in run configurations is hosted in a read-only editor, but
|
||||
// it can still be edited. The `ConsoleViewImpl` class installs a typing handler that ignores the editor's
|
||||
// `isViewer` property and allows typing if the associated process (if any) is still running. We can get the
|
||||
// editor's console view and check this ourselves, but we have to wait until the editor has finished initialising
|
||||
// before it's available in user data.
|
||||
// Finally, we have a special check for diff windows. If we compare against clipboard, we get a diff editor that is
|
||||
// not file based, is writable, and not a viewer, but we don't want to treat this as an interactive editor.
|
||||
// Note that we need a similar check in `VimEditor.isWritable` to allow Escape to work to exit insert mode. We need
|
||||
// to know that a read-only editor that is hosting a console view with a running process can be treated as writable.
|
||||
Runnable switchToInsertMode = () -> {
|
||||
ExecutionContext context = injector.getExecutionContextManager().getEditorExecutionContext(new IjVimEditor(editor));
|
||||
VimPlugin.getChange().insertBeforeCursor(new IjVimEditor(editor), context);
|
||||
KeyHandler.getInstance().reset(new IjVimEditor(editor));
|
||||
};
|
||||
if (!editor.isViewer() &&
|
||||
!EditorHelper.isFileEditor(editor) &&
|
||||
editor.getDocument().isWritable() &&
|
||||
!CommandStateHelper.inInsertMode(editor) &&
|
||||
editor.getEditorKind() != EditorKind.DIFF) {
|
||||
switchToInsertMode.run();
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(
|
||||
() -> {
|
||||
if (editor.isDisposed()) return;
|
||||
ConsoleViewImpl consoleView = editor.getUserData(ConsoleViewImpl.CONSOLE_VIEW_IN_EDITOR_VIEW);
|
||||
if (consoleView != null && consoleView.isRunning() && !CommandStateHelper.inInsertMode(editor)) {
|
||||
switchToInsertMode.run();
|
||||
}
|
||||
});
|
||||
updateCaretsVisualAttributes(new IjVimEditor(editor));
|
||||
}
|
||||
|
||||
@ -416,7 +377,7 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
||||
// Note that IDE scale is handled by LafManager.lookAndFeelChanged
|
||||
VimCommandLine activeCommandLine = injector.getCommandLine().getActiveCommandLine();
|
||||
if (activeCommandLine != null) {
|
||||
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), false);
|
||||
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), true, false);
|
||||
}
|
||||
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor);
|
||||
if (exOutputModel != null) {
|
||||
|
@ -271,7 +271,7 @@ class FileGroup : VimFileBase() {
|
||||
val msg = StringBuilder()
|
||||
val doc = editor.document
|
||||
|
||||
if (getInstance(IjVimEditor(editor)).mode !is VISUAL) {
|
||||
if (injector.vimState.mode !is VISUAL) {
|
||||
val lp = editor.caretModel.logicalPosition
|
||||
val col = editor.caretModel.offset - doc.getLineStartOffset(lp.line)
|
||||
var endoff = doc.getLineEndOffset(lp.line)
|
||||
|
@ -47,7 +47,6 @@ import com.maddyhome.idea.vim.helper.getNormalizedScrollOffset
|
||||
import com.maddyhome.idea.vim.helper.getNormalizedSideScrollOffset
|
||||
import com.maddyhome.idea.vim.helper.isEndAllowed
|
||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.listener.AppCodeTemplates
|
||||
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
@ -307,13 +306,13 @@ internal class MotionGroup : VimMotionGroupBase() {
|
||||
val editor = fileEditor.editor
|
||||
if (!editor.isDisposed) {
|
||||
editor.vim.let { vimEditor ->
|
||||
when (vimEditor.vimStateMachine.mode) {
|
||||
when (vimEditor.mode) {
|
||||
is Mode.VISUAL -> {
|
||||
vimEditor.exitVisualMode()
|
||||
KeyHandler.getInstance().reset(vimEditor)
|
||||
}
|
||||
is Mode.CMD_LINE -> {
|
||||
injector.processGroup.cancelExEntry(vimEditor, false)
|
||||
injector.processGroup.cancelExEntry(vimEditor, refocusOwningEditor = false, resetCaret = false)
|
||||
ExOutputModel.tryGetInstance(editor)?.close()
|
||||
}
|
||||
else -> {}
|
||||
|
@ -73,7 +73,7 @@ internal object GuicursorChangeListener : EffectiveOptionValueChangeListener {
|
||||
}
|
||||
|
||||
private fun Editor.guicursorMode(): GuiCursorMode {
|
||||
return GuiCursorMode.fromMode(vim.mode, vim.vimStateMachine.isReplaceCharacter)
|
||||
return GuiCursorMode.fromMode(vim.mode, injector.vimState.isReplaceCharacter)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,21 +146,15 @@ internal fun getGuiCursorMode(editor: Editor) = editor.guicursorMode()
|
||||
|
||||
class CaretVisualAttributesListener : IsReplaceCharListener, ModeChangeListener {
|
||||
override fun isReplaceCharChanged(editor: VimEditor) {
|
||||
updateCaretsVisual(editor)
|
||||
updateCaretsVisual()
|
||||
}
|
||||
|
||||
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
|
||||
updateCaretsVisual(editor)
|
||||
updateCaretsVisual()
|
||||
}
|
||||
|
||||
private fun updateCaretsVisual(editor: VimEditor) {
|
||||
if (injector.globalOptions().ideaglobalmode) {
|
||||
updateAllEditorsCaretsVisual()
|
||||
} else {
|
||||
val ijEditor = (editor as IjVimEditor).editor
|
||||
ijEditor.updateCaretsVisualAttributes()
|
||||
ijEditor.updateCaretsVisualPosition()
|
||||
}
|
||||
private fun updateCaretsVisual() {
|
||||
updateAllEditorsCaretsVisual()
|
||||
}
|
||||
|
||||
fun updateAllEditorsCaretsVisual() {
|
||||
|
@ -34,4 +34,4 @@ val Editor.inVisualMode: Boolean
|
||||
|
||||
@get:JvmName("inExMode")
|
||||
internal val Editor.inExMode
|
||||
get() = this.vim.vimStateMachine.mode is Mode.CMD_LINE
|
||||
get() = this.vim.mode is Mode.CMD_LINE
|
||||
|
@ -31,7 +31,7 @@ import com.maddyhome.idea.vim.state.mode.returnTo
|
||||
internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||
if (!this.vim.inSelectMode) return
|
||||
|
||||
val returnTo = this.vim.vimStateMachine.mode.returnTo
|
||||
val returnTo = this.vim.mode.returnTo
|
||||
when (returnTo) {
|
||||
ReturnTo.INSERT -> {
|
||||
this.vim.mode = Mode.INSERT
|
||||
@ -64,7 +64,7 @@ internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||
internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||
if (!this.inSelectMode) return
|
||||
|
||||
val returnTo = this.vimStateMachine.mode.returnTo
|
||||
val returnTo = this.mode.returnTo
|
||||
when (returnTo) {
|
||||
ReturnTo.INSERT -> {
|
||||
this.mode = Mode.INSERT
|
||||
|
@ -180,7 +180,7 @@ internal object ScrollViewHelper {
|
||||
}
|
||||
|
||||
private fun getScrollJump(editor: VimEditor, height: Int): Int {
|
||||
val flags = VimStateMachine.getInstance(editor).executingCommandFlags
|
||||
val flags = injector.vimState.executingCommandFlags
|
||||
val scrollJump = !flags.contains(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)
|
||||
|
||||
// Default value is 1. Zero is a valid value, but we normalise to 1 - we always want to scroll at least one line
|
||||
@ -203,7 +203,7 @@ internal object ScrollViewHelper {
|
||||
val caretColumn = position.column
|
||||
val halfWidth = getApproximateScreenWidth(editor) / 2
|
||||
val scrollOffset = getNormalizedSideScrollOffset(editor)
|
||||
val flags = VimStateMachine.getInstance(vimEditor).executingCommandFlags
|
||||
val flags = injector.vimState.executingCommandFlags
|
||||
val allowSidescroll = !flags.contains(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)
|
||||
val sidescroll = injector.options(vimEditor).sidescroll
|
||||
val offsetLeft = caretColumn - (currentVisualLeftColumn + scrollOffset)
|
||||
|
@ -103,7 +103,6 @@ internal var Editor.vimInitialised: Boolean by userDataOr { false }
|
||||
// ------------------ Editor
|
||||
internal fun unInitializeEditor(editor: Editor) {
|
||||
editor.vimLastSelectionType = null
|
||||
editor.vimStateMachine = null
|
||||
editor.vimMorePanel = null
|
||||
editor.vimExOutput = null
|
||||
editor.vimLastHighlighters = null
|
||||
@ -118,7 +117,6 @@ internal var Editor.vimIncsearchCurrentMatchOffset: Int? by userData()
|
||||
* @see :help visualmode()
|
||||
*/
|
||||
internal var Editor.vimLastSelectionType: SelectionType? by userData()
|
||||
internal var Editor.vimStateMachine: VimStateMachine? by userData()
|
||||
internal var Editor.vimEditorGroup: Boolean by userDataOr { false }
|
||||
internal var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
|
||||
internal var Editor.vimMorePanel: ExOutputPanel? by userData()
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2003-2024 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.listener
|
||||
|
||||
import com.intellij.execution.impl.ConsoleViewImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.EditorKind
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
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.common.EditorListener
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||
import com.maddyhome.idea.vim.helper.inInsertMode
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
|
||||
/**
|
||||
* This listener is similar to the one we introduce in vim-engine to handle focus change,
|
||||
* However, in IJ we would like to start editing in some editors in INSERT mode (e.g., consoles)
|
||||
* It is different to we had previously. Now we go to INSERT mode not only when we focus on the console the first time, but every time.
|
||||
* Going to INSERT on every focus is easier to implement and more consistent (behavior is always the same, you don't have to remember if you are focusing a console the first time or not)
|
||||
*/
|
||||
class IJEditorFocusListener : EditorListener {
|
||||
override fun focusGained(editor: VimEditor) {
|
||||
// We add Vim bindings to all opened editors, including editors used as UI controls rather than just project file
|
||||
// editors. This includes editors used as part of the UI, such as the VCS commit message, or used as read-only
|
||||
// viewers for text output, such as log files in run configurations or the Git Console tab. And editors are used for
|
||||
// interactive stdin/stdout for console-based run configurations.
|
||||
// We want to provide an intuitive experience for working with these additional editors, so we automatically switch
|
||||
// to INSERT mode if they are interactive editors. Recognising these can be a bit tricky.
|
||||
// These additional interactive editors are not file-based, but must have a writable document. However, log output
|
||||
// documents are also writable (the IDE is writing new content as it becomes available) just not user-editable. So
|
||||
// we must also check that the editor is not in read-only "viewer" mode (this includes "rendered" mode, which is
|
||||
// read-only and also hides the caret).
|
||||
// Furthermore, interactive stdin/stdout console output in run configurations is hosted in a read-only editor, but
|
||||
// it can still be edited. The `ConsoleViewImpl` class installs a typing handler that ignores the editor's
|
||||
// `isViewer` property and allows typing if the associated process (if any) is still running. We can get the
|
||||
// editor's console view and check this ourselves, but we have to wait until the editor has finished initialising
|
||||
// before it's available in user data.
|
||||
// Finally, we have a special check for diff windows. If we compare against clipboard, we get a diff editor that is
|
||||
// not file based, is writable, and not a viewer, but we don't want to treat this as an interactive editor.
|
||||
// Note that we need a similar check in `VimEditor.isWritable` to allow Escape to work to exit insert mode. We need
|
||||
// to know that a read-only editor that is hosting a console view with a running process can be treated as writable.
|
||||
val switchToInsertMode = Runnable {
|
||||
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
|
||||
VimPlugin.getChange().insertBeforeCursor(editor, context)
|
||||
}
|
||||
val ijEditor = editor.ij
|
||||
if (!ijEditor.isViewer &&
|
||||
!EditorHelper.isFileEditor(ijEditor) &&
|
||||
ijEditor.document.isWritable &&
|
||||
!ijEditor.inInsertMode && ijEditor.editorKind != EditorKind.DIFF
|
||||
) {
|
||||
switchToInsertMode.run()
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
if (ijEditor.isDisposed) return@invokeLater
|
||||
val consoleView: ConsoleViewImpl? = ijEditor.getUserData(ConsoleViewImpl.CONSOLE_VIEW_IN_EDITOR_VIEW)
|
||||
if (consoleView != null && consoleView.isRunning && !ijEditor.inInsertMode) {
|
||||
switchToInsertMode.run()
|
||||
}
|
||||
}
|
||||
KeyHandler.getInstance().reset(editor)
|
||||
}
|
||||
}
|
@ -37,7 +37,6 @@ import com.maddyhome.idea.vim.action.VimShortcutKeyAction
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.group.NotificationService
|
||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
@ -128,7 +127,6 @@ internal object IdeaSpecifics {
|
||||
}
|
||||
) {
|
||||
editor?.let {
|
||||
val commandState = it.vim.vimStateMachine
|
||||
it.vim.mode = Mode.NORMAL()
|
||||
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
||||
KeyHandler.getInstance().reset(it.vim)
|
||||
|
@ -56,7 +56,6 @@ import com.intellij.util.ExceptionUtil
|
||||
import com.jetbrains.rd.util.lifetime.Lifetime
|
||||
import com.maddyhome.idea.vim.EventFacade
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.KeyHandlerStateResetter
|
||||
import com.maddyhome.idea.vim.VimKeyListener
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.VimTypedActionHandler
|
||||
@ -178,7 +177,7 @@ internal object VimListenerManager {
|
||||
injector.listenersNotifier.macroRecordingListeners.add(macroWidgetListener)
|
||||
injector.listenersNotifier.vimPluginListeners.add(macroWidgetListener)
|
||||
|
||||
injector.listenersNotifier.myEditorListeners.add(KeyHandlerStateResetter())
|
||||
injector.listenersNotifier.myEditorListeners.add(IJEditorFocusListener())
|
||||
injector.listenersNotifier.myEditorListeners.add(ShowCmdWidgetUpdater())
|
||||
}
|
||||
|
||||
@ -746,7 +745,7 @@ internal object VimListenerManager {
|
||||
val editor = event.editor
|
||||
val commandLine = injector.commandLine.getActiveCommandLine()
|
||||
if (commandLine != null) {
|
||||
injector.processGroup.cancelExEntry(editor.vim, false)
|
||||
injector.processGroup.cancelExEntry(editor.vim, refocusOwningEditor = true, resetCaret = false)
|
||||
}
|
||||
|
||||
ExOutputModel.tryGetInstance(editor)?.close()
|
||||
@ -777,7 +776,7 @@ internal object VimListenerManager {
|
||||
) {
|
||||
val commandLine = injector.commandLine.getActiveCommandLine()
|
||||
if (commandLine != null) {
|
||||
injector.processGroup.cancelExEntry(event.editor.vim, false)
|
||||
injector.processGroup.cancelExEntry(event.editor.vim, refocusOwningEditor = true, resetCaret = false)
|
||||
}
|
||||
|
||||
ExOutputModel.getInstance(event.editor).close()
|
||||
|
@ -151,7 +151,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
||||
return editor.caretModel.allCarets.map { IjVimCaret(it) }
|
||||
}
|
||||
|
||||
override var isFirstCaret = false
|
||||
override var isFirstCaret = true
|
||||
override var isReversingCarets = false
|
||||
|
||||
@Suppress("ideavimRunForEachCaret")
|
||||
@ -159,7 +159,6 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
||||
if (editor.vim.inBlockSelection) {
|
||||
action(IjVimCaret(editor.caretModel.primaryCaret))
|
||||
} else {
|
||||
isFirstCaret = true
|
||||
try {
|
||||
editor.caretModel.runForEachCaret({
|
||||
if (it.isValid) {
|
||||
@ -168,13 +167,12 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
||||
}
|
||||
}, false)
|
||||
} finally {
|
||||
isFirstCaret = false
|
||||
isFirstCaret = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
|
||||
isFirstCaret = true
|
||||
isReversingCarets = reverse
|
||||
try {
|
||||
editor.caretModel.runForEachCaret({
|
||||
@ -182,7 +180,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
||||
isFirstCaret = false
|
||||
}, reverse)
|
||||
} finally {
|
||||
isFirstCaret = false
|
||||
isFirstCaret = true
|
||||
isReversingCarets = false
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ package com.maddyhome.idea.vim.newapi
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.serviceIfCreated
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.textarea.TextComponentEditorImpl
|
||||
import com.maddyhome.idea.vim.api.EngineEditorHelper
|
||||
import com.maddyhome.idea.vim.api.ExecutionContextManager
|
||||
@ -28,8 +27,6 @@ import com.maddyhome.idea.vim.api.VimDigraphGroup
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.VimEditorGroup
|
||||
import com.maddyhome.idea.vim.api.VimEnabler
|
||||
import com.maddyhome.idea.vim.api.VimExOutputPanel
|
||||
import com.maddyhome.idea.vim.api.VimExOutputPanelService
|
||||
import com.maddyhome.idea.vim.api.VimExtensionRegistrator
|
||||
import com.maddyhome.idea.vim.api.VimFile
|
||||
import com.maddyhome.idea.vim.api.VimInjector
|
||||
@ -41,6 +38,7 @@ import com.maddyhome.idea.vim.api.VimMarkService
|
||||
import com.maddyhome.idea.vim.api.VimMessages
|
||||
import com.maddyhome.idea.vim.api.VimMotionGroup
|
||||
import com.maddyhome.idea.vim.api.VimOptionGroup
|
||||
import com.maddyhome.idea.vim.api.VimOutputPanelService
|
||||
import com.maddyhome.idea.vim.api.VimProcessGroup
|
||||
import com.maddyhome.idea.vim.api.VimPsiService
|
||||
import com.maddyhome.idea.vim.api.VimRedrawService
|
||||
@ -79,9 +77,7 @@ import com.maddyhome.idea.vim.helper.IjActionExecutor
|
||||
import com.maddyhome.idea.vim.helper.IjEditorHelper
|
||||
import com.maddyhome.idea.vim.helper.IjVimStringParser
|
||||
import com.maddyhome.idea.vim.helper.UndoRedoHelper
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.history.VimHistory
|
||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
||||
import com.maddyhome.idea.vim.macro.VimMacro
|
||||
import com.maddyhome.idea.vim.put.VimPut
|
||||
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
||||
@ -105,12 +101,6 @@ internal class IjVimInjector : VimInjectorBase() {
|
||||
|
||||
override val actionExecutor: VimActionExecutor
|
||||
get() = service<IjActionExecutor>()
|
||||
override val exOutputPanel: VimExOutputPanelService
|
||||
get() = object : VimExOutputPanelService {
|
||||
override fun getPanel(editor: VimEditor): VimExOutputPanel {
|
||||
return ExOutputModel.getInstance(editor.ij)
|
||||
}
|
||||
}
|
||||
override val historyGroup: VimHistory
|
||||
get() = service<HistoryGroup>()
|
||||
override val extensionRegistrator: VimExtensionRegistrator
|
||||
@ -193,6 +183,8 @@ internal class IjVimInjector : VimInjectorBase() {
|
||||
get() = com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
|
||||
override val commandLine: VimCommandLineService
|
||||
get() = service()
|
||||
override val outputPanel: VimOutputPanelService
|
||||
get() = service()
|
||||
|
||||
override val optionGroup: VimOptionGroup
|
||||
get() = service()
|
||||
@ -206,21 +198,14 @@ internal class IjVimInjector : VimInjectorBase() {
|
||||
override val redrawService: VimRedrawService
|
||||
get() = service()
|
||||
|
||||
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
||||
var res = editor.ij.vimStateMachine
|
||||
if (res == null) {
|
||||
res = VimStateMachineImpl()
|
||||
editor.ij.vimStateMachine = res
|
||||
}
|
||||
return res
|
||||
return vimState
|
||||
}
|
||||
|
||||
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||
override fun commandStateFor(editor: Any): VimStateMachine {
|
||||
return when (editor) {
|
||||
is VimEditor -> this.commandStateFor(editor)
|
||||
is Editor -> this.commandStateFor(IjVimEditor(editor))
|
||||
else -> error("Unexpected type: $editor")
|
||||
}
|
||||
return vimState
|
||||
}
|
||||
|
||||
override val engineEditorHelper: EngineEditorHelper
|
||||
|
@ -58,7 +58,7 @@ public class ExOutputPanel extends JPanel {
|
||||
private @Nullable LayoutManager myOldLayout = null;
|
||||
private boolean myWasOpaque = false;
|
||||
|
||||
private boolean myActive = false;
|
||||
public boolean myActive = false;
|
||||
|
||||
private static final VimLogger LOG = injector.getLogger(ExOutputPanel.class);
|
||||
|
||||
@ -90,12 +90,16 @@ public class ExOutputPanel extends JPanel {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
public static @Nullable ExOutputPanel getNullablePanel(@NotNull Editor editor) {
|
||||
return UserDataManager.getVimMorePanel(editor);
|
||||
}
|
||||
|
||||
public static boolean isPanelActive(@NotNull Editor editor) {
|
||||
return UserDataManager.getVimMorePanel(editor) != null;
|
||||
return getNullablePanel(editor) != null;
|
||||
}
|
||||
|
||||
public static @NotNull ExOutputPanel getInstance(@NotNull Editor editor) {
|
||||
ExOutputPanel panel = UserDataManager.getVimMorePanel(editor);
|
||||
ExOutputPanel panel = getNullablePanel(editor);
|
||||
if (panel == null) {
|
||||
panel = new ExOutputPanel(editor);
|
||||
UserDataManager.setVimMorePanel(editor, panel);
|
||||
@ -192,7 +196,7 @@ public class ExOutputPanel extends JPanel {
|
||||
/**
|
||||
* Turns on the more window for the given editor
|
||||
*/
|
||||
private void activate() {
|
||||
public void activate() {
|
||||
JRootPane root = SwingUtilities.getRootPane(myEditor.getContentComponent());
|
||||
myOldGlass = (JComponent)root.getGlassPane();
|
||||
if (myOldGlass != null) {
|
||||
|
@ -15,8 +15,8 @@ import com.maddyhome.idea.vim.api.VimCommandLineService
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
||||
import com.maddyhome.idea.vim.helper.inRepeatMode
|
||||
import com.maddyhome.idea.vim.helper.isCloseKeyStroke
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.ui.ModalEntry
|
||||
@ -31,7 +31,7 @@ class ExEntryPanelService : VimCommandLineService {
|
||||
|
||||
override fun inputString(vimEditor: VimEditor, context: ExecutionContext, prompt: String, finishOn: Char?): String? {
|
||||
val editor = vimEditor.ij
|
||||
if (vimEditor.vimStateMachine.isDotRepeatInProgress) {
|
||||
if (vimEditor.inRepeatMode) {
|
||||
val input = Extension.consumeString()
|
||||
return input ?: error("Not enough strings saved: ${Extension.lastExtensionHandler}")
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ public class ExTextField extends JTextField {
|
||||
clearCurrentAction();
|
||||
Editor editor = ExEntryPanel.instance.getEditor();
|
||||
if (editor != null) {
|
||||
VimPlugin.getProcess().cancelExEntry(new IjVimEditor(editor), true);
|
||||
VimPlugin.getProcess().cancelExEntry(new IjVimEditor(editor), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2003-2024 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.ui.ex
|
||||
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.VimOutputPanel
|
||||
import com.maddyhome.idea.vim.api.VimOutputPanelServiceBase
|
||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class IjOutputPanelService : VimOutputPanelServiceBase() {
|
||||
private var activeOutputPanel: VimOutputPanel? = null
|
||||
|
||||
override fun getCurrentOutputPanel(): VimOutputPanel? {
|
||||
return activeOutputPanel?.takeIf {
|
||||
(it as ExOutputModel)
|
||||
it.isActive && it.editor != null
|
||||
}
|
||||
}
|
||||
|
||||
override fun create(editor: VimEditor, context: ExecutionContext): VimOutputPanel {
|
||||
val panel = ExOutputModel(WeakReference(editor.ij))
|
||||
activeOutputPanel = panel
|
||||
return panel
|
||||
}
|
||||
}
|
@ -24,6 +24,8 @@
|
||||
serviceInterface="com.maddyhome.idea.vim.api.VimProcessGroup"/>
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.ExEntryPanelService"
|
||||
serviceInterface="com.maddyhome.idea.vim.api.VimCommandLineService"/>
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.IjOutputPanelService"
|
||||
serviceInterface="com.maddyhome.idea.vim.api.VimOutputPanelService"/>
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.DigraphGroup"
|
||||
serviceInterface="com.maddyhome.idea.vim.api.VimDigraphGroup"/>
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.HistoryGroup"/>
|
||||
|
@ -10,7 +10,6 @@ package org.jetbrains.plugins.ideavim.action
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||
@ -73,8 +72,6 @@ class MotionActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
doTest(listOf("12", "<Esc>"), content, content, Mode.NORMAL())
|
||||
assertPluginError(false)
|
||||
val vimCommandState = fixture.editor.vimStateMachine
|
||||
kotlin.test.assertNotNull(vimCommandState)
|
||||
assertEmpty(KeyHandler.getInstance().keyHandlerState.commandBuilder.keys.toList())
|
||||
}
|
||||
|
||||
|
@ -154,6 +154,8 @@ class SetCommandTest : VimTestCase() {
|
||||
|
||||
// 'fileencoding' defaults to "", but is automatically detected as UTF-8
|
||||
enterCommand("set number relativenumber scrolloff nrformats")
|
||||
assertExOutput(" nrformats=hex scrolloff=0")
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
assertCommandOutput("set",
|
||||
"""
|
||||
|--- Options ---
|
||||
@ -169,21 +171,20 @@ class SetCommandTest : VimTestCase() {
|
||||
assertCommandOutput("set all",
|
||||
"""
|
||||
|--- Options ---
|
||||
|noargtextobj ideamarks scrolljump=1 notextobj-indent
|
||||
|nobomb ideawrite=all scrolloff=0 textwidth=0
|
||||
|nobreakindent noignorecase selectmode= timeout
|
||||
| colorcolumn= noincsearch shellcmdflag=-x timeoutlen=1000
|
||||
|nocommentary nolist shellxescape=@ notrackactionids
|
||||
|nocursorline nomatchit shellxquote={ undolevels=1000
|
||||
|nodigraph maxmapdepth=20 showcmd virtualedit=
|
||||
|noexchange more showmode novisualbell
|
||||
| fileformat=unix nomultiple-cursors sidescroll=0 visualdelay=100
|
||||
|nogdefault noNERDTree sidescrolloff=0 whichwrap=b,s
|
||||
|nohighlightedyank nrformats=hex nosmartcase wrap
|
||||
| history=50 nonumber nosneak wrapscan
|
||||
|nohlsearch operatorfunc= startofline
|
||||
|noideaglobalmode norelativenumber nosurround
|
||||
|noideajoin scroll=0 notextobj-entire
|
||||
|noargtextobj ideamarks scroll=0 nosurround
|
||||
|nobomb ideawrite=all scrolljump=1 notextobj-entire
|
||||
|nobreakindent noignorecase scrolloff=0 notextobj-indent
|
||||
| colorcolumn= noincsearch selectmode= textwidth=0
|
||||
|nocommentary nolist shellcmdflag=-x timeout
|
||||
|nocursorline nomatchit shellxescape=@ timeoutlen=1000
|
||||
|nodigraph maxmapdepth=20 shellxquote={ notrackactionids
|
||||
|noexchange more showcmd undolevels=1000
|
||||
| fileformat=unix nomultiple-cursors showmode virtualedit=
|
||||
|nogdefault noNERDTree sidescroll=0 novisualbell
|
||||
|nohighlightedyank nrformats=hex sidescrolloff=0 visualdelay=100
|
||||
| history=50 nonumber nosmartcase whichwrap=b,s
|
||||
|nohlsearch operatorfunc= nosneak wrap
|
||||
|noideajoin norelativenumber startofline wrapscan
|
||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
||||
| fileencoding=utf-8
|
||||
| guicursor=n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175
|
||||
@ -220,6 +221,8 @@ class SetCommandTest : VimTestCase() {
|
||||
|
||||
// 'fileencoding' defaults to "", but is automatically detected as UTF-8
|
||||
enterCommand("set number relativenumber scrolloff nrformats")
|
||||
assertExOutput(" nrformats=hex scrolloff=0")
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
assertCommandOutput("set!",
|
||||
"""
|
||||
|--- Options ---
|
||||
@ -254,7 +257,6 @@ class SetCommandTest : VimTestCase() {
|
||||
|nohlsearch
|
||||
| ide=IntelliJ IDEA Community Edition
|
||||
|noideacopypreprocess
|
||||
|noideaglobalmode
|
||||
|noideajoin
|
||||
| ideamarks
|
||||
| idearefactormode=select
|
||||
|
@ -435,21 +435,21 @@ class SetglobalCommandTest : VimTestCase() {
|
||||
setOsSpecificOptionsToSafeValues()
|
||||
assertCommandOutput("setglobal all", """
|
||||
|--- Global option values ---
|
||||
|noargtextobj noideajoin scroll=0 notextobj-entire
|
||||
|nobomb ideamarks scrolljump=1 notextobj-indent
|
||||
|nobreakindent ideawrite=all scrolloff=0 textwidth=0
|
||||
| colorcolumn= noignorecase selectmode= timeout
|
||||
|nocommentary noincsearch shellcmdflag=-x timeoutlen=1000
|
||||
|nocursorline nolist shellxescape=@ notrackactionids
|
||||
|nodigraph nomatchit shellxquote={ undolevels=1000
|
||||
|noexchange maxmapdepth=20 showcmd virtualedit=
|
||||
| fileencoding= more showmode novisualbell
|
||||
| fileformat=unix nomultiple-cursors sidescroll=0 visualdelay=100
|
||||
|nogdefault noNERDTree sidescrolloff=0 whichwrap=b,s
|
||||
|nohighlightedyank nrformats=hex nosmartcase wrap
|
||||
| history=50 nonumber nosneak wrapscan
|
||||
|nohlsearch operatorfunc= startofline
|
||||
|noideaglobalmode norelativenumber nosurround
|
||||
|noargtextobj ideamarks scrolljump=1 notextobj-indent
|
||||
|nobomb ideawrite=all scrolloff=0 textwidth=0
|
||||
|nobreakindent noignorecase selectmode= timeout
|
||||
| colorcolumn= noincsearch shellcmdflag=-x timeoutlen=1000
|
||||
|nocommentary nolist shellxescape=@ notrackactionids
|
||||
|nocursorline nomatchit shellxquote={ undolevels=1000
|
||||
|nodigraph maxmapdepth=20 showcmd virtualedit=
|
||||
|noexchange more showmode novisualbell
|
||||
| fileencoding= nomultiple-cursors sidescroll=0 visualdelay=100
|
||||
| fileformat=unix noNERDTree sidescrolloff=0 whichwrap=b,s
|
||||
|nogdefault nrformats=hex nosmartcase wrap
|
||||
|nohighlightedyank nonumber nosneak wrapscan
|
||||
| history=50 operatorfunc= startofline
|
||||
|nohlsearch norelativenumber nosurround
|
||||
|noideajoin scroll=0 notextobj-entire
|
||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
||||
| guicursor=n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175
|
||||
| ide=IntelliJ IDEA Community Edition
|
||||
@ -523,7 +523,6 @@ class SetglobalCommandTest : VimTestCase() {
|
||||
|nohlsearch
|
||||
| ide=IntelliJ IDEA Community Edition
|
||||
|noideacopypreprocess
|
||||
|noideaglobalmode
|
||||
|noideajoin
|
||||
| ideamarks
|
||||
| idearefactormode=select
|
||||
|
@ -489,21 +489,20 @@ class SetlocalCommandTest : VimTestCase() {
|
||||
setOsSpecificOptionsToSafeValues()
|
||||
assertCommandOutput("setlocal all", """
|
||||
|--- Local option values ---
|
||||
|noargtextobj ideamarks scroll=0 notextobj-entire
|
||||
|nobomb idearefactormode= scrolljump=1 notextobj-indent
|
||||
|nobreakindent ideawrite=all scrolloff=-1 textwidth=0
|
||||
| colorcolumn= noignorecase selectmode= timeout
|
||||
|nocommentary noincsearch shellcmdflag=-x timeoutlen=1000
|
||||
|nocursorline nolist shellxescape=@ notrackactionids
|
||||
|nodigraph nomatchit shellxquote={ virtualedit=
|
||||
|noexchange maxmapdepth=20 showcmd novisualbell
|
||||
| fileformat=unix more showmode visualdelay=100
|
||||
|nogdefault nomultiple-cursors sidescroll=0 whichwrap=b,s
|
||||
|nohighlightedyank noNERDTree sidescrolloff=-1 wrap
|
||||
| history=50 nrformats=hex nosmartcase wrapscan
|
||||
|nohlsearch nonumber nosneak
|
||||
|noideaglobalmode operatorfunc= startofline
|
||||
|--ideajoin norelativenumber nosurround
|
||||
|noargtextobj ideamarks norelativenumber startofline
|
||||
|nobomb idearefactormode= scroll=0 nosurround
|
||||
|nobreakindent ideawrite=all scrolljump=1 notextobj-entire
|
||||
| colorcolumn= noignorecase scrolloff=-1 notextobj-indent
|
||||
|nocommentary noincsearch selectmode= textwidth=0
|
||||
|nocursorline nolist shellcmdflag=-x timeout
|
||||
|nodigraph nomatchit shellxescape=@ timeoutlen=1000
|
||||
|noexchange maxmapdepth=20 shellxquote={ notrackactionids
|
||||
| fileformat=unix more showcmd virtualedit=
|
||||
|nogdefault nomultiple-cursors showmode novisualbell
|
||||
|nohighlightedyank noNERDTree sidescroll=0 visualdelay=100
|
||||
| history=50 nrformats=hex sidescrolloff=-1 whichwrap=b,s
|
||||
|nohlsearch nonumber nosmartcase wrap
|
||||
|--ideajoin operatorfunc= nosneak wrapscan
|
||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
||||
| fileencoding=utf-8
|
||||
| guicursor=n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175
|
||||
@ -577,7 +576,6 @@ class SetlocalCommandTest : VimTestCase() {
|
||||
|nohlsearch
|
||||
| ide=IntelliJ IDEA Community Edition
|
||||
|--ideacopypreprocess
|
||||
|noideaglobalmode
|
||||
|--ideajoin
|
||||
| ideamarks
|
||||
| idearefactormode=
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
package org.jetbrains.plugins.ideavim.ex.implementation.statements
|
||||
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
@ -55,6 +56,7 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
)
|
||||
typeText(commandToKeys("echo F1()"))
|
||||
assertExOutput("5550")
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("555")
|
||||
|
||||
@ -203,10 +205,13 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
),
|
||||
)
|
||||
typeText(commandToKeys("echo F1()"))
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("1")
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("2")
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("3")
|
||||
|
||||
@ -230,9 +235,11 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
),
|
||||
)
|
||||
typeText(commandToKeys("echo F1()"))
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("1")
|
||||
typeText(commandToKeys("delf! F1"))
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("2")
|
||||
|
||||
@ -260,10 +267,12 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
assertPluginError(true)
|
||||
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
||||
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F2()"))
|
||||
assertExOutput("10")
|
||||
assertPluginError(false)
|
||||
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo F1()"))
|
||||
assertPluginError(true)
|
||||
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
||||
@ -289,6 +298,7 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
assertPluginError(true)
|
||||
assertPluginErrorMessageContains("E121: Undefined variable: unknownVar")
|
||||
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
typeText(commandToKeys("echo x"))
|
||||
assertExOutput("10")
|
||||
assertPluginError(false)
|
||||
@ -474,7 +484,12 @@ class FunctionDeclarationTest : VimTestCase() {
|
||||
)
|
||||
typeText(commandToKeys("1,4call F1()"))
|
||||
assertPluginError(false)
|
||||
assertExOutput("1:4")
|
||||
assertExOutput("""
|
||||
1:4
|
||||
1:4
|
||||
1:4
|
||||
1:4
|
||||
""".trimIndent())
|
||||
assertState(
|
||||
"""
|
||||
-----
|
||||
|
@ -16,7 +16,6 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.common.CharacterPosition
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.register.RegisterConstants.ALTERNATE_BUFFER_REGISTER
|
||||
import com.maddyhome.idea.vim.register.RegisterConstants.BLACK_HOLE_REGISTER
|
||||
@ -168,7 +167,7 @@ object NeovimTesting {
|
||||
fun vimMode() = neovimApi.mode.get().mode
|
||||
|
||||
private fun assertMode(editor: Editor) {
|
||||
val ideavimState = editor.vim.vimStateMachine.mode.toVimNotation()
|
||||
val ideavimState = editor.vim.mode.toVimNotation()
|
||||
val neovimState = vimMode()
|
||||
assertEquals(neovimState, ideavimState)
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ class TestOptionConstants {
|
||||
const val whichwrap = "whichwrap"
|
||||
|
||||
// IdeaVim specific
|
||||
const val ideaglobalmode = "ideaglobalmode"
|
||||
const val ideatracetime = "ideatracetime"
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ abstract class VimTestCase {
|
||||
KeyHandler.getInstance().fullReset(editor.vim)
|
||||
}
|
||||
KeyHandler.getInstance().keyHandlerState.reset(Mode.NORMAL())
|
||||
injector.vimState.reset()
|
||||
resetAllOptions()
|
||||
VimPlugin.getKey().resetKeyMappings()
|
||||
VimPlugin.getSearch().resetState()
|
||||
@ -221,6 +222,7 @@ abstract class VimTestCase {
|
||||
VimPlugin.getChange().resetRepeat()
|
||||
VimPlugin.getKey().savedShortcutConflicts.clear()
|
||||
assertTrue(KeyHandler.getInstance().keyStack.isEmpty())
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
|
||||
// Tear down neovim
|
||||
NeovimTesting.tearDown(testInfo)
|
||||
|
@ -156,7 +156,6 @@ private class OptionsVerificator : BeforeTestExecutionCallback, AfterTestExecuti
|
||||
val LOG by lazy { vimLogger<OptionsVerificator>() }
|
||||
private val ignored = setOf(
|
||||
TestOptionConstants.guicursor,
|
||||
TestOptionConstants.ideaglobalmode,
|
||||
TestOptionConstants.ideatracetime,
|
||||
TestIjOptionConstants.ideavimsupport,
|
||||
TestOptionConstants.maxmapdepth,
|
||||
|
@ -27,6 +27,9 @@ class TestInjector(val injector: VimInjector) : VimInjector by injector {
|
||||
tracers[key] = collector
|
||||
}
|
||||
|
||||
override val vimState
|
||||
get() = injector.vimState
|
||||
|
||||
override val optionGroup: VimOptionGroup
|
||||
get() {
|
||||
val tracer = tracers[OptionsTracer] as? OptionsTraceCollector
|
||||
|
@ -18,11 +18,9 @@ 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.common.EditorListener
|
||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.impl.state.toMappingMode
|
||||
import com.maddyhome.idea.vim.key.CommandPartNode
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
@ -167,7 +165,7 @@ class KeyHandler {
|
||||
|
||||
if (commandBuilder.isReady) {
|
||||
logger.trace("Ready command builder. Execute command.")
|
||||
executeCommand(editor, context, editor.vimStateMachine, keyState)
|
||||
executeCommand(editor, context, injector.vimState, keyState)
|
||||
}
|
||||
|
||||
// Don't record the keystroke that stops the recording (unmapped this is `q`)
|
||||
@ -186,7 +184,7 @@ class KeyHandler {
|
||||
logger.trace("Command builder is set to BAD")
|
||||
keyState.commandBuilder.commandState = CurrentCommandState.BAD_COMMAND
|
||||
editor.resetOpPending()
|
||||
editor.vimStateMachine.resetRegisterPending()
|
||||
injector.vimState.resetRegisterPending()
|
||||
editor.isReplaceCharacter = false
|
||||
reset(keyState, editor.mode)
|
||||
}
|
||||
@ -267,6 +265,7 @@ class KeyHandler {
|
||||
*/
|
||||
fun reset(editor: VimEditor) {
|
||||
logger.trace { "Reset is executed" }
|
||||
editor.resetOpPending()
|
||||
keyHandlerState.partialReset(editor.mode)
|
||||
keyHandlerState.commandBuilder.resetAll(getKeyRoot(editor.mode.toMappingMode()))
|
||||
}
|
||||
@ -298,7 +297,7 @@ class KeyHandler {
|
||||
injector.messages.clearError()
|
||||
|
||||
editor.mode = Mode.NORMAL()
|
||||
editor.vimStateMachine.executingCommand = null
|
||||
injector.vimState.executingCommand = null
|
||||
keyHandlerState.digraphSequence.reset()
|
||||
|
||||
reset(keyHandlerState, editor.mode)
|
||||
@ -322,7 +321,7 @@ class KeyHandler {
|
||||
val operatorArguments: OperatorArguments,
|
||||
) : Runnable {
|
||||
override fun run() {
|
||||
val editorState = VimStateMachine.getInstance(editor)
|
||||
val editorState = injector.vimState
|
||||
keyState.commandBuilder.commandState = CurrentCommandState.NEW_COMMAND
|
||||
val register = cmd.register
|
||||
if (register != null) {
|
||||
@ -492,15 +491,4 @@ sealed interface KeyProcessResult {
|
||||
}
|
||||
}
|
||||
|
||||
class KeyHandlerStateResetter : EditorListener {
|
||||
override fun focusGained(editor: VimEditor) {
|
||||
KeyHandler.getInstance().reset(editor)
|
||||
}
|
||||
|
||||
override fun focusLost(editor: VimEditor) {
|
||||
// We do not reset the KeyHandler state here, because a command or a search prompt is not considered to be part of the
|
||||
// editor, and resetting state would break the search functionality.
|
||||
}
|
||||
}
|
||||
|
||||
typealias KeyProcessing = (KeyHandlerState, VimEditor, ExecutionContext) -> Unit
|
||||
|
@ -16,7 +16,6 @@ import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import java.util.*
|
||||
|
||||
@CommandOrMotion(keys = ["<Insert>"], modes = [Mode.INSERT])
|
||||
@ -38,5 +37,5 @@ class InsertInsertAction : VimActionHandler.SingleExecution() {
|
||||
|
||||
private fun processInsert(editor: VimEditor) {
|
||||
editor.insertMode = !editor.insertMode
|
||||
editor.vimStateMachine.toggleInsertOverwrite()
|
||||
editor.toggleInsertOverwrite()
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
import com.maddyhome.idea.vim.helper.pushVisualMode
|
||||
import com.maddyhome.idea.vim.helper.setSelectMode
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
|
||||
/**
|
||||
@ -42,8 +41,7 @@ class SelectToggleVisualMode : VimActionHandler.SingleExecution() {
|
||||
|
||||
companion object {
|
||||
fun toggleMode(editor: VimEditor) {
|
||||
val commandState = editor.vimStateMachine
|
||||
val myMode = commandState.mode
|
||||
val myMode = editor.mode
|
||||
if (myMode is com.maddyhome.idea.vim.state.mode.Mode.VISUAL) {
|
||||
editor.setSelectMode(myMode.selectionType)
|
||||
if (myMode.selectionType != SelectionType.LINE_WISE) {
|
||||
|
@ -51,10 +51,6 @@ open class GlobalOptions(scope: OptionAccessScope): OptionsPropertiesBase(scope)
|
||||
|
||||
// IdeaVim specific options. Put any editor or IDE specific options in IjOptionProperties
|
||||
|
||||
// This is an experimental option that enables global mode for the editor. However,
|
||||
// for the moment it has issues and there is no quality garantee if this option is enabled
|
||||
var ideaglobalmode: Boolean by optionProperty(Options.ideaglobalmode)
|
||||
|
||||
// Temporary flags for work-in-progress behaviour. Hidden from the output of `:set all`
|
||||
var ideastrictmode: Boolean by optionProperty(Options.ideastrictmode)
|
||||
var ideatracetime: Boolean by optionProperty(Options.ideatracetime)
|
||||
|
@ -320,7 +320,6 @@ object Options {
|
||||
)
|
||||
|
||||
// IdeaVim specific options. Put any editor or IDE specific options in IjOptionProperties
|
||||
val ideaglobalmode: ToggleOption = addOption(ToggleOption("ideaglobalmode", GLOBAL, "ideaglobalmode", false))
|
||||
|
||||
// Temporary feature flags for work-in-progress behaviour, diagnostic switches, etc. Hidden from the output of `:set all`
|
||||
val ideastrictmode: ToggleOption = addOption(ToggleOption("ideastrictmode", GLOBAL, "ideastrictmode", false, isHidden = true))
|
||||
|
@ -26,13 +26,11 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
|
||||
import com.maddyhome.idea.vim.helper.CharacterHelper.charType
|
||||
import com.maddyhome.idea.vim.helper.StrictMode
|
||||
import com.maddyhome.idea.vim.helper.usesVirtualSpace
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_END
|
||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_POS
|
||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_START
|
||||
import com.maddyhome.idea.vim.register.RegisterConstants.LAST_INSERTED_TEXT_REGISTER
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine.Companion.getInstance
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import com.maddyhome.idea.vim.state.mode.toReturnTo
|
||||
@ -430,7 +428,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
* @param mode The mode - indicate insert or replace
|
||||
*/
|
||||
override fun initInsert(editor: VimEditor, context: ExecutionContext, mode: Mode) {
|
||||
val state = getInstance(editor)
|
||||
val state = injector.vimState
|
||||
for (caret in editor.nativeCarets()) {
|
||||
caret.vimInsertStart = editor.createLiveMarker(caret.offset, caret.offset)
|
||||
injector.markService.setMark(caret, MARK_CHANGE_START, caret.offset)
|
||||
@ -442,7 +440,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
editor.insertMode = false
|
||||
}
|
||||
if (cmd.flags.contains(CommandFlags.FLAG_NO_REPEAT_INSERT)) {
|
||||
val commandState = getInstance(editor)
|
||||
val commandState = injector.vimState
|
||||
repeatInsert(
|
||||
editor,
|
||||
context,
|
||||
@ -451,7 +449,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
OperatorArguments(false, 1, commandState.mode),
|
||||
)
|
||||
} else {
|
||||
val commandState = getInstance(editor)
|
||||
val commandState = injector.vimState
|
||||
repeatInsert(
|
||||
editor,
|
||||
context,
|
||||
@ -484,7 +482,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
}
|
||||
|
||||
override fun runEnterAction(editor: VimEditor, context: ExecutionContext) {
|
||||
val state = getInstance(editor)
|
||||
val state = injector.vimState
|
||||
if (!state.isDotRepeatInProgress) {
|
||||
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
||||
val action = injector.nativeActionManager.enterAction
|
||||
@ -502,7 +500,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
}
|
||||
|
||||
override fun runEnterAboveAction(editor: VimEditor, context: ExecutionContext) {
|
||||
val state = getInstance(editor)
|
||||
val state = injector.vimState
|
||||
if (!state.isDotRepeatInProgress) {
|
||||
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
||||
val action = injector.nativeActionManager.createLineAboveCaret
|
||||
@ -543,7 +541,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
val markGroup = injector.markService
|
||||
markGroup.setMark(editor, VimMarkService.INSERT_EXIT_MARK)
|
||||
markGroup.setMark(editor, MARK_CHANGE_END)
|
||||
if (getInstance(editor).mode is Mode.REPLACE) {
|
||||
if (editor.mode is Mode.REPLACE) {
|
||||
editor.insertMode = true
|
||||
}
|
||||
var cnt = if (lastInsert != null) lastInsert!!.count else 0
|
||||
@ -558,7 +556,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
if (context != null) {
|
||||
injector.changeGroup.repeatInsert(editor, context, if (cnt == 0) 0 else cnt - 1, true, operatorArguments)
|
||||
}
|
||||
if (getInstance(editor).mode is Mode.INSERT) {
|
||||
if (editor.mode is Mode.INSERT) {
|
||||
updateLastInsertedTextRegister()
|
||||
}
|
||||
|
||||
@ -589,7 +587,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
* @param context The data context
|
||||
*/
|
||||
override fun processEnter(editor: VimEditor, context: ExecutionContext) {
|
||||
if (editor.vimStateMachine.mode is Mode.REPLACE) {
|
||||
if (editor.mode is Mode.REPLACE) {
|
||||
editor.insertMode = true
|
||||
}
|
||||
val enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
|
||||
@ -599,7 +597,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (editor.vimStateMachine.mode is Mode.REPLACE) {
|
||||
if (editor.mode is Mode.REPLACE) {
|
||||
editor.insertMode = false
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ package com.maddyhome.idea.vim.api
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.common.LiveRange
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
||||
@ -126,20 +125,22 @@ import com.maddyhome.idea.vim.state.mode.returnTo
|
||||
*/
|
||||
interface VimEditor {
|
||||
var mode: Mode
|
||||
get() = vimStateMachine.mode
|
||||
get() = injector.vimState.mode
|
||||
set(value) {
|
||||
if (vimStateMachine.mode == value) return
|
||||
val vimState = injector.vimState
|
||||
if (vimState.mode == value) return
|
||||
|
||||
val oldValue = vimStateMachine.mode
|
||||
(vimStateMachine as VimStateMachineImpl).mode = value
|
||||
val oldValue = vimState.mode
|
||||
(vimState as VimStateMachineImpl).mode = value
|
||||
injector.listenersNotifier.notifyModeChanged(this, oldValue)
|
||||
}
|
||||
|
||||
var isReplaceCharacter: Boolean
|
||||
get() = vimStateMachine.isReplaceCharacter
|
||||
var isReplaceCharacter: Boolean
|
||||
get() = injector.vimState.isReplaceCharacter
|
||||
set(value) {
|
||||
if (value != vimStateMachine.isReplaceCharacter) {
|
||||
(vimStateMachine as VimStateMachineImpl).isReplaceCharacter = value
|
||||
val vimState = injector.vimState
|
||||
if (value != vimState.isReplaceCharacter) {
|
||||
(vimState as VimStateMachineImpl).isReplaceCharacter = value
|
||||
injector.listenersNotifier.notifyIsReplaceCharChanged(this)
|
||||
}
|
||||
}
|
||||
@ -162,7 +163,7 @@ interface VimEditor {
|
||||
* which indicated that the buffer is empty. However, the line count is still 1.
|
||||
*
|
||||
* The variable for line count is named `ml_line_count` in `memline` structure. There is a single spot where
|
||||
* `0` is assigned to this variable (at the end of `buf_freeall` public function), however I'm not sure that this affects
|
||||
* `0` is assigned to this variable (at the end of `buf_freeall` function), however I'm not sure that this affects
|
||||
* the opened buffer.
|
||||
* Another thing that I don't understand is that I don't see where this variable is updated. There is a small chance
|
||||
* that this variable doesn't present the line count, so I may be wrong and line count can return zero.
|
||||
@ -208,7 +209,7 @@ interface VimEditor {
|
||||
fun isOneLineMode(): Boolean
|
||||
|
||||
/**
|
||||
* public function for refactoring, get rid of it
|
||||
* function for refactoring, get rid of it
|
||||
*/
|
||||
fun search(
|
||||
pair: Pair<Int, Int>,
|
||||
@ -304,6 +305,23 @@ interface VimEditor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the insert/overwrite state. If currently insert, goto replace mode. If currently replace, goto insert
|
||||
* mode.
|
||||
*/
|
||||
fun toggleInsertOverwrite() {
|
||||
val oldMode = this.mode
|
||||
var newMode = oldMode
|
||||
if (oldMode == Mode.INSERT) {
|
||||
newMode = Mode.REPLACE
|
||||
} else if (oldMode == Mode.REPLACE) {
|
||||
newMode = Mode.INSERT
|
||||
}
|
||||
if (oldMode != newMode) {
|
||||
mode = newMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface MutableVimEditor : VimEditor {
|
||||
|
@ -1,23 +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 com.maddyhome.idea.vim.api
|
||||
|
||||
interface VimExOutputPanelService {
|
||||
fun getPanel(editor: VimEditor): VimExOutputPanel
|
||||
}
|
||||
|
||||
interface VimExOutputPanel {
|
||||
val isActive: Boolean
|
||||
|
||||
val text: String?
|
||||
|
||||
fun output(text: String)
|
||||
fun clear()
|
||||
fun close()
|
||||
}
|
@ -22,6 +22,8 @@ import com.maddyhome.idea.vim.vimscript.services.VariableService
|
||||
import com.maddyhome.idea.vim.yank.VimYankGroup
|
||||
|
||||
interface VimInjector {
|
||||
val vimState: VimStateMachine
|
||||
|
||||
/**
|
||||
* The window used when we need a window but there are no editor windows available.
|
||||
*
|
||||
@ -85,12 +87,14 @@ interface VimInjector {
|
||||
val visualMotionGroup: VimVisualMotionGroup
|
||||
|
||||
// [FINISHED] Class moved to vim-engine, but it's attached to Editor using IJ things
|
||||
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||
fun commandStateFor(editor: VimEditor): VimStateMachine
|
||||
// [FINISHED] Class moved to vim-engine, but it's attached to Editor using IJ things
|
||||
/**
|
||||
* COMPATIBILITY-LAYER: Added new method with Any
|
||||
* Please see: https://jb.gg/zo8n0r
|
||||
*/
|
||||
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||
fun commandStateFor(editor: Any): VimStateMachine
|
||||
|
||||
// !! in progress
|
||||
@ -108,9 +112,6 @@ interface VimInjector {
|
||||
// Can't be fully moved to vim-engine.
|
||||
val actionExecutor: VimActionExecutor
|
||||
|
||||
// Can't be fully moved to vim-engine.
|
||||
val exOutputPanel: VimExOutputPanelService
|
||||
|
||||
// Can't be fully moved to vim-engine.
|
||||
val clipboardManager: VimClipboardManager
|
||||
|
||||
@ -175,6 +176,7 @@ interface VimInjector {
|
||||
val variableService: VariableService
|
||||
|
||||
val commandLine: VimCommandLineService
|
||||
val outputPanel: VimOutputPanelService
|
||||
|
||||
// !! in progress
|
||||
val functionService: VimscriptFunctionService
|
||||
|
@ -16,8 +16,10 @@ import com.maddyhome.idea.vim.api.stubs.VimProcessGroupStub
|
||||
import com.maddyhome.idea.vim.common.VimListenersNotifier
|
||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
||||
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
||||
import com.maddyhome.idea.vim.register.VimRegisterGroupBase
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||
import com.maddyhome.idea.vim.vimscript.services.VariableService
|
||||
import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase
|
||||
import com.maddyhome.idea.vim.yank.VimYankGroup
|
||||
@ -29,6 +31,8 @@ abstract class VimInjectorBase : VimInjector {
|
||||
val registerGroupStub: VimRegisterGroupBase by lazy { object : VimRegisterGroupBase() {} }
|
||||
}
|
||||
|
||||
override val vimState: VimStateMachine = VimStateMachineImpl()
|
||||
|
||||
override val parser: VimStringParser = object : VimStringParserBase() {}
|
||||
override val optionGroup: VimOptionGroup by lazy { object : VimOptionGroupBase() {} }
|
||||
|
||||
|
@ -27,7 +27,6 @@ import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.diagnostic.debug
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.mark.Jump
|
||||
import com.maddyhome.idea.vim.mark.Mark
|
||||
import com.maddyhome.idea.vim.mark.VimMark
|
||||
@ -368,7 +367,7 @@ abstract class VimMarkServiceBase : VimMarkService {
|
||||
val markLineStartOffset = editor.getLineStartOffset(mark.line)
|
||||
val markLineEndOffset = editor.getLineEndOffset(mark.line, true)
|
||||
|
||||
val command = editor.vimStateMachine.executingCommand
|
||||
val command = injector.vimState.executingCommand
|
||||
// If text is being changed from the start of the mark line (a special case for mark deletion)
|
||||
val changeFromMarkLineStart =
|
||||
(command != null && command.type === Command.Type.CHANGE && delStartOffset == markLineStartOffset)
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2003-2024 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.api
|
||||
|
||||
interface VimOutputPanel {
|
||||
/**
|
||||
* The current text displayed in the output panel.
|
||||
* The actual text may be different (if we called the [addText] method and did not call [show] afterward)
|
||||
*/
|
||||
val text: String
|
||||
|
||||
/**
|
||||
* Appends the specified text to the existing content of the output panel.
|
||||
* If 'isNewLine' is true, the text will begin on a new line.
|
||||
*
|
||||
* Note: The full text content is not updated in the display until [show] is invoked.
|
||||
*
|
||||
* @param text The text to append.
|
||||
* @param isNewLine Whether to start the appended text on a new line. Defaults to true.
|
||||
*/
|
||||
fun addText(text: String, isNewLine: Boolean = true)
|
||||
|
||||
/**
|
||||
* This method shows the text output or updates the output text if the panel was already shown
|
||||
*/
|
||||
fun show()
|
||||
|
||||
/**
|
||||
* Disposes or hides the output panel, depending on its implementation.
|
||||
* This may free any associated resources.
|
||||
*/
|
||||
fun close()
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2003-2024 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.api
|
||||
|
||||
interface VimOutputPanelService {
|
||||
/**
|
||||
* Creates a new VimOutputPanel instance for building output without affecting the current panel until displayed.
|
||||
*/
|
||||
// TODO make it possible to pass null instead of editor
|
||||
fun create(editor: VimEditor, context: ExecutionContext): VimOutputPanel
|
||||
|
||||
/**
|
||||
* Retrieves the current VimOutputPanel or creates a new one if none exists.
|
||||
*/
|
||||
fun getOrCreate(editor: VimEditor, context: ExecutionContext): VimOutputPanel
|
||||
|
||||
/**
|
||||
* Returns the currently active VimOutputPanel, if available.
|
||||
*/
|
||||
fun getCurrentOutputPanel(): VimOutputPanel?
|
||||
|
||||
/**
|
||||
* Appends text to the existing output panel or creates a new one with the given text.
|
||||
* Basic method that should be sufficient in most cases.
|
||||
*/
|
||||
fun output(editor: VimEditor, context: ExecutionContext, text: String)
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2003-2024 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.api
|
||||
|
||||
abstract class VimOutputPanelServiceBase : VimOutputPanelService {
|
||||
override fun getOrCreate(editor: VimEditor, context: ExecutionContext): VimOutputPanel {
|
||||
return getCurrentOutputPanel() ?: create(editor, context)
|
||||
}
|
||||
|
||||
override fun output(editor: VimEditor, context: ExecutionContext, text: String) {
|
||||
val panel = getOrCreate(editor, context)
|
||||
panel.addText(text)
|
||||
panel.show()
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ interface VimProcessGroup {
|
||||
// TODO remove me
|
||||
// TODO: Why ^^ ? Should that also include startExEntry?
|
||||
fun processExKey(editor: VimEditor, stroke: KeyStroke, processResultBuilder: KeyProcessResult.KeyProcessResultBuilder): Boolean
|
||||
fun cancelExEntry(editor: VimEditor, resetCaret: Boolean)
|
||||
fun cancelExEntry(editor: VimEditor, refocusOwningEditor: Boolean, resetCaret: Boolean)
|
||||
|
||||
@kotlin.jvm.Throws(java.lang.Exception::class)
|
||||
fun executeCommand(editor: VimEditor, command: String, input: CharSequence?, currentDirectoryPath: String?): String?
|
||||
|
@ -11,7 +11,6 @@ package com.maddyhome.idea.vim.api
|
||||
import com.maddyhome.idea.vim.KeyHandler.Companion.getInstance
|
||||
import com.maddyhome.idea.vim.KeyProcessResult
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.ReturnableFromCmd
|
||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
||||
@ -27,7 +26,7 @@ abstract class VimProcessGroupBase : VimProcessGroup {
|
||||
// Don't allow ex commands in one line editors
|
||||
if (editor.isOneLineMode()) return
|
||||
|
||||
val currentMode = editor.vimStateMachine.mode
|
||||
val currentMode = editor.mode
|
||||
check(currentMode is ReturnableFromCmd) {
|
||||
"Cannot enable cmd mode from current mode $currentMode"
|
||||
}
|
||||
@ -76,12 +75,12 @@ abstract class VimProcessGroupBase : VimProcessGroup {
|
||||
}
|
||||
}
|
||||
|
||||
override fun cancelExEntry(editor: VimEditor, resetCaret: Boolean) {
|
||||
override fun cancelExEntry(editor: VimEditor, refocusOwningEditor: Boolean, resetCaret: Boolean) {
|
||||
// If 'cpoptions' contains 'x', then Escape should execute the command line. This is the default for Vi but not Vim.
|
||||
// IdeaVim does not (currently?) support 'cpoptions', so sticks with Vim's default behaviour. Escape cancels.
|
||||
editor.mode = editor.mode.returnTo()
|
||||
getInstance().reset(editor)
|
||||
injector.commandLine.getActiveCommandLine()?.deactivate(refocusOwningEditor = true, resetCaret)
|
||||
injector.commandLine.getActiveCommandLine()?.deactivate(refocusOwningEditor, resetCaret)
|
||||
}
|
||||
|
||||
private fun getRange(editor: VimEditor, cmd: Command) = when {
|
||||
|
@ -20,7 +20,6 @@ import com.maddyhome.idea.vim.regexp.VimRegex
|
||||
import com.maddyhome.idea.vim.regexp.VimRegexException
|
||||
import com.maddyhome.idea.vim.regexp.VimRegexOptions
|
||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import org.jetbrains.annotations.Contract
|
||||
import org.jetbrains.annotations.Range
|
||||
@ -1454,7 +1453,7 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
while (selectionEndWithoutNewline < sequence.length && sequence[selectionEndWithoutNewline] == '\n') {
|
||||
selectionEndWithoutNewline++
|
||||
}
|
||||
val mode = VimStateMachine.getInstance(editor).mode
|
||||
val mode = editor.mode
|
||||
if (mode is Mode.VISUAL) {
|
||||
if (closingTagTextRange.startOffset == selectionEndWithoutNewline &&
|
||||
openingTag.endOffset == selectionStart
|
||||
|
@ -16,7 +16,6 @@ import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.pushVisualMode
|
||||
import com.maddyhome.idea.vim.helper.setSelectMode
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
@ -72,7 +71,7 @@ abstract class VimVisualMotionGroupBase : VimVisualMotionGroup {
|
||||
} else {
|
||||
editor.mode = Mode.VISUAL(
|
||||
selectionType,
|
||||
returnTo ?: editor.vimStateMachine.mode.returnTo
|
||||
returnTo ?: editor.mode.returnTo
|
||||
)
|
||||
editor.forEachCaret { it.vimSetSelection(it.offset) }
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class VimProcessGroupStub : VimProcessGroupBase() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun cancelExEntry(editor: VimEditor, resetCaret: Boolean) {
|
||||
override fun cancelExEntry(editor: VimEditor, refocusOwningEditor: Boolean, resetCaret: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ import com.maddyhome.idea.vim.api.options
|
||||
import com.maddyhome.idea.vim.diagnostic.debug
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.impl.state.toMappingMode
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
||||
@ -42,13 +41,12 @@ object MappingProcessor: KeyConsumer {
|
||||
|
||||
log.debug("Start processing key mappings.")
|
||||
val keyState = keyProcessResultBuilder.state
|
||||
val commandState = editor.vimStateMachine
|
||||
val mappingState = keyState.mappingState
|
||||
val commandBuilder = keyState.commandBuilder
|
||||
if (commandBuilder.isAwaitingCharOrDigraphArgument() ||
|
||||
commandBuilder.isBuildingMultiKeyCommand() ||
|
||||
isMappingDisabledForKey(key, keyState) ||
|
||||
commandState.isRegisterPending
|
||||
injector.vimState.isRegisterPending
|
||||
) {
|
||||
log.debug("Finish key processing, returning false")
|
||||
return false
|
||||
|
@ -9,6 +9,7 @@
|
||||
package com.maddyhome.idea.vim.common
|
||||
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import java.util.concurrent.ConcurrentLinkedDeque
|
||||
@ -22,30 +23,37 @@ class VimListenersNotifier {
|
||||
val isReplaceCharListeners: MutableCollection<IsReplaceCharListener> = ConcurrentLinkedDeque()
|
||||
|
||||
fun notifyModeChanged(editor: VimEditor, oldMode: Mode) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
modeChangeListeners.forEach { it.modeChanged(editor, oldMode) }
|
||||
}
|
||||
|
||||
fun notifyEditorCreated(editor: VimEditor) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
myEditorListeners.forEach { it.created(editor) }
|
||||
}
|
||||
|
||||
fun notifyEditorReleased(editor: VimEditor) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
myEditorListeners.forEach { it.released(editor) }
|
||||
}
|
||||
|
||||
fun notifyEditorFocusGained(editor: VimEditor) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
myEditorListeners.forEach { it.focusGained(editor) }
|
||||
}
|
||||
|
||||
fun notifyEditorFocusLost(editor: VimEditor) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
myEditorListeners.forEach { it.focusLost(editor) }
|
||||
}
|
||||
|
||||
fun notifyMacroRecordingStarted() {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
macroRecordingListeners.forEach { it.recordingStarted() }
|
||||
}
|
||||
|
||||
fun notifyMacroRecordingFinished() {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
macroRecordingListeners.forEach { it.recordingFinished() }
|
||||
}
|
||||
|
||||
@ -58,6 +66,7 @@ class VimListenersNotifier {
|
||||
}
|
||||
|
||||
fun notifyIsReplaceCharChanged(editor: VimEditor) {
|
||||
if (!injector.enabler.isEnabled()) return // we remove all the listeners when turning the plugin off, but let's do it just in case
|
||||
isReplaceCharListeners.forEach { it.isReplaceCharChanged(editor) }
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.noneOfEnum
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.util.*
|
||||
import javax.swing.KeyStroke
|
||||
@ -114,7 +113,7 @@ abstract class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
||||
}
|
||||
|
||||
if (currentCaret == primaryCaret) {
|
||||
val cmd = VimStateMachine.getInstance(editor).executingCommand ?: run {
|
||||
val cmd = injector.vimState.executingCommand ?: run {
|
||||
injector.messages.indicateError()
|
||||
return
|
||||
}
|
||||
@ -127,7 +126,7 @@ abstract class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
||||
|
||||
logger.debug("Execute command with handler: " + this.javaClass.name)
|
||||
|
||||
val cmd = VimStateMachine.getInstance(editor).executingCommand ?: run {
|
||||
val cmd = injector.vimState.executingCommand ?: run {
|
||||
injector.messages.indicateError()
|
||||
return
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ import com.maddyhome.idea.vim.group.visual.VimSimpleSelection
|
||||
import com.maddyhome.idea.vim.group.visual.VisualChange
|
||||
import com.maddyhome.idea.vim.group.visual.VisualOperation
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.inRepeatMode
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
|
||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||
@ -176,7 +174,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
||||
|
||||
private fun VimEditor.collectSelections(): Map<VimCaret, VimSelection>? {
|
||||
return when {
|
||||
!this.inVisualMode && this.inRepeatMode -> {
|
||||
!this.inVisualMode && injector.vimState.isDotRepeatInProgress -> {
|
||||
if (this.vimLastSelectionType == SelectionType.BLOCK_WISE) {
|
||||
val primaryCaret = primaryCaret()
|
||||
val range = primaryCaret.vimLastVisualOperatorRange ?: return null
|
||||
@ -211,7 +209,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
||||
)
|
||||
}
|
||||
else -> this.nativeCarets().associateWith { caret ->
|
||||
val mode = this.vimStateMachine.mode
|
||||
val mode = this.mode
|
||||
VimSimpleSelection.createWithNative(
|
||||
caret.vimSelectionStart,
|
||||
caret.offset,
|
||||
@ -235,7 +233,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
||||
|
||||
editor.forEachCaret {
|
||||
val change =
|
||||
if (editor.inVisualMode && !editor.inRepeatMode) {
|
||||
if (editor.inVisualMode && !injector.vimState.isDotRepeatInProgress) {
|
||||
VisualOperation.getRange(editor, it, cmd.flags)
|
||||
} else {
|
||||
null
|
||||
|
@ -26,10 +26,7 @@ val TextRange.endOffsetInclusive: Int
|
||||
get() = if (this.endOffset > 0 && this.endOffset > this.startOffset) this.endOffset - 1 else this.endOffset
|
||||
|
||||
val VimEditor.inRepeatMode: Boolean
|
||||
get() = this.vimStateMachine.isDotRepeatInProgress
|
||||
|
||||
val VimEditor.vimStateMachine: VimStateMachine
|
||||
get() = VimStateMachine.getInstance(this)
|
||||
get() = injector.vimState.isDotRepeatInProgress
|
||||
|
||||
val VimEditor.usesVirtualSpace: Boolean
|
||||
get() = injector.options(this).virtualedit.contains(OptionConstants.virtualedit_onemore)
|
||||
|
@ -33,7 +33,7 @@ fun VimEditor.exitVisualMode() {
|
||||
injector.markService.setVisualSelectionMarks(this)
|
||||
this.nativeCarets().forEach { it.vimSelectionStartClear() }
|
||||
|
||||
val returnTo = this.vimStateMachine.mode.returnTo
|
||||
val returnTo = this.mode.returnTo
|
||||
when (returnTo) {
|
||||
ReturnTo.INSERT -> {
|
||||
this.mode = Mode.INSERT
|
||||
|
@ -47,21 +47,12 @@ class VimStateMachineImpl : VimStateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the insert/overwrite state. If currently insert, goto replace mode. If currently replace, goto insert
|
||||
* mode.
|
||||
*/
|
||||
override fun toggleInsertOverwrite() {
|
||||
val oldMode = this.mode
|
||||
var newMode = oldMode
|
||||
if (oldMode == Mode.INSERT) {
|
||||
newMode = Mode.REPLACE
|
||||
} else if (oldMode == Mode.REPLACE) {
|
||||
newMode = Mode.INSERT
|
||||
}
|
||||
if (oldMode != newMode) {
|
||||
mode = newMode
|
||||
}
|
||||
override fun reset() {
|
||||
mode = Mode.NORMAL()
|
||||
isDotRepeatInProgress = false
|
||||
isRegisterPending = false
|
||||
isReplaceCharacter = false
|
||||
executingCommand = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -22,7 +22,6 @@ import com.maddyhome.idea.vim.common.argumentCaptured
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.CommandNode
|
||||
import com.maddyhome.idea.vim.key.CommandPartNode
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
@ -126,9 +125,8 @@ class CommandConsumer : KeyConsumer {
|
||||
processBuilder.addExecutionStep { lambdaKeyState, lambdaEditor, lambdaContext ->
|
||||
logger.trace("Set waiting for the argument")
|
||||
val argumentType = action.argumentType
|
||||
val editorState = lambdaEditor.vimStateMachine
|
||||
startWaitingForArgument(lambdaEditor, lambdaContext, action, argumentType!!, lambdaKeyState, editorState)
|
||||
lambdaKeyState.partialReset(editorState.mode)
|
||||
startWaitingForArgument(lambdaEditor, lambdaContext, action, argumentType!!, lambdaKeyState, injector.vimState)
|
||||
lambdaKeyState.partialReset(lambdaEditor.mode)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,9 @@ package com.maddyhome.idea.vim.key.consumers
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.KeyProcessResult
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
@ -43,7 +43,7 @@ class CommandCountConsumer : KeyConsumer {
|
||||
|
||||
private fun isCommandCountKey(chKey: Char, keyState: KeyHandlerState, editor: VimEditor): Boolean {
|
||||
// Make sure to avoid handling '0' as the start of a count.
|
||||
val editorState = editor.vimStateMachine
|
||||
val editorState = injector.vimState
|
||||
val commandBuilder = keyState.commandBuilder
|
||||
val notRegisterPendingCommand = editorState.mode is Mode.NORMAL && !editorState.isRegisterPending
|
||||
val visualMode = editorState.mode is Mode.VISUAL && !editorState.isRegisterPending
|
||||
|
@ -14,7 +14,6 @@ import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
import java.awt.event.KeyEvent
|
||||
import javax.swing.KeyStroke
|
||||
@ -33,7 +32,7 @@ class RegisterConsumer : KeyConsumer {
|
||||
shouldRecord: KeyHandler.MutableBoolean,
|
||||
): Boolean {
|
||||
logger.trace { "Entered RegisterConsumer" }
|
||||
if (!editor.vimStateMachine.isRegisterPending) return false
|
||||
if (!injector.vimState.isRegisterPending) return false
|
||||
|
||||
logger.trace("Pending mode.")
|
||||
keyProcessResultBuilder.state.commandBuilder.addKey(key)
|
||||
@ -45,7 +44,7 @@ class RegisterConsumer : KeyConsumer {
|
||||
|
||||
private fun handleSelectRegister(editor: VimEditor, chKey: Char, processBuilder: KeyProcessResult.KeyProcessResultBuilder) {
|
||||
logger.trace("Handle select register")
|
||||
editor.vimStateMachine.resetRegisterPending()
|
||||
injector.vimState.resetRegisterPending()
|
||||
if (injector.registerGroup.isValid(chKey)) {
|
||||
logger.trace("Valid register")
|
||||
processBuilder.state.commandBuilder.pushCommandPart(chKey)
|
||||
|
@ -11,9 +11,9 @@ package com.maddyhome.idea.vim.key.consumers
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.KeyProcessResult
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.diagnostic.trace
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||
@ -35,24 +35,25 @@ class SelectRegisterConsumer : KeyConsumer {
|
||||
): Boolean {
|
||||
logger.trace { "Entered SelectRegisterConsumer" }
|
||||
val state = keyProcessResultBuilder.state
|
||||
if (!isSelectRegister(key, state, editor.vimStateMachine)) return false
|
||||
if (!isSelectRegister(key, state)) return false
|
||||
|
||||
logger.trace("Select register")
|
||||
state.commandBuilder.addKey(key)
|
||||
keyProcessResultBuilder.addExecutionStep { _, lambdaEditor, _ ->
|
||||
lambdaEditor.vimStateMachine.isRegisterPending = true
|
||||
injector.vimState.isRegisterPending = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isSelectRegister(key: KeyStroke, keyState: KeyHandlerState, editorState: VimStateMachine): Boolean {
|
||||
if (editorState.mode !is Mode.NORMAL && editorState.mode !is Mode.VISUAL) {
|
||||
private fun isSelectRegister(key: KeyStroke, keyState: KeyHandlerState): Boolean {
|
||||
val vimState = injector.vimState
|
||||
if (vimState.mode !is Mode.NORMAL && vimState.mode !is Mode.VISUAL) {
|
||||
return false
|
||||
}
|
||||
return if (editorState.isRegisterPending) {
|
||||
return if (vimState.isRegisterPending) {
|
||||
true
|
||||
} else {
|
||||
key.keyChar == '"' && !KeyHandler.getInstance().isOperatorPending(editorState.mode, keyState) && keyState.commandBuilder.expectedArgumentType == null
|
||||
key.keyChar == '"' && !KeyHandler.getInstance().isOperatorPending(vimState.mode, keyState) && keyState.commandBuilder.expectedArgumentType == null
|
||||
}
|
||||
}
|
||||
}
|
@ -146,8 +146,8 @@ abstract class VimRegisterGroupBase : VimRegisterGroup {
|
||||
myRegisters.clear()
|
||||
}
|
||||
|
||||
private fun isSmallDeletionSpecialCase(editor: VimEditor): Boolean {
|
||||
val currentCommand = VimStateMachine.getInstance(editor).executingCommand
|
||||
private fun isSmallDeletionSpecialCase(): Boolean {
|
||||
val currentCommand = injector.vimState.executingCommand
|
||||
if (currentCommand != null) {
|
||||
val argument = currentCommand.argument
|
||||
if (argument != null) {
|
||||
@ -264,7 +264,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup {
|
||||
)
|
||||
|
||||
// Deletes go into numbered registers only if text is smaller than a line, register is used or it's a special case
|
||||
if (!smallInlineDeletion && register == defaultRegister || isSmallDeletionSpecialCase(editor)) {
|
||||
if (!smallInlineDeletion && register == defaultRegister || isSmallDeletionSpecialCase()) {
|
||||
// Old 1 goes to 2, etc. Old 8 to 9, old 9 is lost
|
||||
var d = '8'
|
||||
while (d >= '1') {
|
||||
|
@ -8,11 +8,9 @@
|
||||
|
||||
package com.maddyhome.idea.vim.state
|
||||
|
||||
import com.maddyhome.idea.vim.api.globalOptions
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import java.util.*
|
||||
|
||||
@ -40,22 +38,12 @@ interface VimStateMachine {
|
||||
|
||||
fun resetRegisterPending()
|
||||
|
||||
/**
|
||||
* Toggles the insert/overwrite state. If currently insert, goto replace mode. If currently replace, goto insert
|
||||
* mode.
|
||||
*/
|
||||
fun toggleInsertOverwrite()
|
||||
fun reset()
|
||||
|
||||
companion object {
|
||||
private val globalState = VimStateMachineImpl()
|
||||
|
||||
// TODO do we really need this method? Can't we use editor.vimStateMachine?
|
||||
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("injector.vimState", imports = ["com.maddyhome.idea.vim.api.injector"]))
|
||||
fun getInstance(editor: Any?): VimStateMachine {
|
||||
return if (editor == null || injector.globalOptions().ideaglobalmode) {
|
||||
globalState
|
||||
} else {
|
||||
injector.commandStateFor(editor)
|
||||
}
|
||||
return injector.vimState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,10 @@
|
||||
package com.maddyhome.idea.vim.state.mode
|
||||
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
|
||||
val VimEditor.mode: Mode
|
||||
get() = this.vimStateMachine.mode
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
|
||||
val VimEditor.inVisualMode: Boolean
|
||||
get() = this.vimStateMachine.mode is Mode.VISUAL
|
||||
get() = injector.vimState.mode is Mode.VISUAL
|
||||
|
||||
val VimEditor.inBlockSelection: Boolean
|
||||
get() = this.mode.selectionType == SelectionType.BLOCK_WISE
|
||||
|
@ -52,14 +52,14 @@ data class CmdCommand(val range: Range, val argument: String) : Command.SingleEx
|
||||
}
|
||||
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
|
||||
val result: Boolean = if (argument.trim().isEmpty()) {
|
||||
this.listAlias(editor, "")
|
||||
this.listAlias(editor, context, "")
|
||||
} else {
|
||||
this.addAlias(editor)
|
||||
this.addAlias(editor, context)
|
||||
}
|
||||
return if (result) ExecutionResult.Success else ExecutionResult.Error
|
||||
}
|
||||
|
||||
private fun listAlias(editor: VimEditor, filter: String): Boolean {
|
||||
private fun listAlias(editor: VimEditor, context: ExecutionContext, filter: String): Boolean {
|
||||
val lineSeparator = "\n"
|
||||
val allAliases = injector.commandGroup.listAliases()
|
||||
val aliases = allAliases.filter {
|
||||
@ -67,11 +67,11 @@ data class CmdCommand(val range: Range, val argument: String) : Command.SingleEx
|
||||
}.map {
|
||||
"${it.key.padEnd(12)}${it.value.numberOfArguments.padEnd(11)}${it.value.printValue()}"
|
||||
}.sortedWith(String.CASE_INSENSITIVE_ORDER).joinToString(lineSeparator)
|
||||
injector.exOutputPanel.getPanel(editor).output("Name Args Definition$lineSeparator$aliases")
|
||||
injector.outputPanel.output(editor, context, "Name Args Definition$lineSeparator$aliases")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun addAlias(editor: VimEditor): Boolean {
|
||||
private fun addAlias(editor: VimEditor, context: ExecutionContext): Boolean {
|
||||
var argument = argument.trim()
|
||||
|
||||
// Handle overwriting of aliases
|
||||
@ -165,7 +165,7 @@ data class CmdCommand(val range: Range, val argument: String) : Command.SingleEx
|
||||
// No message should be shown either, since there is no editor.
|
||||
return false
|
||||
}
|
||||
return this.listAlias(editor, alias)
|
||||
return this.listAlias(editor, context, alias)
|
||||
}
|
||||
|
||||
// If we are not over-writing existing aliases, and an alias with the same command
|
||||
|
@ -29,7 +29,7 @@ data class EchoCommand(val range: Range, val args: List<Expression>) : Command.S
|
||||
val text = args.joinToString(separator = " ", postfix = "\n") {
|
||||
it.evaluate(editor, context, this).toString()
|
||||
}
|
||||
injector.exOutputPanel.getPanel(editor).output(text)
|
||||
injector.outputPanel.output(editor, context, text)
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
}
|
||||
|
@ -131,9 +131,7 @@ data class GlobalCommand(val range: Range, val argument: String, val invert: Boo
|
||||
globalBusy = true
|
||||
try {
|
||||
if (cmd.isEmpty() || (cmd.length == 1 && cmd[0] == '\n')) {
|
||||
val exOutputModel = injector.exOutputPanel.getPanel(editor)
|
||||
exOutputModel.clear()
|
||||
exOutputModel.output(originalCommandString + '\n' + PrintCommand.getText(editor, lines))
|
||||
injector.outputPanel.output(editor, context, originalCommandString + '\n' + PrintCommand.getText(editor, lines))
|
||||
} else {
|
||||
for (mark in marks) {
|
||||
if (gotInt) break
|
||||
|
@ -105,8 +105,7 @@ data class HistoryCommand(val range: Range, val argument: String) : Command.Sing
|
||||
else -> ""
|
||||
}
|
||||
|
||||
injector.exOutputPanel.getPanel(editor).output(res)
|
||||
|
||||
injector.outputPanel.output(editor, context, res)
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,7 @@ data class JumpsCommand(val range: Range, val argument: String) : Command.Single
|
||||
text.append(">\n")
|
||||
}
|
||||
|
||||
injector.exOutputPanel.getPanel(editor).output(text.toString())
|
||||
|
||||
injector.outputPanel.output(editor, context, text.toString())
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ data class MarksCommand(val range: Range, val argument: String) : Command.Single
|
||||
" ${mark.key} $line $column $text"
|
||||
}
|
||||
|
||||
injector.exOutputPanel.getPanel(editor).output(res)
|
||||
injector.outputPanel.output(editor, context, res)
|
||||
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.ex.ranges.Range
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
||||
|
||||
// todo make it for each caret
|
||||
@ -40,7 +39,6 @@ data class NormalCommand(val range: Range, val argument: String) : Command.Singl
|
||||
argument = argument.substring(1)
|
||||
}
|
||||
|
||||
val commandState = editor.vimStateMachine
|
||||
val rangeUsed = range.size() != 0
|
||||
when (editor.mode) {
|
||||
is Mode.VISUAL -> {
|
||||
@ -50,8 +48,8 @@ data class NormalCommand(val range: Range, val argument: String) : Command.Singl
|
||||
editor.currentCaret().moveToBufferPosition(BufferPosition(selectionStart.line, selectionStart.col))
|
||||
}
|
||||
}
|
||||
is Mode.CMD_LINE -> injector.processGroup.cancelExEntry(editor, false)
|
||||
Mode.INSERT, Mode.REPLACE -> editor.exitInsertMode(context, OperatorArguments(false, 1, commandState.mode))
|
||||
is Mode.CMD_LINE -> injector.processGroup.cancelExEntry(editor, refocusOwningEditor = true, resetCaret = false)
|
||||
Mode.INSERT, Mode.REPLACE -> editor.exitInsertMode(context, OperatorArguments(false, 1, editor.mode))
|
||||
is Mode.SELECT -> editor.exitSelectModeNative(false)
|
||||
is Mode.OP_PENDING, is Mode.NORMAL -> Unit
|
||||
}
|
||||
@ -76,12 +74,12 @@ data class NormalCommand(val range: Range, val argument: String) : Command.Singl
|
||||
}
|
||||
|
||||
// Exit if state leaves as insert or cmd_line
|
||||
val mode = commandState.mode
|
||||
val mode = editor.mode
|
||||
if (mode is Mode.CMD_LINE) {
|
||||
injector.processGroup.cancelExEntry(editor, false)
|
||||
injector.processGroup.cancelExEntry(editor, refocusOwningEditor = true, resetCaret = false)
|
||||
}
|
||||
if (mode is Mode.INSERT || mode is Mode.REPLACE) {
|
||||
editor.exitInsertMode(context, OperatorArguments(false, 1, commandState.mode))
|
||||
editor.exitInsertMode(context, OperatorArguments(false, 1, mode))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,22 +29,12 @@ data class PrintCommand(val range: Range, val argument: String) : Command.Single
|
||||
editor.removeSecondaryCarets()
|
||||
val caret = editor.currentCaret()
|
||||
val lineRange = getLineRangeWithCount(editor, caret)
|
||||
val text = getText(editor, (lineRange.startLine .. lineRange.endLine).toList())
|
||||
|
||||
// Move the caret to the start of the last line of the range
|
||||
val offset = injector.motion.moveCaretToLineStartSkipLeading(editor, lineRange.endLine)
|
||||
caret.moveToOffset(offset)
|
||||
|
||||
// Note that we append to the existing text because we can be called multiple times by the :global command
|
||||
// TODO: We need a better way to handle output. This is not very efficient, especially if we have a lot of output
|
||||
val exOutputModel = injector.exOutputPanel.getPanel(editor)
|
||||
if (!exOutputModel.isActive) {
|
||||
// When we add text, we make the panel active. So if we're appending, it should already be active. If it's not,
|
||||
// make sure it's clear
|
||||
exOutputModel.clear()
|
||||
}
|
||||
val existingText = exOutputModel.text?.let { if (it.isNotEmpty()) it.plus("\n") else it } ?: ""
|
||||
exOutputModel.output(existingText + text)
|
||||
injector.outputPanel.output(editor, context, getText(editor, (lineRange.startLine .. lineRange.endLine).toList()))
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ data class RegistersCommand(val range: Range, val argument: String) : Command.Si
|
||||
" $type \"${reg.name} ${EngineStringHelper.toPrintableCharacters(text).take(200)}"
|
||||
}
|
||||
|
||||
injector.exOutputPanel.getPanel(editor).output(regs)
|
||||
injector.outputPanel.output(editor, context, regs)
|
||||
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ abstract class SetCommandBase(range: Range, argument: String) : Command.SingleEx
|
||||
context: ExecutionContext,
|
||||
operatorArguments: OperatorArguments
|
||||
): ExecutionResult {
|
||||
parseOptionLine(editor, commandArgument, getScope(editor))
|
||||
parseOptionLine(editor, context, commandArgument, getScope(editor))
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ abstract class SetCommandBase(range: Range, argument: String) : Command.SingleEx
|
||||
* @param args The raw text passed to the `:set` command
|
||||
* @throws ExException Thrown if any option names or operations are incorrect
|
||||
*/
|
||||
fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessScope) {
|
||||
fun parseOptionLine(editor: VimEditor, context: ExecutionContext, args: String, scope: OptionAccessScope) {
|
||||
val optionGroup = injector.optionGroup
|
||||
|
||||
val columnFormat = args.startsWith("!")
|
||||
@ -105,14 +105,14 @@ fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessScope) {
|
||||
val changedOptions = optionGroup.getAllOptions()
|
||||
.filter { !optionGroup.isDefaultValue(it, scope) && (!it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest())) }
|
||||
.map { Pair(it.name, it.name) }
|
||||
showOptions(editor, changedOptions, scope, true, columnFormat)
|
||||
showOptions(editor, context, changedOptions, scope, true, columnFormat)
|
||||
return
|
||||
}
|
||||
argument == "all" -> {
|
||||
val options = optionGroup.getAllOptions()
|
||||
.filter { !it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest()) }
|
||||
.map { Pair(it.name, it.name) }
|
||||
showOptions(editor, options, scope, true, columnFormat)
|
||||
showOptions(editor, context, options, scope, true, columnFormat)
|
||||
return
|
||||
}
|
||||
argument == "all&" -> {
|
||||
@ -196,7 +196,7 @@ fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessScope) {
|
||||
|
||||
// Now show all options that were individually requested
|
||||
if (toShow.size > 0) {
|
||||
showOptions(editor, toShow, scope, false, columnFormat)
|
||||
showOptions(editor, context, toShow, scope, false, columnFormat)
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
@ -212,6 +212,7 @@ private fun getValidToggleOption(optionName: String, token: String) =
|
||||
|
||||
private fun showOptions(
|
||||
editor: VimEditor,
|
||||
context: ExecutionContext,
|
||||
nameAndToken: Collection<Pair<String, String>>,
|
||||
scope: OptionAccessScope,
|
||||
showIntro: Boolean,
|
||||
@ -275,7 +276,7 @@ private fun showOptions(
|
||||
appendLine(option)
|
||||
}
|
||||
}
|
||||
injector.exOutputPanel.getPanel(editor).output(output)
|
||||
injector.outputPanel.output(editor, context, output)
|
||||
|
||||
if (unknownOption != null) {
|
||||
throw exExceptionMessage("E518", unknownOption.second)
|
||||
|
Loading…
Reference in New Issue
Block a user