[ide-console][bug-fixes] Disable process on closed dialog window

Fix history bugs (lost completion focus, occasional flush)
Faster incomplete icon change
Correct console window title
Other small gui decorations
This commit is contained in:
Dmitry Kovanikov
2015-08-25 18:04:24 +03:00
committed by Pavel V. Talanov
parent b19010184a
commit 3152792860
6 changed files with 48 additions and 24 deletions
@@ -16,12 +16,18 @@
package org.jetbrains.kotlin.console
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.ex.util.EditorUtil
import org.jetbrains.kotlin.console.highlight.ReplOutputType
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
public class KotlinConsoleHistoryManager(private val ktConsole: KotlinConsoleRunner) : KeyAdapter() {
public class KotlinConsoleHistoryManager(private val runner: KotlinConsoleRunner) : KeyAdapter() {
private val project = runner.project
private val consoleEditor: EditorEx by lazy { runner.consoleView.consoleEditor } // [consoleEditor] is null at the moment if instantiation
private val history = arrayListOf<String>()
private var historyPos = 0
@@ -52,14 +58,15 @@ public class KotlinConsoleHistoryManager(private val ktConsole: KotlinConsoleRun
override fun keyReleased(e: KeyEvent): Unit = when (e.keyCode) {
KeyEvent.VK_UP -> moveHistoryCursor(HistoryMove.UP)
KeyEvent.VK_DOWN -> moveHistoryCursor(HistoryMove.DOWN)
KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT -> prevCaretOffset = ktConsole.consoleView.consoleEditor.caretModel.offset
KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT -> prevCaretOffset = consoleEditor.caretModel.offset
}
private fun moveHistoryCursor(move: HistoryMove) {
if (history.isEmpty()) return
if (LookupManager.getInstance(project).activeLookup != null) return
val caret = ktConsole.consoleView.consoleEditor.caretModel
val document = ktConsole.consoleView.editorDocument
val caret = consoleEditor.caretModel
val document = consoleEditor.document
val curOffset = caret.offset
val curLine = document.getLineNumber(curOffset)
@@ -78,23 +85,27 @@ public class KotlinConsoleHistoryManager(private val ktConsole: KotlinConsoleRun
}
historyPos = Math.max(historyPos - 1, 0)
WriteCommandAction.runWriteCommandAction(ktConsole.project) {
WriteCommandAction.runWriteCommandAction(project) {
document.setText(history[historyPos].trim())
caret.moveToOffset(0)
EditorUtil.scrollToTheEnd(consoleEditor)
prevCaretOffset = 0
caret.moveToOffset(0)
}
}
HistoryMove.DOWN -> {
if (historyPos == history.size()) return
if (curLine != totalLines - 1 || (isMultiline && prevCaretOffset != document.textLength)) {
prevCaretOffset = curOffset
return
}
historyPos = Math.min(historyPos + 1, history.size())
WriteCommandAction.runWriteCommandAction(ktConsole.project) {
WriteCommandAction.runWriteCommandAction(project) {
document.setText(if (historyPos == history.size()) unfinishedCommand else history[historyPos].trim())
caret.moveToOffset(document.textLength)
prevCaretOffset = document.textLength
EditorUtil.scrollToTheEnd(consoleEditor)
}
}
}
@@ -35,6 +35,8 @@ import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.concurrent.ConcurrentHashMap
private val REPL_TITLE = "Kotlin REPL"
public class KotlinConsoleKeeper(val project: Project) {
private val consoleMap: MutableMap<VirtualFile, KotlinConsoleRunner> = ConcurrentHashMap()
@@ -46,7 +48,7 @@ public class KotlinConsoleKeeper(val project: Project) {
val path = module.moduleFilePath
val cmdLine = createCommandLine(module) ?: return errorNotification(project, "Module SDK not found") let { null }
val consoleRunner = KotlinConsoleRunner(path, cmdLine, module, project, REPL_TITLE)
val consoleRunner = KotlinConsoleRunner(cmdLine, module, project, REPL_TITLE, path)
consoleRunner.initAndRun()
consoleRunner.setupGutters()
@@ -110,8 +112,6 @@ public class KotlinConsoleKeeper(val project: Project) {
}
companion object {
private val REPL_TITLE = "Kotlin REPL"
jvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, javaClass<KotlinConsoleKeeper>())
}
}
@@ -23,6 +23,7 @@ import com.intellij.execution.process.*
import com.intellij.execution.runners.AbstractConsoleRunnerWithHistory
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.colors.EditorColors
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.markup.*
@@ -47,13 +48,13 @@ import java.util.concurrent.ConcurrentHashMap
import javax.swing.Icon
public class KotlinConsoleRunner(
private val title: String,
private val cmdLine: GeneralCommandLine,
private val module: Module,
myProject: Project,
title: String,
path: String?
) : AbstractConsoleRunnerWithHistory<LanguageConsoleView>(myProject, title, path) {
private val editorToIndicator = ConcurrentHashMap<EditorEx, KotlinConsoleIndicatorRenderer>()
private val editorToIndicator = ConcurrentHashMap<EditorEx, RangeHighlighter>()
private val historyManager = KotlinConsoleHistoryManager(this)
val executor = KotlinConsoleExecutor(this, historyManager)
@@ -119,6 +120,8 @@ public class KotlinConsoleRunner(
}
}
override fun constructConsoleTitle(title: String) = "$title (in module ${module.name})"
private fun setupPlaceholder(editor: EditorEx) {
editor.setPlaceholder("<Ctrl+Enter> to execute")
editor.setShowPlaceholderWhenFocused(true)
@@ -147,10 +150,16 @@ public class KotlinConsoleRunner(
addGutterIndicator(editor, icon)
}
configureEditorGutter(consoleView.historyViewer, ReplColors.HISTORY_GUTTER_COLOR, ReplIcons.HISTORY_INDICATOR)
configureEditorGutter(consoleView.consoleEditor, ReplColors.EDITOR_GUTTER_COLOR, ReplIcons.EDITOR_INDICATOR)
val historyEditor = consoleView.historyViewer
val consoleEditor = consoleView.consoleEditor
consoleView.consoleEditor.settings.isCaretRowShown = true
configureEditorGutter(historyEditor, ReplColors.HISTORY_GUTTER_COLOR, ReplIcons.HISTORY_INDICATOR)
configureEditorGutter(consoleEditor, ReplColors.EDITOR_GUTTER_COLOR, ReplIcons.EDITOR_INDICATOR)
historyEditor.settings.isUseSoftWraps = true
consoleEditor.settings.isCaretRowShown = true
consoleEditor.settings.additionalLinesCount = 2
}
fun addGutterIndicator(editor: EditorEx, icon: Icon) {
@@ -161,10 +170,11 @@ public class KotlinConsoleRunner(
)
indicatorHighlighter.gutterIconRenderer = indicator
editorToIndicator[editor] = indicator
editorToIndicator[editor] = indicatorHighlighter
}
fun changeEditorIndicatorIcon(editor: EditorEx, newIcon: Icon) {
editorToIndicator[editor]?.indicatorIcon = newIcon
val oldHighlighter = editorToIndicator[editor] ?: return
WriteCommandAction.runWriteCommandAction(project) { oldHighlighter.gutterIconRenderer = KotlinConsoleIndicatorRenderer(newIcon) }
}
}
@@ -44,6 +44,8 @@ public class KotlinReplOutputHandler(
private val dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
override fun isSilentlyDestroyOnClose() = true
override fun notifyTextAvailable(text: String, key: Key<*>?) {
// skip "/usr/lib/jvm/java-8-oracle/bin/java -cp ..." intro
if (!text.startsWith(XML_PREFIX)) return super.notifyTextAvailable(text, key)
@@ -19,8 +19,8 @@ package org.jetbrains.kotlin.console.gutter
import com.intellij.openapi.editor.markup.GutterIconRenderer
import javax.swing.Icon
public class KotlinConsoleIndicatorRenderer(var indicatorIcon: Icon) : GutterIconRenderer() {
public class KotlinConsoleIndicatorRenderer(private val indicatorIcon: Icon) : GutterIconRenderer() {
override fun getIcon() = indicatorIcon
override fun hashCode() = System.identityHashCode(this)
override fun equals(other: Any?) = this === other
override fun hashCode() = indicatorIcon.hashCode()
override fun equals(other: Any?) = indicatorIcon == (other as? KotlinConsoleIndicatorRenderer)?.indicatorIcon ?: null
}
@@ -47,6 +47,7 @@ public class KotlinReplOutputHighlighter(
private val runner: KotlinConsoleRunner,
private val historyManager: KotlinConsoleHistoryManager
) {
private val project = runner.project
private val consoleView = runner.consoleView
private val historyEditor = consoleView.historyViewer
private val historyDocument = historyEditor.document
@@ -70,7 +71,7 @@ public class KotlinReplOutputHighlighter(
consoleView.print(command, ReplColors.USER_OUTPUT_CONTENT_TYPE)
}
fun printResultWithGutterIcon(result: String) = WriteCommandAction.runWriteCommandAction(runner.project) {
fun printResultWithGutterIcon(result: String) = WriteCommandAction.runWriteCommandAction(project) {
resetConsoleEditorIndicator()
historyManager.lastCommandType = ReplOutputType.RESULT
@@ -85,7 +86,7 @@ public class KotlinReplOutputHighlighter(
runner.changeEditorIndicatorIcon(consoleView.consoleEditor, ReplIcons.INCOMPLETE_INDICATOR)
}
fun highlightCompilerErrors(compilerMessages: List<SeverityDetails>) = WriteCommandAction.runWriteCommandAction(runner.project) {
fun highlightCompilerErrors(compilerMessages: List<SeverityDetails>) = WriteCommandAction.runWriteCommandAction(project) {
resetConsoleEditorIndicator()
historyManager.lastCommandType = ReplOutputType.ERROR
@@ -137,8 +138,8 @@ public class KotlinReplOutputHighlighter(
): TextAttributes {
val highlightInfo = HighlightInfo.newHighlightInfo(infoType).range(start, end).severity(severity).textAttributes(insightColors).create()
val psiFile = PsiDocumentManager.getInstance(runner.project).getPsiFile(runner.consoleView.consoleEditor.document)
val colorScheme = runner.consoleView.consoleEditor.colorsScheme
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(consoleView.consoleEditor.document)
val colorScheme = consoleView.consoleEditor.colorsScheme
return highlightInfo?.getTextAttributes(psiFile, colorScheme) ?: TextAttributes()
}