Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fleet #935

Merged
merged 15 commits into from
Jul 8, 2024
Merged

Fleet #935

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.group.visual.VimSelection
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.helper.inRepeatMode
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
Expand Down Expand Up @@ -102,7 +102,7 @@ internal class OperatorAction : VimActionHandler.SingleExecution() {

override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val argument = cmd.argument ?: return false
if (!editor.vimStateMachine.isDotRepeatInProgress) {
if (!editor.inRepeatMode) {
argumentCaptured = argument
}
val range = getMotionRange(editor, context, argument, operatorArguments)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.newapi.ij

@CommandOrMotion(keys = ["."], modes = [Mode.NORMAL])
internal class RepeatChangeAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_WRITABLE

override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val state = editor.vimStateMachine
val state = injector.vimState
val lastCommand = VimRepeater.lastChangeCommand

if (lastCommand == null && Extension.lastExtensionHandler == null) return false
Expand Down
54 changes: 39 additions & 15 deletions src/main/java/com/maddyhome/idea/vim/ex/ExOutputModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,75 @@ package com.maddyhome.idea.vim.ex

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.api.VimExOutputPanel
import com.maddyhome.idea.vim.api.VimOutputPanel
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.helper.vimExOutput
import com.maddyhome.idea.vim.ui.ExOutputPanel
import java.lang.ref.WeakReference

// TODO: We need a nicer way to handle output, especially wrt testing, appending + clearing
class ExOutputModel private constructor(private val myEditor: Editor) : VimExOutputPanel {
class ExOutputModel(private val myEditor: WeakReference<Editor>) : VimOutputPanel {
private var isActiveInTestMode = false

override val isActive: Boolean
val editor get() = myEditor.get()

val isActive: Boolean
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
ExOutputPanel.isPanelActive(myEditor)
editor?.let { ExOutputPanel.getNullablePanel(it) }?.myActive ?: false
} else {
isActiveInTestMode
}

override var text: String? = null
override fun addText(text: String, isNewLine: Boolean) {
if (this.text.isNotEmpty() && isNewLine) this.text += "\n$text" else this.text += text
}

override fun show() {
if (editor == null) return
val currentPanel = injector.outputPanel.getCurrentOutputPanel()
if (currentPanel != null && currentPanel != this) currentPanel.close()

editor!!.vimExOutput = this
val exOutputPanel = ExOutputPanel.getInstance(editor!!)
if (!exOutputPanel.myActive) {
if (ApplicationManager.getApplication().isUnitTestMode) {
isActiveInTestMode = true
} else {
exOutputPanel.activate()
}
}
}

override var text: String = ""
get() = if (!ApplicationManager.getApplication().isUnitTestMode) {
ExOutputPanel.getInstance(myEditor).text
editor?.let { ExOutputPanel.getInstance(it).text } ?: ""
} else {
// ExOutputPanel always returns a non-null string
field ?: ""
field
}
set(value) {
// ExOutputPanel will strip a trailing newline. We'll do it now so that tests have the same behaviour. We also
// never pass null to ExOutputPanel, but we do store it for tests, so we know if we're active or not
val newValue = value?.removeSuffix("\n")
val newValue = value.removeSuffix("\n")
if (!ApplicationManager.getApplication().isUnitTestMode) {
ExOutputPanel.getInstance(myEditor).setText(newValue ?: "")
editor?.let { ExOutputPanel.getInstance(it).setText(newValue) }
} else {
field = newValue
isActiveInTestMode = !newValue.isNullOrEmpty()
isActiveInTestMode = newValue.isNotEmpty()
}
}

override fun output(text: String) {
fun output(text: String) {
this.text = text
}

override fun clear() {
text = null
fun clear() {
text = ""
}

override fun close() {
if (!ApplicationManager.getApplication().isUnitTestMode) {
ExOutputPanel.getInstance(myEditor).close()
editor?.let { ExOutputPanel.getInstance(it).close() }
}
else {
isActiveInTestMode = false
Expand All @@ -65,7 +89,7 @@ class ExOutputModel private constructor(private val myEditor: Editor) : VimExOut
fun getInstance(editor: Editor): ExOutputModel {
var model = editor.vimExOutput
if (model == null) {
model = ExOutputModel(editor)
model = ExOutputModel(WeakReference(editor))
editor.vimExOutput = model
}
return model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import com.maddyhome.idea.vim.common.CommandAlias
import com.maddyhome.idea.vim.common.CommandAliasHandler
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.helper.TestInputModel
import com.maddyhome.idea.vim.helper.inRepeatMode
import com.maddyhome.idea.vim.helper.noneOfEnum
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.key.MappingOwner
import com.maddyhome.idea.vim.key.OperatorFunction
import com.maddyhome.idea.vim.newapi.vim
Expand Down Expand Up @@ -150,7 +150,7 @@ object VimExtensionFacade {
/** Returns a single key stroke from the user input similar to 'getchar()'. */
@JvmStatic
fun inputKeyStroke(editor: Editor): KeyStroke {
if (editor.vim.vimStateMachine.isDotRepeatInProgress) {
if (editor.vim.inRepeatMode) {
val input = Extension.consumeKeystroke()
LOG.trace("inputKeyStroke: dot repeat in progress. Input: $input")
return input ?: error("Not enough keystrokes saved: ${Extension.lastExtensionHandler}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissin
import com.maddyhome.idea.vim.extension.exportOperatorFunction
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
import com.maddyhome.idea.vim.helper.PsiHelper
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.key.OperatorFunction
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
Expand All @@ -65,7 +64,7 @@ internal class CommentaryExtension : VimExtension {
selectionType: SelectionType,
resetCaret: Boolean = true,
): Boolean {
val mode = editor.vimStateMachine.mode
val mode = editor.mode
if (mode !is Mode.VISUAL) {
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
}
Expand Down
41 changes: 1 addition & 40 deletions src/main/java/com/maddyhome/idea/vim/group/EditorGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,45 +218,6 @@ public void editorCreated(@NotNull Editor editor) {
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));
}

Expand Down Expand Up @@ -416,7 +377,7 @@ public void propertyChange(PropertyChangeEvent evt) {
// Note that IDE scale is handled by LafManager.lookAndFeelChanged
VimCommandLine activeCommandLine = injector.getCommandLine().getActiveCommandLine();
if (activeCommandLine != null) {
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), false);
injector.getProcessGroup().cancelExEntry(new IjVimEditor(editor), true, false);
}
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor);
if (exOutputModel != null) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/maddyhome/idea/vim/group/FileGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ class FileGroup : VimFileBase() {
val msg = StringBuilder()
val doc = editor.document

if (getInstance(IjVimEditor(editor)).mode !is VISUAL) {
if (injector.vimState.mode !is VISUAL) {
val lp = editor.caretModel.logicalPosition
val col = editor.caretModel.offset - doc.getLineStartOffset(lp.line)
var endoff = doc.getLineEndOffset(lp.line)
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/maddyhome/idea/vim/group/MotionGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import com.maddyhome.idea.vim.helper.getNormalizedScrollOffset
import com.maddyhome.idea.vim.helper.getNormalizedSideScrollOffset
import com.maddyhome.idea.vim.helper.isEndAllowed
import com.maddyhome.idea.vim.helper.vimLastColumn
import com.maddyhome.idea.vim.helper.vimStateMachine
import com.maddyhome.idea.vim.listener.AppCodeTemplates
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
import com.maddyhome.idea.vim.newapi.ij
Expand Down Expand Up @@ -307,13 +306,13 @@ internal class MotionGroup : VimMotionGroupBase() {
val editor = fileEditor.editor
if (!editor.isDisposed) {
editor.vim.let { vimEditor ->
when (vimEditor.vimStateMachine.mode) {
when (vimEditor.mode) {
is Mode.VISUAL -> {
vimEditor.exitVisualMode()
KeyHandler.getInstance().reset(vimEditor)
}
is Mode.CMD_LINE -> {
injector.processGroup.cancelExEntry(vimEditor, false)
injector.processGroup.cancelExEntry(vimEditor, refocusOwningEditor = false, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close()
}
else -> {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ internal object GuicursorChangeListener : EffectiveOptionValueChangeListener {
}

private fun Editor.guicursorMode(): GuiCursorMode {
return GuiCursorMode.fromMode(vim.mode, vim.vimStateMachine.isReplaceCharacter)
return GuiCursorMode.fromMode(vim.mode, injector.vimState.isReplaceCharacter)
}

/**
Expand Down Expand Up @@ -146,21 +146,15 @@ internal fun getGuiCursorMode(editor: Editor) = editor.guicursorMode()

class CaretVisualAttributesListener : IsReplaceCharListener, ModeChangeListener {
override fun isReplaceCharChanged(editor: VimEditor) {
updateCaretsVisual(editor)
updateCaretsVisual()
}

override fun modeChanged(editor: VimEditor, oldMode: Mode) {
updateCaretsVisual(editor)
updateCaretsVisual()
}

private fun updateCaretsVisual(editor: VimEditor) {
if (injector.globalOptions().ideaglobalmode) {
updateAllEditorsCaretsVisual()
} else {
val ijEditor = (editor as IjVimEditor).editor
ijEditor.updateCaretsVisualAttributes()
ijEditor.updateCaretsVisualPosition()
}
private fun updateCaretsVisual() {
updateAllEditorsCaretsVisual()
}

fun updateAllEditorsCaretsVisual() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ val Editor.inVisualMode: Boolean

@get:JvmName("inExMode")
internal val Editor.inExMode
get() = this.vim.vimStateMachine.mode is Mode.CMD_LINE
get() = this.vim.mode is Mode.CMD_LINE
4 changes: 2 additions & 2 deletions src/main/java/com/maddyhome/idea/vim/helper/ModeExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import com.maddyhome.idea.vim.state.mode.returnTo
internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
if (!this.vim.inSelectMode) return

val returnTo = this.vim.vimStateMachine.mode.returnTo
val returnTo = this.vim.mode.returnTo
when (returnTo) {
ReturnTo.INSERT -> {
this.vim.mode = Mode.INSERT
Expand Down Expand Up @@ -64,7 +64,7 @@ internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
if (!this.inSelectMode) return

val returnTo = this.vimStateMachine.mode.returnTo
val returnTo = this.mode.returnTo
when (returnTo) {
ReturnTo.INSERT -> {
this.mode = Mode.INSERT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ internal object ScrollViewHelper {
}

private fun getScrollJump(editor: VimEditor, height: Int): Int {
val flags = VimStateMachine.getInstance(editor).executingCommandFlags
val flags = injector.vimState.executingCommandFlags
val scrollJump = !flags.contains(CommandFlags.FLAG_IGNORE_SCROLL_JUMP)

// Default value is 1. Zero is a valid value, but we normalise to 1 - we always want to scroll at least one line
Expand All @@ -203,7 +203,7 @@ internal object ScrollViewHelper {
val caretColumn = position.column
val halfWidth = getApproximateScreenWidth(editor) / 2
val scrollOffset = getNormalizedSideScrollOffset(editor)
val flags = VimStateMachine.getInstance(vimEditor).executingCommandFlags
val flags = injector.vimState.executingCommandFlags
val allowSidescroll = !flags.contains(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP)
val sidescroll = injector.options(vimEditor).sidescroll
val offsetLeft = caretColumn - (currentVisualLeftColumn + scrollOffset)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ internal var Editor.vimInitialised: Boolean by userDataOr { false }
// ------------------ Editor
internal fun unInitializeEditor(editor: Editor) {
editor.vimLastSelectionType = null
editor.vimStateMachine = null
editor.vimMorePanel = null
editor.vimExOutput = null
editor.vimLastHighlighters = null
Expand All @@ -120,7 +119,6 @@ internal var Editor.vimIncsearchCurrentMatchOffset: Int? by userData()
* @see :help visualmode()
*/
internal var Editor.vimLastSelectionType: SelectionType? by userData()
internal var Editor.vimStateMachine: VimStateMachine? by userData()
internal var Editor.vimEditorGroup: Boolean by userDataOr { false }
internal var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
internal var Editor.vimMorePanel: ExOutputPanel? by userData()
Expand Down
Loading
Loading