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
|
ideaType=IC
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=chylex-36
|
version=chylex-37
|
||||||
javaVersion=17
|
javaVersion=17
|
||||||
remoteRobotVersion=0.11.22
|
remoteRobotVersion=0.11.22
|
||||||
antlrVersion=4.10.1
|
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.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
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.newapi.ij
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
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 {
|
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||||
val argument = cmd.argument ?: return false
|
val argument = cmd.argument ?: return false
|
||||||
if (!editor.vimStateMachine.isDotRepeatInProgress) {
|
if (!editor.inRepeatMode) {
|
||||||
argumentCaptured = argument
|
argumentCaptured = argument
|
||||||
}
|
}
|
||||||
val range = getMotionRange(editor, context, argument, operatorArguments)
|
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.Command
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["."], modes = [Mode.NORMAL])
|
@CommandOrMotion(keys = ["."], modes = [Mode.NORMAL])
|
||||||
@ -25,7 +24,7 @@ internal class RepeatChangeAction : VimActionHandler.SingleExecution() {
|
|||||||
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||||
val state = editor.vimStateMachine
|
val state = injector.vimState
|
||||||
val lastCommand = VimRepeater.lastChangeCommand
|
val lastCommand = VimRepeater.lastChangeCommand
|
||||||
|
|
||||||
if (lastCommand == null && Extension.lastExtensionHandler == null) return false
|
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.application.ApplicationManager
|
||||||
import com.intellij.openapi.editor.Editor
|
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.helper.vimExOutput
|
||||||
import com.maddyhome.idea.vim.ui.ExOutputPanel
|
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
|
// 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
|
private var isActiveInTestMode = false
|
||||||
|
|
||||||
override val isActive: Boolean
|
val editor get() = myEditor.get()
|
||||||
|
|
||||||
|
val isActive: Boolean
|
||||||
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
|
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
ExOutputPanel.isPanelActive(myEditor)
|
editor?.let { ExOutputPanel.getNullablePanel(it) }?.myActive ?: false
|
||||||
} else {
|
} else {
|
||||||
isActiveInTestMode
|
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) {
|
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
ExOutputPanel.getInstance(myEditor).text
|
editor?.let { ExOutputPanel.getInstance(it).text } ?: ""
|
||||||
} else {
|
} else {
|
||||||
// ExOutputPanel always returns a non-null string
|
// ExOutputPanel always returns a non-null string
|
||||||
field ?: ""
|
field
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
// ExOutputPanel will strip a trailing newline. We'll do it now so that tests have the same behaviour. We also
|
// 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
|
// 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) {
|
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
ExOutputPanel.getInstance(myEditor).setText(newValue ?: "")
|
editor?.let { ExOutputPanel.getInstance(it).setText(newValue) }
|
||||||
} else {
|
} else {
|
||||||
field = newValue
|
field = newValue
|
||||||
isActiveInTestMode = !newValue.isNullOrEmpty()
|
isActiveInTestMode = newValue.isNotEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun output(text: String) {
|
fun output(text: String) {
|
||||||
this.text = text
|
this.text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
fun clear() {
|
||||||
text = null
|
text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
ExOutputPanel.getInstance(myEditor).close()
|
editor?.let { ExOutputPanel.getInstance(it).close() }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isActiveInTestMode = false
|
isActiveInTestMode = false
|
||||||
@ -65,7 +89,7 @@ class ExOutputModel private constructor(private val myEditor: Editor) : VimExOut
|
|||||||
fun getInstance(editor: Editor): ExOutputModel {
|
fun getInstance(editor: Editor): ExOutputModel {
|
||||||
var model = editor.vimExOutput
|
var model = editor.vimExOutput
|
||||||
if (model == null) {
|
if (model == null) {
|
||||||
model = ExOutputModel(editor)
|
model = ExOutputModel(WeakReference(editor))
|
||||||
editor.vimExOutput = model
|
editor.vimExOutput = model
|
||||||
}
|
}
|
||||||
return 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.CommandAliasHandler
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
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.noneOfEnum
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
import com.maddyhome.idea.vim.key.MappingOwner
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
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()'. */
|
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun inputKeyStroke(editor: Editor): KeyStroke {
|
fun inputKeyStroke(editor: Editor): KeyStroke {
|
||||||
if (editor.vim.vimStateMachine.isDotRepeatInProgress) {
|
if (editor.vim.inRepeatMode) {
|
||||||
val input = Extension.consumeKeystroke()
|
val input = Extension.consumeKeystroke()
|
||||||
LOG.trace("inputKeyStroke: dot repeat in progress. Input: $input")
|
LOG.trace("inputKeyStroke: dot repeat in progress. Input: $input")
|
||||||
return input ?: error("Not enough keystrokes saved: ${Extension.lastExtensionHandler}")
|
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.extension.exportOperatorFunction
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.PsiHelper
|
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.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
@ -65,7 +64,7 @@ internal class CommentaryExtension : VimExtension {
|
|||||||
selectionType: SelectionType,
|
selectionType: SelectionType,
|
||||||
resetCaret: Boolean = true,
|
resetCaret: Boolean = true,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val mode = editor.vimStateMachine.mode
|
val mode = editor.mode
|
||||||
if (mode !is Mode.VISUAL) {
|
if (mode !is Mode.VISUAL) {
|
||||||
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||||
}
|
}
|
||||||
|
@ -218,45 +218,6 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
editorEx.addPropertyChangeListener(FontSizeChangeListener.INSTANCE);
|
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));
|
updateCaretsVisualAttributes(new IjVimEditor(editor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +377,7 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
// Note that IDE scale is handled by LafManager.lookAndFeelChanged
|
// Note that IDE scale is handled by LafManager.lookAndFeelChanged
|
||||||
VimCommandLine activeCommandLine = injector.getCommandLine().getActiveCommandLine();
|
VimCommandLine activeCommandLine = injector.getCommandLine().getActiveCommandLine();
|
||||||
if (activeCommandLine != null) {
|
if (activeCommandLine != null) {
|
||||||
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), false);
|
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), true, false);
|
||||||
}
|
}
|
||||||
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor);
|
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor);
|
||||||
if (exOutputModel != null) {
|
if (exOutputModel != null) {
|
||||||
|
@ -271,7 +271,7 @@ class FileGroup : VimFileBase() {
|
|||||||
val msg = StringBuilder()
|
val msg = StringBuilder()
|
||||||
val doc = editor.document
|
val doc = editor.document
|
||||||
|
|
||||||
if (getInstance(IjVimEditor(editor)).mode !is VISUAL) {
|
if (injector.vimState.mode !is VISUAL) {
|
||||||
val lp = editor.caretModel.logicalPosition
|
val lp = editor.caretModel.logicalPosition
|
||||||
val col = editor.caretModel.offset - doc.getLineStartOffset(lp.line)
|
val col = editor.caretModel.offset - doc.getLineStartOffset(lp.line)
|
||||||
var endoff = doc.getLineEndOffset(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.getNormalizedSideScrollOffset
|
||||||
import com.maddyhome.idea.vim.helper.isEndAllowed
|
import com.maddyhome.idea.vim.helper.isEndAllowed
|
||||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
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.listener.AppCodeTemplates
|
||||||
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
@ -307,13 +306,13 @@ internal class MotionGroup : VimMotionGroupBase() {
|
|||||||
val editor = fileEditor.editor
|
val editor = fileEditor.editor
|
||||||
if (!editor.isDisposed) {
|
if (!editor.isDisposed) {
|
||||||
editor.vim.let { vimEditor ->
|
editor.vim.let { vimEditor ->
|
||||||
when (vimEditor.vimStateMachine.mode) {
|
when (vimEditor.mode) {
|
||||||
is Mode.VISUAL -> {
|
is Mode.VISUAL -> {
|
||||||
vimEditor.exitVisualMode()
|
vimEditor.exitVisualMode()
|
||||||
KeyHandler.getInstance().reset(vimEditor)
|
KeyHandler.getInstance().reset(vimEditor)
|
||||||
}
|
}
|
||||||
is Mode.CMD_LINE -> {
|
is Mode.CMD_LINE -> {
|
||||||
injector.processGroup.cancelExEntry(vimEditor, false)
|
injector.processGroup.cancelExEntry(vimEditor, refocusOwningEditor = false, resetCaret = false)
|
||||||
ExOutputModel.tryGetInstance(editor)?.close()
|
ExOutputModel.tryGetInstance(editor)?.close()
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
|
@ -73,7 +73,7 @@ internal object GuicursorChangeListener : EffectiveOptionValueChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Editor.guicursorMode(): GuiCursorMode {
|
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 {
|
class CaretVisualAttributesListener : IsReplaceCharListener, ModeChangeListener {
|
||||||
override fun isReplaceCharChanged(editor: VimEditor) {
|
override fun isReplaceCharChanged(editor: VimEditor) {
|
||||||
updateCaretsVisual(editor)
|
updateCaretsVisual()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
|
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
|
||||||
updateCaretsVisual(editor)
|
updateCaretsVisual()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCaretsVisual(editor: VimEditor) {
|
private fun updateCaretsVisual() {
|
||||||
if (injector.globalOptions().ideaglobalmode) {
|
|
||||||
updateAllEditorsCaretsVisual()
|
updateAllEditorsCaretsVisual()
|
||||||
} else {
|
|
||||||
val ijEditor = (editor as IjVimEditor).editor
|
|
||||||
ijEditor.updateCaretsVisualAttributes()
|
|
||||||
ijEditor.updateCaretsVisualPosition()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAllEditorsCaretsVisual() {
|
fun updateAllEditorsCaretsVisual() {
|
||||||
|
@ -34,4 +34,4 @@ val Editor.inVisualMode: Boolean
|
|||||||
|
|
||||||
@get:JvmName("inExMode")
|
@get:JvmName("inExMode")
|
||||||
internal val Editor.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) {
|
internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||||
if (!this.vim.inSelectMode) return
|
if (!this.vim.inSelectMode) return
|
||||||
|
|
||||||
val returnTo = this.vim.vimStateMachine.mode.returnTo
|
val returnTo = this.vim.mode.returnTo
|
||||||
when (returnTo) {
|
when (returnTo) {
|
||||||
ReturnTo.INSERT -> {
|
ReturnTo.INSERT -> {
|
||||||
this.vim.mode = Mode.INSERT
|
this.vim.mode = Mode.INSERT
|
||||||
@ -64,7 +64,7 @@ internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
|||||||
internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||||
if (!this.inSelectMode) return
|
if (!this.inSelectMode) return
|
||||||
|
|
||||||
val returnTo = this.vimStateMachine.mode.returnTo
|
val returnTo = this.mode.returnTo
|
||||||
when (returnTo) {
|
when (returnTo) {
|
||||||
ReturnTo.INSERT -> {
|
ReturnTo.INSERT -> {
|
||||||
this.mode = Mode.INSERT
|
this.mode = Mode.INSERT
|
||||||
|
@ -180,7 +180,7 @@ internal object ScrollViewHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getScrollJump(editor: VimEditor, height: Int): Int {
|
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)
|
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
|
// 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 caretColumn = position.column
|
||||||
val halfWidth = getApproximateScreenWidth(editor) / 2
|
val halfWidth = getApproximateScreenWidth(editor) / 2
|
||||||
val scrollOffset = getNormalizedSideScrollOffset(editor)
|
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 allowSidescroll = !flags.contains(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)
|
||||||
val sidescroll = injector.options(vimEditor).sidescroll
|
val sidescroll = injector.options(vimEditor).sidescroll
|
||||||
val offsetLeft = caretColumn - (currentVisualLeftColumn + scrollOffset)
|
val offsetLeft = caretColumn - (currentVisualLeftColumn + scrollOffset)
|
||||||
|
@ -103,7 +103,6 @@ internal var Editor.vimInitialised: Boolean by userDataOr { false }
|
|||||||
// ------------------ Editor
|
// ------------------ Editor
|
||||||
internal fun unInitializeEditor(editor: Editor) {
|
internal fun unInitializeEditor(editor: Editor) {
|
||||||
editor.vimLastSelectionType = null
|
editor.vimLastSelectionType = null
|
||||||
editor.vimStateMachine = null
|
|
||||||
editor.vimMorePanel = null
|
editor.vimMorePanel = null
|
||||||
editor.vimExOutput = null
|
editor.vimExOutput = null
|
||||||
editor.vimLastHighlighters = null
|
editor.vimLastHighlighters = null
|
||||||
@ -118,7 +117,6 @@ internal var Editor.vimIncsearchCurrentMatchOffset: Int? by userData()
|
|||||||
* @see :help visualmode()
|
* @see :help visualmode()
|
||||||
*/
|
*/
|
||||||
internal var Editor.vimLastSelectionType: SelectionType? by userData()
|
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.vimEditorGroup: Boolean by userDataOr { false }
|
||||||
internal var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
|
internal var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
|
||||||
internal var Editor.vimMorePanel: ExOutputPanel? by userData()
|
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.api.injector
|
||||||
import com.maddyhome.idea.vim.group.NotificationService
|
import com.maddyhome.idea.vim.group.NotificationService
|
||||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
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.globalIjOptions
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
@ -128,7 +127,6 @@ internal object IdeaSpecifics {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
editor?.let {
|
editor?.let {
|
||||||
val commandState = it.vim.vimStateMachine
|
|
||||||
it.vim.mode = Mode.NORMAL()
|
it.vim.mode = Mode.NORMAL()
|
||||||
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
||||||
KeyHandler.getInstance().reset(it.vim)
|
KeyHandler.getInstance().reset(it.vim)
|
||||||
|
@ -56,7 +56,6 @@ import com.intellij.util.ExceptionUtil
|
|||||||
import com.jetbrains.rd.util.lifetime.Lifetime
|
import com.jetbrains.rd.util.lifetime.Lifetime
|
||||||
import com.maddyhome.idea.vim.EventFacade
|
import com.maddyhome.idea.vim.EventFacade
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.KeyHandlerStateResetter
|
|
||||||
import com.maddyhome.idea.vim.VimKeyListener
|
import com.maddyhome.idea.vim.VimKeyListener
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.VimTypedActionHandler
|
import com.maddyhome.idea.vim.VimTypedActionHandler
|
||||||
@ -178,7 +177,7 @@ internal object VimListenerManager {
|
|||||||
injector.listenersNotifier.macroRecordingListeners.add(macroWidgetListener)
|
injector.listenersNotifier.macroRecordingListeners.add(macroWidgetListener)
|
||||||
injector.listenersNotifier.vimPluginListeners.add(macroWidgetListener)
|
injector.listenersNotifier.vimPluginListeners.add(macroWidgetListener)
|
||||||
|
|
||||||
injector.listenersNotifier.myEditorListeners.add(KeyHandlerStateResetter())
|
injector.listenersNotifier.myEditorListeners.add(IJEditorFocusListener())
|
||||||
injector.listenersNotifier.myEditorListeners.add(ShowCmdWidgetUpdater())
|
injector.listenersNotifier.myEditorListeners.add(ShowCmdWidgetUpdater())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,7 +745,7 @@ internal object VimListenerManager {
|
|||||||
val editor = event.editor
|
val editor = event.editor
|
||||||
val commandLine = injector.commandLine.getActiveCommandLine()
|
val commandLine = injector.commandLine.getActiveCommandLine()
|
||||||
if (commandLine != null) {
|
if (commandLine != null) {
|
||||||
injector.processGroup.cancelExEntry(editor.vim, false)
|
injector.processGroup.cancelExEntry(editor.vim, refocusOwningEditor = true, resetCaret = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExOutputModel.tryGetInstance(editor)?.close()
|
ExOutputModel.tryGetInstance(editor)?.close()
|
||||||
@ -777,7 +776,7 @@ internal object VimListenerManager {
|
|||||||
) {
|
) {
|
||||||
val commandLine = injector.commandLine.getActiveCommandLine()
|
val commandLine = injector.commandLine.getActiveCommandLine()
|
||||||
if (commandLine != null) {
|
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()
|
ExOutputModel.getInstance(event.editor).close()
|
||||||
|
@ -151,7 +151,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
return editor.caretModel.allCarets.map { IjVimCaret(it) }
|
return editor.caretModel.allCarets.map { IjVimCaret(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override var isFirstCaret = false
|
override var isFirstCaret = true
|
||||||
override var isReversingCarets = false
|
override var isReversingCarets = false
|
||||||
|
|
||||||
@Suppress("ideavimRunForEachCaret")
|
@Suppress("ideavimRunForEachCaret")
|
||||||
@ -159,7 +159,6 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
if (editor.vim.inBlockSelection) {
|
if (editor.vim.inBlockSelection) {
|
||||||
action(IjVimCaret(editor.caretModel.primaryCaret))
|
action(IjVimCaret(editor.caretModel.primaryCaret))
|
||||||
} else {
|
} else {
|
||||||
isFirstCaret = true
|
|
||||||
try {
|
try {
|
||||||
editor.caretModel.runForEachCaret({
|
editor.caretModel.runForEachCaret({
|
||||||
if (it.isValid) {
|
if (it.isValid) {
|
||||||
@ -168,13 +167,12 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
} finally {
|
} finally {
|
||||||
isFirstCaret = false
|
isFirstCaret = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
|
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
|
||||||
isFirstCaret = true
|
|
||||||
isReversingCarets = reverse
|
isReversingCarets = reverse
|
||||||
try {
|
try {
|
||||||
editor.caretModel.runForEachCaret({
|
editor.caretModel.runForEachCaret({
|
||||||
@ -182,7 +180,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
isFirstCaret = false
|
isFirstCaret = false
|
||||||
}, reverse)
|
}, reverse)
|
||||||
} finally {
|
} finally {
|
||||||
isFirstCaret = false
|
isFirstCaret = true
|
||||||
isReversingCarets = false
|
isReversingCarets = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ package com.maddyhome.idea.vim.newapi
|
|||||||
import com.intellij.openapi.components.service
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.components.serviceIfCreated
|
import com.intellij.openapi.components.serviceIfCreated
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.openapi.editor.textarea.TextComponentEditorImpl
|
import com.intellij.openapi.editor.textarea.TextComponentEditorImpl
|
||||||
import com.maddyhome.idea.vim.api.EngineEditorHelper
|
import com.maddyhome.idea.vim.api.EngineEditorHelper
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContextManager
|
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.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.VimEditorGroup
|
import com.maddyhome.idea.vim.api.VimEditorGroup
|
||||||
import com.maddyhome.idea.vim.api.VimEnabler
|
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.VimExtensionRegistrator
|
||||||
import com.maddyhome.idea.vim.api.VimFile
|
import com.maddyhome.idea.vim.api.VimFile
|
||||||
import com.maddyhome.idea.vim.api.VimInjector
|
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.VimMessages
|
||||||
import com.maddyhome.idea.vim.api.VimMotionGroup
|
import com.maddyhome.idea.vim.api.VimMotionGroup
|
||||||
import com.maddyhome.idea.vim.api.VimOptionGroup
|
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.VimProcessGroup
|
||||||
import com.maddyhome.idea.vim.api.VimPsiService
|
import com.maddyhome.idea.vim.api.VimPsiService
|
||||||
import com.maddyhome.idea.vim.api.VimRedrawService
|
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.IjEditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.IjVimStringParser
|
import com.maddyhome.idea.vim.helper.IjVimStringParser
|
||||||
import com.maddyhome.idea.vim.helper.UndoRedoHelper
|
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.history.VimHistory
|
||||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
|
||||||
import com.maddyhome.idea.vim.macro.VimMacro
|
import com.maddyhome.idea.vim.macro.VimMacro
|
||||||
import com.maddyhome.idea.vim.put.VimPut
|
import com.maddyhome.idea.vim.put.VimPut
|
||||||
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
||||||
@ -105,12 +101,6 @@ internal class IjVimInjector : VimInjectorBase() {
|
|||||||
|
|
||||||
override val actionExecutor: VimActionExecutor
|
override val actionExecutor: VimActionExecutor
|
||||||
get() = service<IjActionExecutor>()
|
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
|
override val historyGroup: VimHistory
|
||||||
get() = service<HistoryGroup>()
|
get() = service<HistoryGroup>()
|
||||||
override val extensionRegistrator: VimExtensionRegistrator
|
override val extensionRegistrator: VimExtensionRegistrator
|
||||||
@ -193,6 +183,8 @@ internal class IjVimInjector : VimInjectorBase() {
|
|||||||
get() = com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
|
get() = com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
|
||||||
override val commandLine: VimCommandLineService
|
override val commandLine: VimCommandLineService
|
||||||
get() = service()
|
get() = service()
|
||||||
|
override val outputPanel: VimOutputPanelService
|
||||||
|
get() = service()
|
||||||
|
|
||||||
override val optionGroup: VimOptionGroup
|
override val optionGroup: VimOptionGroup
|
||||||
get() = service()
|
get() = service()
|
||||||
@ -206,21 +198,14 @@ internal class IjVimInjector : VimInjectorBase() {
|
|||||||
override val redrawService: VimRedrawService
|
override val redrawService: VimRedrawService
|
||||||
get() = service()
|
get() = service()
|
||||||
|
|
||||||
|
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||||
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
||||||
var res = editor.ij.vimStateMachine
|
return vimState
|
||||||
if (res == null) {
|
|
||||||
res = VimStateMachineImpl()
|
|
||||||
editor.ij.vimStateMachine = res
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||||
override fun commandStateFor(editor: Any): VimStateMachine {
|
override fun commandStateFor(editor: Any): VimStateMachine {
|
||||||
return when (editor) {
|
return vimState
|
||||||
is VimEditor -> this.commandStateFor(editor)
|
|
||||||
is Editor -> this.commandStateFor(IjVimEditor(editor))
|
|
||||||
else -> error("Unexpected type: $editor")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val engineEditorHelper: EngineEditorHelper
|
override val engineEditorHelper: EngineEditorHelper
|
||||||
|
@ -58,7 +58,7 @@ public class ExOutputPanel extends JPanel {
|
|||||||
private @Nullable LayoutManager myOldLayout = null;
|
private @Nullable LayoutManager myOldLayout = null;
|
||||||
private boolean myWasOpaque = false;
|
private boolean myWasOpaque = false;
|
||||||
|
|
||||||
private boolean myActive = false;
|
public boolean myActive = false;
|
||||||
|
|
||||||
private static final VimLogger LOG = injector.getLogger(ExOutputPanel.class);
|
private static final VimLogger LOG = injector.getLogger(ExOutputPanel.class);
|
||||||
|
|
||||||
@ -90,12 +90,16 @@ public class ExOutputPanel extends JPanel {
|
|||||||
updateUI();
|
updateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @Nullable ExOutputPanel getNullablePanel(@NotNull Editor editor) {
|
||||||
|
return UserDataManager.getVimMorePanel(editor);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isPanelActive(@NotNull Editor 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) {
|
public static @NotNull ExOutputPanel getInstance(@NotNull Editor editor) {
|
||||||
ExOutputPanel panel = UserDataManager.getVimMorePanel(editor);
|
ExOutputPanel panel = getNullablePanel(editor);
|
||||||
if (panel == null) {
|
if (panel == null) {
|
||||||
panel = new ExOutputPanel(editor);
|
panel = new ExOutputPanel(editor);
|
||||||
UserDataManager.setVimMorePanel(editor, panel);
|
UserDataManager.setVimMorePanel(editor, panel);
|
||||||
@ -192,7 +196,7 @@ public class ExOutputPanel extends JPanel {
|
|||||||
/**
|
/**
|
||||||
* Turns on the more window for the given editor
|
* Turns on the more window for the given editor
|
||||||
*/
|
*/
|
||||||
private void activate() {
|
public void activate() {
|
||||||
JRootPane root = SwingUtilities.getRootPane(myEditor.getContentComponent());
|
JRootPane root = SwingUtilities.getRootPane(myEditor.getContentComponent());
|
||||||
myOldGlass = (JComponent)root.getGlassPane();
|
myOldGlass = (JComponent)root.getGlassPane();
|
||||||
if (myOldGlass != null) {
|
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.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
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.isCloseKeyStroke
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.ui.ModalEntry
|
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? {
|
override fun inputString(vimEditor: VimEditor, context: ExecutionContext, prompt: String, finishOn: Char?): String? {
|
||||||
val editor = vimEditor.ij
|
val editor = vimEditor.ij
|
||||||
if (vimEditor.vimStateMachine.isDotRepeatInProgress) {
|
if (vimEditor.inRepeatMode) {
|
||||||
val input = Extension.consumeString()
|
val input = Extension.consumeString()
|
||||||
return input ?: error("Not enough strings saved: ${Extension.lastExtensionHandler}")
|
return input ?: error("Not enough strings saved: ${Extension.lastExtensionHandler}")
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ public class ExTextField extends JTextField {
|
|||||||
clearCurrentAction();
|
clearCurrentAction();
|
||||||
Editor editor = ExEntryPanel.instance.getEditor();
|
Editor editor = ExEntryPanel.instance.getEditor();
|
||||||
if (editor != null) {
|
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"/>
|
serviceInterface="com.maddyhome.idea.vim.api.VimProcessGroup"/>
|
||||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.ExEntryPanelService"
|
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.ExEntryPanelService"
|
||||||
serviceInterface="com.maddyhome.idea.vim.api.VimCommandLineService"/>
|
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"
|
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.DigraphGroup"
|
||||||
serviceInterface="com.maddyhome.idea.vim.api.VimDigraphGroup"/>
|
serviceInterface="com.maddyhome.idea.vim.api.VimDigraphGroup"/>
|
||||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.HistoryGroup"/>
|
<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.KeyHandler
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.injector
|
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.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
@ -73,8 +72,6 @@ class MotionActionTest : VimTestCase() {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
doTest(listOf("12", "<Esc>"), content, content, Mode.NORMAL())
|
doTest(listOf("12", "<Esc>"), content, content, Mode.NORMAL())
|
||||||
assertPluginError(false)
|
assertPluginError(false)
|
||||||
val vimCommandState = fixture.editor.vimStateMachine
|
|
||||||
kotlin.test.assertNotNull(vimCommandState)
|
|
||||||
assertEmpty(KeyHandler.getInstance().keyHandlerState.commandBuilder.keys.toList())
|
assertEmpty(KeyHandler.getInstance().keyHandlerState.commandBuilder.keys.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +154,8 @@ class SetCommandTest : VimTestCase() {
|
|||||||
|
|
||||||
// 'fileencoding' defaults to "", but is automatically detected as UTF-8
|
// 'fileencoding' defaults to "", but is automatically detected as UTF-8
|
||||||
enterCommand("set number relativenumber scrolloff nrformats")
|
enterCommand("set number relativenumber scrolloff nrformats")
|
||||||
|
assertExOutput(" nrformats=hex scrolloff=0")
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
assertCommandOutput("set",
|
assertCommandOutput("set",
|
||||||
"""
|
"""
|
||||||
|--- Options ---
|
|--- Options ---
|
||||||
@ -169,21 +171,20 @@ class SetCommandTest : VimTestCase() {
|
|||||||
assertCommandOutput("set all",
|
assertCommandOutput("set all",
|
||||||
"""
|
"""
|
||||||
|--- Options ---
|
|--- Options ---
|
||||||
|noargtextobj ideamarks scrolljump=1 notextobj-indent
|
|noargtextobj ideamarks scroll=0 nosurround
|
||||||
|nobomb ideawrite=all scrolloff=0 textwidth=0
|
|nobomb ideawrite=all scrolljump=1 notextobj-entire
|
||||||
|nobreakindent noignorecase selectmode= timeout
|
|nobreakindent noignorecase scrolloff=0 notextobj-indent
|
||||||
| colorcolumn= noincsearch shellcmdflag=-x timeoutlen=1000
|
| colorcolumn= noincsearch selectmode= textwidth=0
|
||||||
|nocommentary nolist shellxescape=@ notrackactionids
|
|nocommentary nolist shellcmdflag=-x timeout
|
||||||
|nocursorline nomatchit shellxquote={ undolevels=1000
|
|nocursorline nomatchit shellxescape=@ timeoutlen=1000
|
||||||
|nodigraph maxmapdepth=20 showcmd virtualedit=
|
|nodigraph maxmapdepth=20 shellxquote={ notrackactionids
|
||||||
|noexchange more showmode novisualbell
|
|noexchange more showcmd undolevels=1000
|
||||||
| fileformat=unix nomultiple-cursors sidescroll=0 visualdelay=100
|
| fileformat=unix nomultiple-cursors showmode virtualedit=
|
||||||
|nogdefault noNERDTree sidescrolloff=0 whichwrap=b,s
|
|nogdefault noNERDTree sidescroll=0 novisualbell
|
||||||
|nohighlightedyank nrformats=hex nosmartcase wrap
|
|nohighlightedyank nrformats=hex sidescrolloff=0 visualdelay=100
|
||||||
| history=50 nonumber nosneak wrapscan
|
| history=50 nonumber nosmartcase whichwrap=b,s
|
||||||
|nohlsearch operatorfunc= startofline
|
|nohlsearch operatorfunc= nosneak wrap
|
||||||
|noideaglobalmode norelativenumber nosurround
|
|noideajoin norelativenumber startofline wrapscan
|
||||||
|noideajoin scroll=0 notextobj-entire
|
|
||||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
||||||
| fileencoding=utf-8
|
| 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
|
| 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
|
// 'fileencoding' defaults to "", but is automatically detected as UTF-8
|
||||||
enterCommand("set number relativenumber scrolloff nrformats")
|
enterCommand("set number relativenumber scrolloff nrformats")
|
||||||
|
assertExOutput(" nrformats=hex scrolloff=0")
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
assertCommandOutput("set!",
|
assertCommandOutput("set!",
|
||||||
"""
|
"""
|
||||||
|--- Options ---
|
|--- Options ---
|
||||||
@ -254,7 +257,6 @@ class SetCommandTest : VimTestCase() {
|
|||||||
|nohlsearch
|
|nohlsearch
|
||||||
| ide=IntelliJ IDEA Community Edition
|
| ide=IntelliJ IDEA Community Edition
|
||||||
|noideacopypreprocess
|
|noideacopypreprocess
|
||||||
|noideaglobalmode
|
|
||||||
|noideajoin
|
|noideajoin
|
||||||
| ideamarks
|
| ideamarks
|
||||||
| idearefactormode=select
|
| idearefactormode=select
|
||||||
|
@ -435,21 +435,21 @@ class SetglobalCommandTest : VimTestCase() {
|
|||||||
setOsSpecificOptionsToSafeValues()
|
setOsSpecificOptionsToSafeValues()
|
||||||
assertCommandOutput("setglobal all", """
|
assertCommandOutput("setglobal all", """
|
||||||
|--- Global option values ---
|
|--- Global option values ---
|
||||||
|noargtextobj noideajoin scroll=0 notextobj-entire
|
|noargtextobj ideamarks scrolljump=1 notextobj-indent
|
||||||
|nobomb ideamarks scrolljump=1 notextobj-indent
|
|nobomb ideawrite=all scrolloff=0 textwidth=0
|
||||||
|nobreakindent ideawrite=all scrolloff=0 textwidth=0
|
|nobreakindent noignorecase selectmode= timeout
|
||||||
| colorcolumn= noignorecase selectmode= timeout
|
| colorcolumn= noincsearch shellcmdflag=-x timeoutlen=1000
|
||||||
|nocommentary noincsearch shellcmdflag=-x timeoutlen=1000
|
|nocommentary nolist shellxescape=@ notrackactionids
|
||||||
|nocursorline nolist shellxescape=@ notrackactionids
|
|nocursorline nomatchit shellxquote={ undolevels=1000
|
||||||
|nodigraph nomatchit shellxquote={ undolevels=1000
|
|nodigraph maxmapdepth=20 showcmd virtualedit=
|
||||||
|noexchange maxmapdepth=20 showcmd virtualedit=
|
|noexchange more showmode novisualbell
|
||||||
| fileencoding= more showmode novisualbell
|
| fileencoding= nomultiple-cursors sidescroll=0 visualdelay=100
|
||||||
| fileformat=unix nomultiple-cursors sidescroll=0 visualdelay=100
|
| fileformat=unix noNERDTree sidescrolloff=0 whichwrap=b,s
|
||||||
|nogdefault noNERDTree sidescrolloff=0 whichwrap=b,s
|
|nogdefault nrformats=hex nosmartcase wrap
|
||||||
|nohighlightedyank nrformats=hex nosmartcase wrap
|
|nohighlightedyank nonumber nosneak wrapscan
|
||||||
| history=50 nonumber nosneak wrapscan
|
| history=50 operatorfunc= startofline
|
||||||
|nohlsearch operatorfunc= startofline
|
|nohlsearch norelativenumber nosurround
|
||||||
|noideaglobalmode norelativenumber nosurround
|
|noideajoin scroll=0 notextobj-entire
|
||||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
| 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
|
| 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
|
| ide=IntelliJ IDEA Community Edition
|
||||||
@ -523,7 +523,6 @@ class SetglobalCommandTest : VimTestCase() {
|
|||||||
|nohlsearch
|
|nohlsearch
|
||||||
| ide=IntelliJ IDEA Community Edition
|
| ide=IntelliJ IDEA Community Edition
|
||||||
|noideacopypreprocess
|
|noideacopypreprocess
|
||||||
|noideaglobalmode
|
|
||||||
|noideajoin
|
|noideajoin
|
||||||
| ideamarks
|
| ideamarks
|
||||||
| idearefactormode=select
|
| idearefactormode=select
|
||||||
|
@ -489,21 +489,20 @@ class SetlocalCommandTest : VimTestCase() {
|
|||||||
setOsSpecificOptionsToSafeValues()
|
setOsSpecificOptionsToSafeValues()
|
||||||
assertCommandOutput("setlocal all", """
|
assertCommandOutput("setlocal all", """
|
||||||
|--- Local option values ---
|
|--- Local option values ---
|
||||||
|noargtextobj ideamarks scroll=0 notextobj-entire
|
|noargtextobj ideamarks norelativenumber startofline
|
||||||
|nobomb idearefactormode= scrolljump=1 notextobj-indent
|
|nobomb idearefactormode= scroll=0 nosurround
|
||||||
|nobreakindent ideawrite=all scrolloff=-1 textwidth=0
|
|nobreakindent ideawrite=all scrolljump=1 notextobj-entire
|
||||||
| colorcolumn= noignorecase selectmode= timeout
|
| colorcolumn= noignorecase scrolloff=-1 notextobj-indent
|
||||||
|nocommentary noincsearch shellcmdflag=-x timeoutlen=1000
|
|nocommentary noincsearch selectmode= textwidth=0
|
||||||
|nocursorline nolist shellxescape=@ notrackactionids
|
|nocursorline nolist shellcmdflag=-x timeout
|
||||||
|nodigraph nomatchit shellxquote={ virtualedit=
|
|nodigraph nomatchit shellxescape=@ timeoutlen=1000
|
||||||
|noexchange maxmapdepth=20 showcmd novisualbell
|
|noexchange maxmapdepth=20 shellxquote={ notrackactionids
|
||||||
| fileformat=unix more showmode visualdelay=100
|
| fileformat=unix more showcmd virtualedit=
|
||||||
|nogdefault nomultiple-cursors sidescroll=0 whichwrap=b,s
|
|nogdefault nomultiple-cursors showmode novisualbell
|
||||||
|nohighlightedyank noNERDTree sidescrolloff=-1 wrap
|
|nohighlightedyank noNERDTree sidescroll=0 visualdelay=100
|
||||||
| history=50 nrformats=hex nosmartcase wrapscan
|
| history=50 nrformats=hex sidescrolloff=-1 whichwrap=b,s
|
||||||
|nohlsearch nonumber nosneak
|
|nohlsearch nonumber nosmartcase wrap
|
||||||
|noideaglobalmode operatorfunc= startofline
|
|--ideajoin operatorfunc= nosneak wrapscan
|
||||||
|--ideajoin norelativenumber nosurround
|
|
||||||
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
| clipboard=ideaput,autoselect,exclude:cons\|linux
|
||||||
| fileencoding=utf-8
|
| 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
|
| 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
|
|nohlsearch
|
||||||
| ide=IntelliJ IDEA Community Edition
|
| ide=IntelliJ IDEA Community Edition
|
||||||
|--ideacopypreprocess
|
|--ideacopypreprocess
|
||||||
|noideaglobalmode
|
|
||||||
|--ideajoin
|
|--ideajoin
|
||||||
| ideamarks
|
| ideamarks
|
||||||
| idearefactormode=
|
| idearefactormode=
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.plugins.ideavim.ex.implementation.statements
|
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.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@ -55,6 +56,7 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
)
|
)
|
||||||
typeText(commandToKeys("echo F1()"))
|
typeText(commandToKeys("echo F1()"))
|
||||||
assertExOutput("5550")
|
assertExOutput("5550")
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("555")
|
assertExOutput("555")
|
||||||
|
|
||||||
@ -203,10 +205,13 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
typeText(commandToKeys("echo F1()"))
|
typeText(commandToKeys("echo F1()"))
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("1")
|
assertExOutput("1")
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("2")
|
assertExOutput("2")
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("3")
|
assertExOutput("3")
|
||||||
|
|
||||||
@ -230,9 +235,11 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
typeText(commandToKeys("echo F1()"))
|
typeText(commandToKeys("echo F1()"))
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("1")
|
assertExOutput("1")
|
||||||
typeText(commandToKeys("delf! F1"))
|
typeText(commandToKeys("delf! F1"))
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("2")
|
assertExOutput("2")
|
||||||
|
|
||||||
@ -260,10 +267,12 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
assertPluginError(true)
|
assertPluginError(true)
|
||||||
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
||||||
|
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F2()"))
|
typeText(commandToKeys("echo F2()"))
|
||||||
assertExOutput("10")
|
assertExOutput("10")
|
||||||
assertPluginError(false)
|
assertPluginError(false)
|
||||||
|
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo F1()"))
|
typeText(commandToKeys("echo F1()"))
|
||||||
assertPluginError(true)
|
assertPluginError(true)
|
||||||
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
assertPluginErrorMessageContains("E121: Undefined variable: x")
|
||||||
@ -289,6 +298,7 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
assertPluginError(true)
|
assertPluginError(true)
|
||||||
assertPluginErrorMessageContains("E121: Undefined variable: unknownVar")
|
assertPluginErrorMessageContains("E121: Undefined variable: unknownVar")
|
||||||
|
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
typeText(commandToKeys("echo x"))
|
typeText(commandToKeys("echo x"))
|
||||||
assertExOutput("10")
|
assertExOutput("10")
|
||||||
assertPluginError(false)
|
assertPluginError(false)
|
||||||
@ -474,7 +484,12 @@ class FunctionDeclarationTest : VimTestCase() {
|
|||||||
)
|
)
|
||||||
typeText(commandToKeys("1,4call F1()"))
|
typeText(commandToKeys("1,4call F1()"))
|
||||||
assertPluginError(false)
|
assertPluginError(false)
|
||||||
assertExOutput("1:4")
|
assertExOutput("""
|
||||||
|
1:4
|
||||||
|
1:4
|
||||||
|
1:4
|
||||||
|
1:4
|
||||||
|
""".trimIndent())
|
||||||
assertState(
|
assertState(
|
||||||
"""
|
"""
|
||||||
-----
|
-----
|
||||||
|
@ -16,7 +16,6 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.common.CharacterPosition
|
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.newapi.vim
|
||||||
import com.maddyhome.idea.vim.register.RegisterConstants.ALTERNATE_BUFFER_REGISTER
|
import com.maddyhome.idea.vim.register.RegisterConstants.ALTERNATE_BUFFER_REGISTER
|
||||||
import com.maddyhome.idea.vim.register.RegisterConstants.BLACK_HOLE_REGISTER
|
import com.maddyhome.idea.vim.register.RegisterConstants.BLACK_HOLE_REGISTER
|
||||||
@ -168,7 +167,7 @@ object NeovimTesting {
|
|||||||
fun vimMode() = neovimApi.mode.get().mode
|
fun vimMode() = neovimApi.mode.get().mode
|
||||||
|
|
||||||
private fun assertMode(editor: Editor) {
|
private fun assertMode(editor: Editor) {
|
||||||
val ideavimState = editor.vim.vimStateMachine.mode.toVimNotation()
|
val ideavimState = editor.vim.mode.toVimNotation()
|
||||||
val neovimState = vimMode()
|
val neovimState = vimMode()
|
||||||
assertEquals(neovimState, ideavimState)
|
assertEquals(neovimState, ideavimState)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ class TestOptionConstants {
|
|||||||
const val whichwrap = "whichwrap"
|
const val whichwrap = "whichwrap"
|
||||||
|
|
||||||
// IdeaVim specific
|
// IdeaVim specific
|
||||||
const val ideaglobalmode = "ideaglobalmode"
|
|
||||||
const val ideatracetime = "ideatracetime"
|
const val ideatracetime = "ideatracetime"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ abstract class VimTestCase {
|
|||||||
KeyHandler.getInstance().fullReset(editor.vim)
|
KeyHandler.getInstance().fullReset(editor.vim)
|
||||||
}
|
}
|
||||||
KeyHandler.getInstance().keyHandlerState.reset(Mode.NORMAL())
|
KeyHandler.getInstance().keyHandlerState.reset(Mode.NORMAL())
|
||||||
|
injector.vimState.reset()
|
||||||
resetAllOptions()
|
resetAllOptions()
|
||||||
VimPlugin.getKey().resetKeyMappings()
|
VimPlugin.getKey().resetKeyMappings()
|
||||||
VimPlugin.getSearch().resetState()
|
VimPlugin.getSearch().resetState()
|
||||||
@ -221,6 +222,7 @@ abstract class VimTestCase {
|
|||||||
VimPlugin.getChange().resetRepeat()
|
VimPlugin.getChange().resetRepeat()
|
||||||
VimPlugin.getKey().savedShortcutConflicts.clear()
|
VimPlugin.getKey().savedShortcutConflicts.clear()
|
||||||
assertTrue(KeyHandler.getInstance().keyStack.isEmpty())
|
assertTrue(KeyHandler.getInstance().keyStack.isEmpty())
|
||||||
|
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||||
|
|
||||||
// Tear down neovim
|
// Tear down neovim
|
||||||
NeovimTesting.tearDown(testInfo)
|
NeovimTesting.tearDown(testInfo)
|
||||||
|
@ -156,7 +156,6 @@ private class OptionsVerificator : BeforeTestExecutionCallback, AfterTestExecuti
|
|||||||
val LOG by lazy { vimLogger<OptionsVerificator>() }
|
val LOG by lazy { vimLogger<OptionsVerificator>() }
|
||||||
private val ignored = setOf(
|
private val ignored = setOf(
|
||||||
TestOptionConstants.guicursor,
|
TestOptionConstants.guicursor,
|
||||||
TestOptionConstants.ideaglobalmode,
|
|
||||||
TestOptionConstants.ideatracetime,
|
TestOptionConstants.ideatracetime,
|
||||||
TestIjOptionConstants.ideavimsupport,
|
TestIjOptionConstants.ideavimsupport,
|
||||||
TestOptionConstants.maxmapdepth,
|
TestOptionConstants.maxmapdepth,
|
||||||
|
@ -27,6 +27,9 @@ class TestInjector(val injector: VimInjector) : VimInjector by injector {
|
|||||||
tracers[key] = collector
|
tracers[key] = collector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val vimState
|
||||||
|
get() = injector.vimState
|
||||||
|
|
||||||
override val optionGroup: VimOptionGroup
|
override val optionGroup: VimOptionGroup
|
||||||
get() {
|
get() {
|
||||||
val tracer = tracers[OptionsTracer] as? OptionsTraceCollector
|
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.MappingProcessor
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.common.CurrentCommandState
|
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.VimLogger
|
||||||
import com.maddyhome.idea.vim.diagnostic.trace
|
import com.maddyhome.idea.vim.diagnostic.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.impl.state.toMappingMode
|
||||||
import com.maddyhome.idea.vim.key.CommandPartNode
|
import com.maddyhome.idea.vim.key.CommandPartNode
|
||||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||||
@ -167,7 +165,7 @@ class KeyHandler {
|
|||||||
|
|
||||||
if (commandBuilder.isReady) {
|
if (commandBuilder.isReady) {
|
||||||
logger.trace("Ready command builder. Execute command.")
|
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`)
|
// 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")
|
logger.trace("Command builder is set to BAD")
|
||||||
keyState.commandBuilder.commandState = CurrentCommandState.BAD_COMMAND
|
keyState.commandBuilder.commandState = CurrentCommandState.BAD_COMMAND
|
||||||
editor.resetOpPending()
|
editor.resetOpPending()
|
||||||
editor.vimStateMachine.resetRegisterPending()
|
injector.vimState.resetRegisterPending()
|
||||||
editor.isReplaceCharacter = false
|
editor.isReplaceCharacter = false
|
||||||
reset(keyState, editor.mode)
|
reset(keyState, editor.mode)
|
||||||
}
|
}
|
||||||
@ -267,6 +265,7 @@ class KeyHandler {
|
|||||||
*/
|
*/
|
||||||
fun reset(editor: VimEditor) {
|
fun reset(editor: VimEditor) {
|
||||||
logger.trace { "Reset is executed" }
|
logger.trace { "Reset is executed" }
|
||||||
|
editor.resetOpPending()
|
||||||
keyHandlerState.partialReset(editor.mode)
|
keyHandlerState.partialReset(editor.mode)
|
||||||
keyHandlerState.commandBuilder.resetAll(getKeyRoot(editor.mode.toMappingMode()))
|
keyHandlerState.commandBuilder.resetAll(getKeyRoot(editor.mode.toMappingMode()))
|
||||||
}
|
}
|
||||||
@ -298,7 +297,7 @@ class KeyHandler {
|
|||||||
injector.messages.clearError()
|
injector.messages.clearError()
|
||||||
|
|
||||||
editor.mode = Mode.NORMAL()
|
editor.mode = Mode.NORMAL()
|
||||||
editor.vimStateMachine.executingCommand = null
|
injector.vimState.executingCommand = null
|
||||||
keyHandlerState.digraphSequence.reset()
|
keyHandlerState.digraphSequence.reset()
|
||||||
|
|
||||||
reset(keyHandlerState, editor.mode)
|
reset(keyHandlerState, editor.mode)
|
||||||
@ -322,7 +321,7 @@ class KeyHandler {
|
|||||||
val operatorArguments: OperatorArguments,
|
val operatorArguments: OperatorArguments,
|
||||||
) : Runnable {
|
) : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
val editorState = VimStateMachine.getInstance(editor)
|
val editorState = injector.vimState
|
||||||
keyState.commandBuilder.commandState = CurrentCommandState.NEW_COMMAND
|
keyState.commandBuilder.commandState = CurrentCommandState.NEW_COMMAND
|
||||||
val register = cmd.register
|
val register = cmd.register
|
||||||
if (register != null) {
|
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
|
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.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["<Insert>"], modes = [Mode.INSERT])
|
@CommandOrMotion(keys = ["<Insert>"], modes = [Mode.INSERT])
|
||||||
@ -38,5 +37,5 @@ class InsertInsertAction : VimActionHandler.SingleExecution() {
|
|||||||
|
|
||||||
private fun processInsert(editor: VimEditor) {
|
private fun processInsert(editor: VimEditor) {
|
||||||
editor.insertMode = !editor.insertMode
|
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.handler.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.pushVisualMode
|
import com.maddyhome.idea.vim.helper.pushVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.setSelectMode
|
import com.maddyhome.idea.vim.helper.setSelectMode
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,8 +41,7 @@ class SelectToggleVisualMode : VimActionHandler.SingleExecution() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun toggleMode(editor: VimEditor) {
|
fun toggleMode(editor: VimEditor) {
|
||||||
val commandState = editor.vimStateMachine
|
val myMode = editor.mode
|
||||||
val myMode = commandState.mode
|
|
||||||
if (myMode is com.maddyhome.idea.vim.state.mode.Mode.VISUAL) {
|
if (myMode is com.maddyhome.idea.vim.state.mode.Mode.VISUAL) {
|
||||||
editor.setSelectMode(myMode.selectionType)
|
editor.setSelectMode(myMode.selectionType)
|
||||||
if (myMode.selectionType != SelectionType.LINE_WISE) {
|
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
|
// 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`
|
// Temporary flags for work-in-progress behaviour. Hidden from the output of `:set all`
|
||||||
var ideastrictmode: Boolean by optionProperty(Options.ideastrictmode)
|
var ideastrictmode: Boolean by optionProperty(Options.ideastrictmode)
|
||||||
var ideatracetime: Boolean by optionProperty(Options.ideatracetime)
|
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
|
// 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`
|
// 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))
|
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.CharacterHelper.charType
|
||||||
import com.maddyhome.idea.vim.helper.StrictMode
|
import com.maddyhome.idea.vim.helper.StrictMode
|
||||||
import com.maddyhome.idea.vim.helper.usesVirtualSpace
|
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.listener.SelectionVimListenerSuppressor
|
||||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_END
|
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_POS
|
||||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_START
|
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.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.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.state.mode.toReturnTo
|
import com.maddyhome.idea.vim.state.mode.toReturnTo
|
||||||
@ -430,7 +428,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
* @param mode The mode - indicate insert or replace
|
* @param mode The mode - indicate insert or replace
|
||||||
*/
|
*/
|
||||||
override fun initInsert(editor: VimEditor, context: ExecutionContext, mode: Mode) {
|
override fun initInsert(editor: VimEditor, context: ExecutionContext, mode: Mode) {
|
||||||
val state = getInstance(editor)
|
val state = injector.vimState
|
||||||
for (caret in editor.nativeCarets()) {
|
for (caret in editor.nativeCarets()) {
|
||||||
caret.vimInsertStart = editor.createLiveMarker(caret.offset, caret.offset)
|
caret.vimInsertStart = editor.createLiveMarker(caret.offset, caret.offset)
|
||||||
injector.markService.setMark(caret, MARK_CHANGE_START, caret.offset)
|
injector.markService.setMark(caret, MARK_CHANGE_START, caret.offset)
|
||||||
@ -442,7 +440,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
editor.insertMode = false
|
editor.insertMode = false
|
||||||
}
|
}
|
||||||
if (cmd.flags.contains(CommandFlags.FLAG_NO_REPEAT_INSERT)) {
|
if (cmd.flags.contains(CommandFlags.FLAG_NO_REPEAT_INSERT)) {
|
||||||
val commandState = getInstance(editor)
|
val commandState = injector.vimState
|
||||||
repeatInsert(
|
repeatInsert(
|
||||||
editor,
|
editor,
|
||||||
context,
|
context,
|
||||||
@ -451,7 +449,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
OperatorArguments(false, 1, commandState.mode),
|
OperatorArguments(false, 1, commandState.mode),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val commandState = getInstance(editor)
|
val commandState = injector.vimState
|
||||||
repeatInsert(
|
repeatInsert(
|
||||||
editor,
|
editor,
|
||||||
context,
|
context,
|
||||||
@ -484,7 +482,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun runEnterAction(editor: VimEditor, context: ExecutionContext) {
|
override fun runEnterAction(editor: VimEditor, context: ExecutionContext) {
|
||||||
val state = getInstance(editor)
|
val state = injector.vimState
|
||||||
if (!state.isDotRepeatInProgress) {
|
if (!state.isDotRepeatInProgress) {
|
||||||
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
||||||
val action = injector.nativeActionManager.enterAction
|
val action = injector.nativeActionManager.enterAction
|
||||||
@ -502,7 +500,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun runEnterAboveAction(editor: VimEditor, context: ExecutionContext) {
|
override fun runEnterAboveAction(editor: VimEditor, context: ExecutionContext) {
|
||||||
val state = getInstance(editor)
|
val state = injector.vimState
|
||||||
if (!state.isDotRepeatInProgress) {
|
if (!state.isDotRepeatInProgress) {
|
||||||
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
// While repeating the enter action has been already executed because `initInsert` repeats the input
|
||||||
val action = injector.nativeActionManager.createLineAboveCaret
|
val action = injector.nativeActionManager.createLineAboveCaret
|
||||||
@ -543,7 +541,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
val markGroup = injector.markService
|
val markGroup = injector.markService
|
||||||
markGroup.setMark(editor, VimMarkService.INSERT_EXIT_MARK)
|
markGroup.setMark(editor, VimMarkService.INSERT_EXIT_MARK)
|
||||||
markGroup.setMark(editor, MARK_CHANGE_END)
|
markGroup.setMark(editor, MARK_CHANGE_END)
|
||||||
if (getInstance(editor).mode is Mode.REPLACE) {
|
if (editor.mode is Mode.REPLACE) {
|
||||||
editor.insertMode = true
|
editor.insertMode = true
|
||||||
}
|
}
|
||||||
var cnt = if (lastInsert != null) lastInsert!!.count else 0
|
var cnt = if (lastInsert != null) lastInsert!!.count else 0
|
||||||
@ -558,7 +556,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
if (context != null) {
|
if (context != null) {
|
||||||
injector.changeGroup.repeatInsert(editor, context, if (cnt == 0) 0 else cnt - 1, true, operatorArguments)
|
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()
|
updateLastInsertedTextRegister()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +587,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
* @param context The data context
|
* @param context The data context
|
||||||
*/
|
*/
|
||||||
override fun processEnter(editor: VimEditor, context: ExecutionContext) {
|
override fun processEnter(editor: VimEditor, context: ExecutionContext) {
|
||||||
if (editor.vimStateMachine.mode is Mode.REPLACE) {
|
if (editor.mode is Mode.REPLACE) {
|
||||||
editor.insertMode = true
|
editor.insertMode = true
|
||||||
}
|
}
|
||||||
val enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
|
val enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
|
||||||
@ -599,7 +597,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (editor.vimStateMachine.mode is Mode.REPLACE) {
|
if (editor.mode is Mode.REPLACE) {
|
||||||
editor.insertMode = false
|
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.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.common.LiveRange
|
import com.maddyhome.idea.vim.common.LiveRange
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
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.impl.state.VimStateMachineImpl
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
||||||
@ -126,20 +125,22 @@ import com.maddyhome.idea.vim.state.mode.returnTo
|
|||||||
*/
|
*/
|
||||||
interface VimEditor {
|
interface VimEditor {
|
||||||
var mode: Mode
|
var mode: Mode
|
||||||
get() = vimStateMachine.mode
|
get() = injector.vimState.mode
|
||||||
set(value) {
|
set(value) {
|
||||||
if (vimStateMachine.mode == value) return
|
val vimState = injector.vimState
|
||||||
|
if (vimState.mode == value) return
|
||||||
|
|
||||||
val oldValue = vimStateMachine.mode
|
val oldValue = vimState.mode
|
||||||
(vimStateMachine as VimStateMachineImpl).mode = value
|
(vimState as VimStateMachineImpl).mode = value
|
||||||
injector.listenersNotifier.notifyModeChanged(this, oldValue)
|
injector.listenersNotifier.notifyModeChanged(this, oldValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isReplaceCharacter: Boolean
|
var isReplaceCharacter: Boolean
|
||||||
get() = vimStateMachine.isReplaceCharacter
|
get() = injector.vimState.isReplaceCharacter
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value != vimStateMachine.isReplaceCharacter) {
|
val vimState = injector.vimState
|
||||||
(vimStateMachine as VimStateMachineImpl).isReplaceCharacter = value
|
if (value != vimState.isReplaceCharacter) {
|
||||||
|
(vimState as VimStateMachineImpl).isReplaceCharacter = value
|
||||||
injector.listenersNotifier.notifyIsReplaceCharChanged(this)
|
injector.listenersNotifier.notifyIsReplaceCharChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +163,7 @@ interface VimEditor {
|
|||||||
* which indicated that the buffer is empty. However, the line count is still 1.
|
* 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
|
* 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.
|
* 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
|
* 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.
|
* 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
|
fun isOneLineMode(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* public function for refactoring, get rid of it
|
* function for refactoring, get rid of it
|
||||||
*/
|
*/
|
||||||
fun search(
|
fun search(
|
||||||
pair: Pair<Int, Int>,
|
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 {
|
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
|
import com.maddyhome.idea.vim.yank.VimYankGroup
|
||||||
|
|
||||||
interface VimInjector {
|
interface VimInjector {
|
||||||
|
val vimState: VimStateMachine
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The window used when we need a window but there are no editor windows available.
|
* The window used when we need a window but there are no editor windows available.
|
||||||
*
|
*
|
||||||
@ -85,12 +87,14 @@ interface VimInjector {
|
|||||||
val visualMotionGroup: VimVisualMotionGroup
|
val visualMotionGroup: VimVisualMotionGroup
|
||||||
|
|
||||||
// [FINISHED] Class moved to vim-engine, but it's attached to Editor using IJ things
|
// [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
|
fun commandStateFor(editor: VimEditor): VimStateMachine
|
||||||
// [FINISHED] Class moved to vim-engine, but it's attached to Editor using IJ things
|
// [FINISHED] Class moved to vim-engine, but it's attached to Editor using IJ things
|
||||||
/**
|
/**
|
||||||
* COMPATIBILITY-LAYER: Added new method with Any
|
* COMPATIBILITY-LAYER: Added new method with Any
|
||||||
* Please see: https://jb.gg/zo8n0r
|
* Please see: https://jb.gg/zo8n0r
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("vimState"))
|
||||||
fun commandStateFor(editor: Any): VimStateMachine
|
fun commandStateFor(editor: Any): VimStateMachine
|
||||||
|
|
||||||
// !! in progress
|
// !! in progress
|
||||||
@ -108,9 +112,6 @@ interface VimInjector {
|
|||||||
// Can't be fully moved to vim-engine.
|
// Can't be fully moved to vim-engine.
|
||||||
val actionExecutor: VimActionExecutor
|
val actionExecutor: VimActionExecutor
|
||||||
|
|
||||||
// Can't be fully moved to vim-engine.
|
|
||||||
val exOutputPanel: VimExOutputPanelService
|
|
||||||
|
|
||||||
// Can't be fully moved to vim-engine.
|
// Can't be fully moved to vim-engine.
|
||||||
val clipboardManager: VimClipboardManager
|
val clipboardManager: VimClipboardManager
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ interface VimInjector {
|
|||||||
val variableService: VariableService
|
val variableService: VariableService
|
||||||
|
|
||||||
val commandLine: VimCommandLineService
|
val commandLine: VimCommandLineService
|
||||||
|
val outputPanel: VimOutputPanelService
|
||||||
|
|
||||||
// !! in progress
|
// !! in progress
|
||||||
val functionService: VimscriptFunctionService
|
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.common.VimListenersNotifier
|
||||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||||
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.VimRegisterGroup
|
||||||
import com.maddyhome.idea.vim.register.VimRegisterGroupBase
|
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.VariableService
|
||||||
import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase
|
import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase
|
||||||
import com.maddyhome.idea.vim.yank.VimYankGroup
|
import com.maddyhome.idea.vim.yank.VimYankGroup
|
||||||
@ -29,6 +31,8 @@ abstract class VimInjectorBase : VimInjector {
|
|||||||
val registerGroupStub: VimRegisterGroupBase by lazy { object : VimRegisterGroupBase() {} }
|
val registerGroupStub: VimRegisterGroupBase by lazy { object : VimRegisterGroupBase() {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val vimState: VimStateMachine = VimStateMachineImpl()
|
||||||
|
|
||||||
override val parser: VimStringParser = object : VimStringParserBase() {}
|
override val parser: VimStringParser = object : VimStringParserBase() {}
|
||||||
override val optionGroup: VimOptionGroup by lazy { object : VimOptionGroupBase() {} }
|
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.common.TextRange
|
||||||
import com.maddyhome.idea.vim.diagnostic.debug
|
import com.maddyhome.idea.vim.diagnostic.debug
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.Jump
|
||||||
import com.maddyhome.idea.vim.mark.Mark
|
import com.maddyhome.idea.vim.mark.Mark
|
||||||
import com.maddyhome.idea.vim.mark.VimMark
|
import com.maddyhome.idea.vim.mark.VimMark
|
||||||
@ -368,7 +367,7 @@ abstract class VimMarkServiceBase : VimMarkService {
|
|||||||
val markLineStartOffset = editor.getLineStartOffset(mark.line)
|
val markLineStartOffset = editor.getLineStartOffset(mark.line)
|
||||||
val markLineEndOffset = editor.getLineEndOffset(mark.line, true)
|
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)
|
// If text is being changed from the start of the mark line (a special case for mark deletion)
|
||||||
val changeFromMarkLineStart =
|
val changeFromMarkLineStart =
|
||||||
(command != null && command.type === Command.Type.CHANGE && delStartOffset == markLineStartOffset)
|
(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 remove me
|
||||||
// TODO: Why ^^ ? Should that also include startExEntry?
|
// TODO: Why ^^ ? Should that also include startExEntry?
|
||||||
fun processExKey(editor: VimEditor, stroke: KeyStroke, processResultBuilder: KeyProcessResult.KeyProcessResultBuilder): Boolean
|
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)
|
@kotlin.jvm.Throws(java.lang.Exception::class)
|
||||||
fun executeCommand(editor: VimEditor, command: String, input: CharSequence?, currentDirectoryPath: String?): String?
|
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.KeyHandler.Companion.getInstance
|
||||||
import com.maddyhome.idea.vim.KeyProcessResult
|
import com.maddyhome.idea.vim.KeyProcessResult
|
||||||
import com.maddyhome.idea.vim.command.Command
|
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.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.ReturnableFromCmd
|
import com.maddyhome.idea.vim.state.mode.ReturnableFromCmd
|
||||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
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
|
// Don't allow ex commands in one line editors
|
||||||
if (editor.isOneLineMode()) return
|
if (editor.isOneLineMode()) return
|
||||||
|
|
||||||
val currentMode = editor.vimStateMachine.mode
|
val currentMode = editor.mode
|
||||||
check(currentMode is ReturnableFromCmd) {
|
check(currentMode is ReturnableFromCmd) {
|
||||||
"Cannot enable cmd mode from current mode $currentMode"
|
"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.
|
// 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.
|
// IdeaVim does not (currently?) support 'cpoptions', so sticks with Vim's default behaviour. Escape cancels.
|
||||||
editor.mode = editor.mode.returnTo()
|
editor.mode = editor.mode.returnTo()
|
||||||
getInstance().reset(editor)
|
getInstance().reset(editor)
|
||||||
injector.commandLine.getActiveCommandLine()?.deactivate(refocusOwningEditor = true, resetCaret)
|
injector.commandLine.getActiveCommandLine()?.deactivate(refocusOwningEditor, resetCaret)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRange(editor: VimEditor, cmd: Command) = when {
|
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.VimRegexException
|
||||||
import com.maddyhome.idea.vim.regexp.VimRegexOptions
|
import com.maddyhome.idea.vim.regexp.VimRegexOptions
|
||||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import org.jetbrains.annotations.Contract
|
import org.jetbrains.annotations.Contract
|
||||||
import org.jetbrains.annotations.Range
|
import org.jetbrains.annotations.Range
|
||||||
@ -1454,7 +1453,7 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
|||||||
while (selectionEndWithoutNewline < sequence.length && sequence[selectionEndWithoutNewline] == '\n') {
|
while (selectionEndWithoutNewline < sequence.length && sequence[selectionEndWithoutNewline] == '\n') {
|
||||||
selectionEndWithoutNewline++
|
selectionEndWithoutNewline++
|
||||||
}
|
}
|
||||||
val mode = VimStateMachine.getInstance(editor).mode
|
val mode = editor.mode
|
||||||
if (mode is Mode.VISUAL) {
|
if (mode is Mode.VISUAL) {
|
||||||
if (closingTagTextRange.startOffset == selectionEndWithoutNewline &&
|
if (closingTagTextRange.startOffset == selectionEndWithoutNewline &&
|
||||||
openingTag.endOffset == selectionStart
|
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.exitVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.pushVisualMode
|
import com.maddyhome.idea.vim.helper.pushVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.setSelectMode
|
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.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
import com.maddyhome.idea.vim.state.mode.ReturnTo
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
@ -72,7 +71,7 @@ abstract class VimVisualMotionGroupBase : VimVisualMotionGroup {
|
|||||||
} else {
|
} else {
|
||||||
editor.mode = Mode.VISUAL(
|
editor.mode = Mode.VISUAL(
|
||||||
selectionType,
|
selectionType,
|
||||||
returnTo ?: editor.vimStateMachine.mode.returnTo
|
returnTo ?: editor.mode.returnTo
|
||||||
)
|
)
|
||||||
editor.forEachCaret { it.vimSetSelection(it.offset) }
|
editor.forEachCaret { it.vimSetSelection(it.offset) }
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ class VimProcessGroupStub : VimProcessGroupBase() {
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancelExEntry(editor: VimEditor, resetCaret: Boolean) {
|
override fun cancelExEntry(editor: VimEditor, refocusOwningEditor: Boolean, resetCaret: Boolean) {
|
||||||
TODO("Not yet implemented")
|
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.debug
|
||||||
import com.maddyhome.idea.vim.diagnostic.trace
|
import com.maddyhome.idea.vim.diagnostic.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.impl.state.toMappingMode
|
||||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||||
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
||||||
@ -42,13 +41,12 @@ object MappingProcessor: KeyConsumer {
|
|||||||
|
|
||||||
log.debug("Start processing key mappings.")
|
log.debug("Start processing key mappings.")
|
||||||
val keyState = keyProcessResultBuilder.state
|
val keyState = keyProcessResultBuilder.state
|
||||||
val commandState = editor.vimStateMachine
|
|
||||||
val mappingState = keyState.mappingState
|
val mappingState = keyState.mappingState
|
||||||
val commandBuilder = keyState.commandBuilder
|
val commandBuilder = keyState.commandBuilder
|
||||||
if (commandBuilder.isAwaitingCharOrDigraphArgument() ||
|
if (commandBuilder.isAwaitingCharOrDigraphArgument() ||
|
||||||
commandBuilder.isBuildingMultiKeyCommand() ||
|
commandBuilder.isBuildingMultiKeyCommand() ||
|
||||||
isMappingDisabledForKey(key, keyState) ||
|
isMappingDisabledForKey(key, keyState) ||
|
||||||
commandState.isRegisterPending
|
injector.vimState.isRegisterPending
|
||||||
) {
|
) {
|
||||||
log.debug("Finish key processing, returning false")
|
log.debug("Finish key processing, returning false")
|
||||||
return false
|
return false
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
package com.maddyhome.idea.vim.common
|
package com.maddyhome.idea.vim.common
|
||||||
|
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import org.jetbrains.annotations.ApiStatus.Internal
|
import org.jetbrains.annotations.ApiStatus.Internal
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque
|
import java.util.concurrent.ConcurrentLinkedDeque
|
||||||
@ -22,30 +23,37 @@ class VimListenersNotifier {
|
|||||||
val isReplaceCharListeners: MutableCollection<IsReplaceCharListener> = ConcurrentLinkedDeque()
|
val isReplaceCharListeners: MutableCollection<IsReplaceCharListener> = ConcurrentLinkedDeque()
|
||||||
|
|
||||||
fun notifyModeChanged(editor: VimEditor, oldMode: Mode) {
|
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) }
|
modeChangeListeners.forEach { it.modeChanged(editor, oldMode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyEditorCreated(editor: VimEditor) {
|
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) }
|
myEditorListeners.forEach { it.created(editor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyEditorReleased(editor: VimEditor) {
|
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) }
|
myEditorListeners.forEach { it.released(editor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyEditorFocusGained(editor: VimEditor) {
|
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) }
|
myEditorListeners.forEach { it.focusGained(editor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyEditorFocusLost(editor: VimEditor) {
|
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) }
|
myEditorListeners.forEach { it.focusLost(editor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyMacroRecordingStarted() {
|
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() }
|
macroRecordingListeners.forEach { it.recordingStarted() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyMacroRecordingFinished() {
|
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() }
|
macroRecordingListeners.forEach { it.recordingFinished() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +66,7 @@ class VimListenersNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun notifyIsReplaceCharChanged(editor: VimEditor) {
|
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) }
|
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.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||||
import com.maddyhome.idea.vim.helper.noneOfEnum
|
import com.maddyhome.idea.vim.helper.noneOfEnum
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
@ -114,7 +113,7 @@ abstract class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentCaret == primaryCaret) {
|
if (currentCaret == primaryCaret) {
|
||||||
val cmd = VimStateMachine.getInstance(editor).executingCommand ?: run {
|
val cmd = injector.vimState.executingCommand ?: run {
|
||||||
injector.messages.indicateError()
|
injector.messages.indicateError()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -127,7 +126,7 @@ abstract class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
|||||||
|
|
||||||
logger.debug("Execute command with handler: " + this.javaClass.name)
|
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()
|
injector.messages.indicateError()
|
||||||
return
|
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.VisualChange
|
||||||
import com.maddyhome.idea.vim.group.visual.VisualOperation
|
import com.maddyhome.idea.vim.group.visual.VisualOperation
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
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
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
|
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
|
||||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||||
@ -176,7 +174,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
|
|
||||||
private fun VimEditor.collectSelections(): Map<VimCaret, VimSelection>? {
|
private fun VimEditor.collectSelections(): Map<VimCaret, VimSelection>? {
|
||||||
return when {
|
return when {
|
||||||
!this.inVisualMode && this.inRepeatMode -> {
|
!this.inVisualMode && injector.vimState.isDotRepeatInProgress -> {
|
||||||
if (this.vimLastSelectionType == SelectionType.BLOCK_WISE) {
|
if (this.vimLastSelectionType == SelectionType.BLOCK_WISE) {
|
||||||
val primaryCaret = primaryCaret()
|
val primaryCaret = primaryCaret()
|
||||||
val range = primaryCaret.vimLastVisualOperatorRange ?: return null
|
val range = primaryCaret.vimLastVisualOperatorRange ?: return null
|
||||||
@ -211,7 +209,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> this.nativeCarets().associateWith { caret ->
|
else -> this.nativeCarets().associateWith { caret ->
|
||||||
val mode = this.vimStateMachine.mode
|
val mode = this.mode
|
||||||
VimSimpleSelection.createWithNative(
|
VimSimpleSelection.createWithNative(
|
||||||
caret.vimSelectionStart,
|
caret.vimSelectionStart,
|
||||||
caret.offset,
|
caret.offset,
|
||||||
@ -235,7 +233,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
|
|
||||||
editor.forEachCaret {
|
editor.forEachCaret {
|
||||||
val change =
|
val change =
|
||||||
if (editor.inVisualMode && !editor.inRepeatMode) {
|
if (editor.inVisualMode && !injector.vimState.isDotRepeatInProgress) {
|
||||||
VisualOperation.getRange(editor, it, cmd.flags)
|
VisualOperation.getRange(editor, it, cmd.flags)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
@ -26,10 +26,7 @@ val TextRange.endOffsetInclusive: Int
|
|||||||
get() = if (this.endOffset > 0 && this.endOffset > this.startOffset) this.endOffset - 1 else this.endOffset
|
get() = if (this.endOffset > 0 && this.endOffset > this.startOffset) this.endOffset - 1 else this.endOffset
|
||||||
|
|
||||||
val VimEditor.inRepeatMode: Boolean
|
val VimEditor.inRepeatMode: Boolean
|
||||||
get() = this.vimStateMachine.isDotRepeatInProgress
|
get() = injector.vimState.isDotRepeatInProgress
|
||||||
|
|
||||||
val VimEditor.vimStateMachine: VimStateMachine
|
|
||||||
get() = VimStateMachine.getInstance(this)
|
|
||||||
|
|
||||||
val VimEditor.usesVirtualSpace: Boolean
|
val VimEditor.usesVirtualSpace: Boolean
|
||||||
get() = injector.options(this).virtualedit.contains(OptionConstants.virtualedit_onemore)
|
get() = injector.options(this).virtualedit.contains(OptionConstants.virtualedit_onemore)
|
||||||
|
@ -33,7 +33,7 @@ fun VimEditor.exitVisualMode() {
|
|||||||
injector.markService.setVisualSelectionMarks(this)
|
injector.markService.setVisualSelectionMarks(this)
|
||||||
this.nativeCarets().forEach { it.vimSelectionStartClear() }
|
this.nativeCarets().forEach { it.vimSelectionStartClear() }
|
||||||
|
|
||||||
val returnTo = this.vimStateMachine.mode.returnTo
|
val returnTo = this.mode.returnTo
|
||||||
when (returnTo) {
|
when (returnTo) {
|
||||||
ReturnTo.INSERT -> {
|
ReturnTo.INSERT -> {
|
||||||
this.mode = Mode.INSERT
|
this.mode = Mode.INSERT
|
||||||
|
@ -47,21 +47,12 @@ class VimStateMachineImpl : VimStateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override fun reset() {
|
||||||
* Toggles the insert/overwrite state. If currently insert, goto replace mode. If currently replace, goto insert
|
mode = Mode.NORMAL()
|
||||||
* mode.
|
isDotRepeatInProgress = false
|
||||||
*/
|
isRegisterPending = false
|
||||||
override fun toggleInsertOverwrite() {
|
isReplaceCharacter = false
|
||||||
val oldMode = this.mode
|
executingCommand = null
|
||||||
var newMode = oldMode
|
|
||||||
if (oldMode == Mode.INSERT) {
|
|
||||||
newMode = Mode.REPLACE
|
|
||||||
} else if (oldMode == Mode.REPLACE) {
|
|
||||||
newMode = Mode.INSERT
|
|
||||||
}
|
|
||||||
if (oldMode != newMode) {
|
|
||||||
mode = newMode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||||
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase
|
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.CommandNode
|
||||||
import com.maddyhome.idea.vim.key.CommandPartNode
|
import com.maddyhome.idea.vim.key.CommandPartNode
|
||||||
import com.maddyhome.idea.vim.key.KeyConsumer
|
import com.maddyhome.idea.vim.key.KeyConsumer
|
||||||
@ -126,9 +125,8 @@ class CommandConsumer : KeyConsumer {
|
|||||||
processBuilder.addExecutionStep { lambdaKeyState, lambdaEditor, lambdaContext ->
|
processBuilder.addExecutionStep { lambdaKeyState, lambdaEditor, lambdaContext ->
|
||||||
logger.trace("Set waiting for the argument")
|
logger.trace("Set waiting for the argument")
|
||||||
val argumentType = action.argumentType
|
val argumentType = action.argumentType
|
||||||
val editorState = lambdaEditor.vimStateMachine
|
startWaitingForArgument(lambdaEditor, lambdaContext, action, argumentType!!, lambdaKeyState, injector.vimState)
|
||||||
startWaitingForArgument(lambdaEditor, lambdaContext, action, argumentType!!, lambdaKeyState, editorState)
|
lambdaKeyState.partialReset(lambdaEditor.mode)
|
||||||
lambdaKeyState.partialReset(editorState.mode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ package com.maddyhome.idea.vim.key.consumers
|
|||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.KeyProcessResult
|
import com.maddyhome.idea.vim.KeyProcessResult
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
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.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.key.KeyConsumer
|
||||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
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 {
|
private fun isCommandCountKey(chKey: Char, keyState: KeyHandlerState, editor: VimEditor): Boolean {
|
||||||
// Make sure to avoid handling '0' as the start of a count.
|
// 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 commandBuilder = keyState.commandBuilder
|
||||||
val notRegisterPendingCommand = editorState.mode is Mode.NORMAL && !editorState.isRegisterPending
|
val notRegisterPendingCommand = editorState.mode is Mode.NORMAL && !editorState.isRegisterPending
|
||||||
val visualMode = editorState.mode is Mode.VISUAL && !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.api.injector
|
||||||
import com.maddyhome.idea.vim.diagnostic.trace
|
import com.maddyhome.idea.vim.diagnostic.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.key.KeyConsumer
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
@ -33,7 +32,7 @@ class RegisterConsumer : KeyConsumer {
|
|||||||
shouldRecord: KeyHandler.MutableBoolean,
|
shouldRecord: KeyHandler.MutableBoolean,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
logger.trace { "Entered RegisterConsumer" }
|
logger.trace { "Entered RegisterConsumer" }
|
||||||
if (!editor.vimStateMachine.isRegisterPending) return false
|
if (!injector.vimState.isRegisterPending) return false
|
||||||
|
|
||||||
logger.trace("Pending mode.")
|
logger.trace("Pending mode.")
|
||||||
keyProcessResultBuilder.state.commandBuilder.addKey(key)
|
keyProcessResultBuilder.state.commandBuilder.addKey(key)
|
||||||
@ -45,7 +44,7 @@ class RegisterConsumer : KeyConsumer {
|
|||||||
|
|
||||||
private fun handleSelectRegister(editor: VimEditor, chKey: Char, processBuilder: KeyProcessResult.KeyProcessResultBuilder) {
|
private fun handleSelectRegister(editor: VimEditor, chKey: Char, processBuilder: KeyProcessResult.KeyProcessResultBuilder) {
|
||||||
logger.trace("Handle select register")
|
logger.trace("Handle select register")
|
||||||
editor.vimStateMachine.resetRegisterPending()
|
injector.vimState.resetRegisterPending()
|
||||||
if (injector.registerGroup.isValid(chKey)) {
|
if (injector.registerGroup.isValid(chKey)) {
|
||||||
logger.trace("Valid register")
|
logger.trace("Valid register")
|
||||||
processBuilder.state.commandBuilder.pushCommandPart(chKey)
|
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.KeyHandler
|
||||||
import com.maddyhome.idea.vim.KeyProcessResult
|
import com.maddyhome.idea.vim.KeyProcessResult
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
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.trace
|
||||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
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.key.KeyConsumer
|
||||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||||
@ -35,24 +35,25 @@ class SelectRegisterConsumer : KeyConsumer {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
logger.trace { "Entered SelectRegisterConsumer" }
|
logger.trace { "Entered SelectRegisterConsumer" }
|
||||||
val state = keyProcessResultBuilder.state
|
val state = keyProcessResultBuilder.state
|
||||||
if (!isSelectRegister(key, state, editor.vimStateMachine)) return false
|
if (!isSelectRegister(key, state)) return false
|
||||||
|
|
||||||
logger.trace("Select register")
|
logger.trace("Select register")
|
||||||
state.commandBuilder.addKey(key)
|
state.commandBuilder.addKey(key)
|
||||||
keyProcessResultBuilder.addExecutionStep { _, lambdaEditor, _ ->
|
keyProcessResultBuilder.addExecutionStep { _, lambdaEditor, _ ->
|
||||||
lambdaEditor.vimStateMachine.isRegisterPending = true
|
injector.vimState.isRegisterPending = true
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSelectRegister(key: KeyStroke, keyState: KeyHandlerState, editorState: VimStateMachine): Boolean {
|
private fun isSelectRegister(key: KeyStroke, keyState: KeyHandlerState): Boolean {
|
||||||
if (editorState.mode !is Mode.NORMAL && editorState.mode !is Mode.VISUAL) {
|
val vimState = injector.vimState
|
||||||
|
if (vimState.mode !is Mode.NORMAL && vimState.mode !is Mode.VISUAL) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return if (editorState.isRegisterPending) {
|
return if (vimState.isRegisterPending) {
|
||||||
true
|
true
|
||||||
} else {
|
} 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()
|
myRegisters.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSmallDeletionSpecialCase(editor: VimEditor): Boolean {
|
private fun isSmallDeletionSpecialCase(): Boolean {
|
||||||
val currentCommand = VimStateMachine.getInstance(editor).executingCommand
|
val currentCommand = injector.vimState.executingCommand
|
||||||
if (currentCommand != null) {
|
if (currentCommand != null) {
|
||||||
val argument = currentCommand.argument
|
val argument = currentCommand.argument
|
||||||
if (argument != null) {
|
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
|
// 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
|
// Old 1 goes to 2, etc. Old 8 to 9, old 9 is lost
|
||||||
var d = '8'
|
var d = '8'
|
||||||
while (d >= '1') {
|
while (d >= '1') {
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.state
|
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.api.injector
|
||||||
import com.maddyhome.idea.vim.command.Command
|
import com.maddyhome.idea.vim.command.Command
|
||||||
import com.maddyhome.idea.vim.command.CommandFlags
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -40,22 +38,12 @@ interface VimStateMachine {
|
|||||||
|
|
||||||
fun resetRegisterPending()
|
fun resetRegisterPending()
|
||||||
|
|
||||||
/**
|
fun reset()
|
||||||
* Toggles the insert/overwrite state. If currently insert, goto replace mode. If currently replace, goto insert
|
|
||||||
* mode.
|
|
||||||
*/
|
|
||||||
fun toggleInsertOverwrite()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val globalState = VimStateMachineImpl()
|
@Deprecated("Please use VimInjector.vimState", replaceWith = ReplaceWith("injector.vimState", imports = ["com.maddyhome.idea.vim.api.injector"]))
|
||||||
|
|
||||||
// TODO do we really need this method? Can't we use editor.vimStateMachine?
|
|
||||||
fun getInstance(editor: Any?): VimStateMachine {
|
fun getInstance(editor: Any?): VimStateMachine {
|
||||||
return if (editor == null || injector.globalOptions().ideaglobalmode) {
|
return injector.vimState
|
||||||
globalState
|
|
||||||
} else {
|
|
||||||
injector.commandStateFor(editor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,10 @@
|
|||||||
package com.maddyhome.idea.vim.state.mode
|
package com.maddyhome.idea.vim.state.mode
|
||||||
|
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
|
||||||
val VimEditor.mode: Mode
|
|
||||||
get() = this.vimStateMachine.mode
|
|
||||||
|
|
||||||
val VimEditor.inVisualMode: Boolean
|
val VimEditor.inVisualMode: Boolean
|
||||||
get() = this.vimStateMachine.mode is Mode.VISUAL
|
get() = injector.vimState.mode is Mode.VISUAL
|
||||||
|
|
||||||
val VimEditor.inBlockSelection: Boolean
|
val VimEditor.inBlockSelection: Boolean
|
||||||
get() = this.mode.selectionType == SelectionType.BLOCK_WISE
|
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 {
|
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
|
||||||
val result: Boolean = if (argument.trim().isEmpty()) {
|
val result: Boolean = if (argument.trim().isEmpty()) {
|
||||||
this.listAlias(editor, "")
|
this.listAlias(editor, context, "")
|
||||||
} else {
|
} else {
|
||||||
this.addAlias(editor)
|
this.addAlias(editor, context)
|
||||||
}
|
}
|
||||||
return if (result) ExecutionResult.Success else ExecutionResult.Error
|
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 lineSeparator = "\n"
|
||||||
val allAliases = injector.commandGroup.listAliases()
|
val allAliases = injector.commandGroup.listAliases()
|
||||||
val aliases = allAliases.filter {
|
val aliases = allAliases.filter {
|
||||||
@ -67,11 +67,11 @@ data class CmdCommand(val range: Range, val argument: String) : Command.SingleEx
|
|||||||
}.map {
|
}.map {
|
||||||
"${it.key.padEnd(12)}${it.value.numberOfArguments.padEnd(11)}${it.value.printValue()}"
|
"${it.key.padEnd(12)}${it.value.numberOfArguments.padEnd(11)}${it.value.printValue()}"
|
||||||
}.sortedWith(String.CASE_INSENSITIVE_ORDER).joinToString(lineSeparator)
|
}.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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAlias(editor: VimEditor): Boolean {
|
private fun addAlias(editor: VimEditor, context: ExecutionContext): Boolean {
|
||||||
var argument = argument.trim()
|
var argument = argument.trim()
|
||||||
|
|
||||||
// Handle overwriting of aliases
|
// 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.
|
// No message should be shown either, since there is no editor.
|
||||||
return false
|
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
|
// 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") {
|
val text = args.joinToString(separator = " ", postfix = "\n") {
|
||||||
it.evaluate(editor, context, this).toString()
|
it.evaluate(editor, context, this).toString()
|
||||||
}
|
}
|
||||||
injector.exOutputPanel.getPanel(editor).output(text)
|
injector.outputPanel.output(editor, context, text)
|
||||||
return ExecutionResult.Success
|
return ExecutionResult.Success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,9 +131,7 @@ data class GlobalCommand(val range: Range, val argument: String, val invert: Boo
|
|||||||
globalBusy = true
|
globalBusy = true
|
||||||
try {
|
try {
|
||||||
if (cmd.isEmpty() || (cmd.length == 1 && cmd[0] == '\n')) {
|
if (cmd.isEmpty() || (cmd.length == 1 && cmd[0] == '\n')) {
|
||||||
val exOutputModel = injector.exOutputPanel.getPanel(editor)
|
injector.outputPanel.output(editor, context, originalCommandString + '\n' + PrintCommand.getText(editor, lines))
|
||||||
exOutputModel.clear()
|
|
||||||
exOutputModel.output(originalCommandString + '\n' + PrintCommand.getText(editor, lines))
|
|
||||||
} else {
|
} else {
|
||||||
for (mark in marks) {
|
for (mark in marks) {
|
||||||
if (gotInt) break
|
if (gotInt) break
|
||||||
|
@ -105,8 +105,7 @@ data class HistoryCommand(val range: Range, val argument: String) : Command.Sing
|
|||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.exOutputPanel.getPanel(editor).output(res)
|
injector.outputPanel.output(editor, context, res)
|
||||||
|
|
||||||
return ExecutionResult.Success
|
return ExecutionResult.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,7 @@ data class JumpsCommand(val range: Range, val argument: String) : Command.Single
|
|||||||
text.append(">\n")
|
text.append(">\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.exOutputPanel.getPanel(editor).output(text.toString())
|
injector.outputPanel.output(editor, context, text.toString())
|
||||||
|
|
||||||
return ExecutionResult.Success
|
return ExecutionResult.Success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ data class MarksCommand(val range: Range, val argument: String) : Command.Single
|
|||||||
" ${mark.key} $line $column $text"
|
" ${mark.key} $line $column $text"
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.exOutputPanel.getPanel(editor).output(res)
|
injector.outputPanel.output(editor, context, res)
|
||||||
|
|
||||||
return ExecutionResult.Success
|
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.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.ex.ranges.Range
|
import com.maddyhome.idea.vim.ex.ranges.Range
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
||||||
|
|
||||||
// todo make it for each caret
|
// 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)
|
argument = argument.substring(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val commandState = editor.vimStateMachine
|
|
||||||
val rangeUsed = range.size() != 0
|
val rangeUsed = range.size() != 0
|
||||||
when (editor.mode) {
|
when (editor.mode) {
|
||||||
is Mode.VISUAL -> {
|
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))
|
editor.currentCaret().moveToBufferPosition(BufferPosition(selectionStart.line, selectionStart.col))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Mode.CMD_LINE -> injector.processGroup.cancelExEntry(editor, false)
|
is Mode.CMD_LINE -> injector.processGroup.cancelExEntry(editor, refocusOwningEditor = true, resetCaret = false)
|
||||||
Mode.INSERT, Mode.REPLACE -> editor.exitInsertMode(context, OperatorArguments(false, 1, commandState.mode))
|
Mode.INSERT, Mode.REPLACE -> editor.exitInsertMode(context, OperatorArguments(false, 1, editor.mode))
|
||||||
is Mode.SELECT -> editor.exitSelectModeNative(false)
|
is Mode.SELECT -> editor.exitSelectModeNative(false)
|
||||||
is Mode.OP_PENDING, is Mode.NORMAL -> Unit
|
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
|
// Exit if state leaves as insert or cmd_line
|
||||||
val mode = commandState.mode
|
val mode = editor.mode
|
||||||
if (mode is Mode.CMD_LINE) {
|
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) {
|
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()
|
editor.removeSecondaryCarets()
|
||||||
val caret = editor.currentCaret()
|
val caret = editor.currentCaret()
|
||||||
val lineRange = getLineRangeWithCount(editor, caret)
|
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
|
// Move the caret to the start of the last line of the range
|
||||||
val offset = injector.motion.moveCaretToLineStartSkipLeading(editor, lineRange.endLine)
|
val offset = injector.motion.moveCaretToLineStartSkipLeading(editor, lineRange.endLine)
|
||||||
caret.moveToOffset(offset)
|
caret.moveToOffset(offset)
|
||||||
|
|
||||||
// Note that we append to the existing text because we can be called multiple times by the :global command
|
injector.outputPanel.output(editor, context, getText(editor, (lineRange.startLine .. lineRange.endLine).toList()))
|
||||||
// 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)
|
|
||||||
return ExecutionResult.Success
|
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)}"
|
" $type \"${reg.name} ${EngineStringHelper.toPrintableCharacters(text).take(200)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.exOutputPanel.getPanel(editor).output(regs)
|
injector.outputPanel.output(editor, context, regs)
|
||||||
|
|
||||||
return ExecutionResult.Success
|
return ExecutionResult.Success
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ abstract class SetCommandBase(range: Range, argument: String) : Command.SingleEx
|
|||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
operatorArguments: OperatorArguments
|
operatorArguments: OperatorArguments
|
||||||
): ExecutionResult {
|
): ExecutionResult {
|
||||||
parseOptionLine(editor, commandArgument, getScope(editor))
|
parseOptionLine(editor, context, commandArgument, getScope(editor))
|
||||||
return ExecutionResult.Success
|
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
|
* @param args The raw text passed to the `:set` command
|
||||||
* @throws ExException Thrown if any option names or operations are incorrect
|
* @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 optionGroup = injector.optionGroup
|
||||||
|
|
||||||
val columnFormat = args.startsWith("!")
|
val columnFormat = args.startsWith("!")
|
||||||
@ -105,14 +105,14 @@ fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessScope) {
|
|||||||
val changedOptions = optionGroup.getAllOptions()
|
val changedOptions = optionGroup.getAllOptions()
|
||||||
.filter { !optionGroup.isDefaultValue(it, scope) && (!it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest())) }
|
.filter { !optionGroup.isDefaultValue(it, scope) && (!it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest())) }
|
||||||
.map { Pair(it.name, it.name) }
|
.map { Pair(it.name, it.name) }
|
||||||
showOptions(editor, changedOptions, scope, true, columnFormat)
|
showOptions(editor, context, changedOptions, scope, true, columnFormat)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
argument == "all" -> {
|
argument == "all" -> {
|
||||||
val options = optionGroup.getAllOptions()
|
val options = optionGroup.getAllOptions()
|
||||||
.filter { !it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest()) }
|
.filter { !it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest()) }
|
||||||
.map { Pair(it.name, it.name) }
|
.map { Pair(it.name, it.name) }
|
||||||
showOptions(editor, options, scope, true, columnFormat)
|
showOptions(editor, context, options, scope, true, columnFormat)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
argument == "all&" -> {
|
argument == "all&" -> {
|
||||||
@ -196,7 +196,7 @@ fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessScope) {
|
|||||||
|
|
||||||
// Now show all options that were individually requested
|
// Now show all options that were individually requested
|
||||||
if (toShow.size > 0) {
|
if (toShow.size > 0) {
|
||||||
showOptions(editor, toShow, scope, false, columnFormat)
|
showOptions(editor, context, toShow, scope, false, columnFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -212,6 +212,7 @@ private fun getValidToggleOption(optionName: String, token: String) =
|
|||||||
|
|
||||||
private fun showOptions(
|
private fun showOptions(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
|
context: ExecutionContext,
|
||||||
nameAndToken: Collection<Pair<String, String>>,
|
nameAndToken: Collection<Pair<String, String>>,
|
||||||
scope: OptionAccessScope,
|
scope: OptionAccessScope,
|
||||||
showIntro: Boolean,
|
showIntro: Boolean,
|
||||||
@ -275,7 +276,7 @@ private fun showOptions(
|
|||||||
appendLine(option)
|
appendLine(option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
injector.exOutputPanel.getPanel(editor).output(output)
|
injector.outputPanel.output(editor, context, output)
|
||||||
|
|
||||||
if (unknownOption != null) {
|
if (unknownOption != null) {
|
||||||
throw exExceptionMessage("E518", unknownOption.second)
|
throw exExceptionMessage("E518", unknownOption.second)
|
||||||
|
Loading…
Reference in New Issue
Block a user