From 10c6ec2b847fd78879cf8222dab5387b315bcb5d Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Fri, 14 Sep 2012 16:11:33 +0400 Subject: [PATCH] IDEA-89915 Notification on stderror output in Run panel / Console --- .../configurations/CommandLineState.java | 1 + .../execution/ui/ObservableConsoleView.java | 3 ++- .../logging/LogConfigurationPanel.form | 4 +-- .../execution/impl/ConsoleViewImpl.java | 2 +- .../src/com/intellij/tools/Tool.java | 22 ++++++++++++++++ .../com/intellij/tools/ToolEditorDialog.java | 26 +++++++++++++++++-- .../com/intellij/tools/ToolRunProfile.java | 17 +++++++++--- .../com/intellij/tools/ToolsProcessor.java | 6 +++++ .../src/messages/ExecutionBundle.properties | 2 ++ .../ui/BaseTestsOutputConsoleView.java | 2 +- 10 files changed, 74 insertions(+), 11 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java b/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java index af02ab7c34f2..c242e6f8e3e9 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java @@ -60,6 +60,7 @@ public abstract class CommandLineState implements RunnableState { return myEnvironment.getExecutionTarget(); } + @NotNull public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException { final ProcessHandler processHandler = startProcess(); final ConsoleView console = createConsole(executor); diff --git a/platform/lang-api/src/com/intellij/execution/ui/ObservableConsoleView.java b/platform/lang-api/src/com/intellij/execution/ui/ObservableConsoleView.java index 40ca61d92a54..87fcf415eb63 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/ObservableConsoleView.java +++ b/platform/lang-api/src/com/intellij/execution/ui/ObservableConsoleView.java @@ -17,12 +17,13 @@ package com.intellij.execution.ui; import com.intellij.openapi.Disposable; +import org.jetbrains.annotations.NotNull; import java.util.Collection; public interface ObservableConsoleView { - void addChangeListener(ChangeListener listener, Disposable parent); + void addChangeListener(@NotNull ChangeListener listener, @NotNull Disposable parent); interface ChangeListener { void contentAdded(Collection types); diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConfigurationPanel.form b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConfigurationPanel.form index dc801f846316..b2e9ac44de55 100644 --- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConfigurationPanel.form +++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConfigurationPanel.form @@ -48,7 +48,7 @@ - + @@ -56,7 +56,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 4b368a4fa702..94d22879706f 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -1512,7 +1512,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo } @Override - public void addChangeListener(final ChangeListener listener, final Disposable parent) { + public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) { myListeners.add(listener); Disposer.register(parent, new Disposable() { @Override diff --git a/platform/lang-impl/src/com/intellij/tools/Tool.java b/platform/lang-impl/src/com/intellij/tools/Tool.java index 3c9db88ee02e..2848c547a936 100644 --- a/platform/lang-impl/src/com/intellij/tools/Tool.java +++ b/platform/lang-impl/src/com/intellij/tools/Tool.java @@ -52,6 +52,8 @@ public class Tool implements SchemeElement { private boolean myEnabled; private boolean myUseConsole; + private boolean myShowConsoleOnStdOut; + private boolean myShowConsoleOnStdErr; private boolean mySynchronizeAfterExecution; private String myWorkingDirectory; @@ -103,6 +105,14 @@ public class Tool implements SchemeElement { return myUseConsole; } + public boolean isShowConsoleOnStdOut() { + return myShowConsoleOnStdOut; + } + + public boolean isShowConsoleOnStdErr() { + return myShowConsoleOnStdErr; + } + public boolean synchronizeAfterExecution() { return mySynchronizeAfterExecution; } @@ -139,6 +149,14 @@ public class Tool implements SchemeElement { myUseConsole = useConsole; } + void setShowConsoleOnStdOut(boolean showConsole) { + myShowConsoleOnStdOut = showConsole; + } + + void setShowConsoleOnStdErr(boolean showConsole) { + myShowConsoleOnStdErr = showConsole; + } + public void setFilesSynchronizedAfterRun(boolean synchronizeAfterRun) { mySynchronizeAfterExecution = synchronizeAfterRun; } @@ -192,6 +210,8 @@ public class Tool implements SchemeElement { myShownInSearchResultsPopup = source.myShownInSearchResultsPopup; myEnabled = source.myEnabled; myUseConsole = source.myUseConsole; + myShowConsoleOnStdOut = source.myShowConsoleOnStdOut; + myShowConsoleOnStdErr = source.myShowConsoleOnStdErr; mySynchronizeAfterExecution = source.mySynchronizeAfterExecution; myWorkingDirectory = source.myWorkingDirectory; myProgram = source.myProgram; @@ -215,6 +235,8 @@ public class Tool implements SchemeElement { myShownInSearchResultsPopup == source.myShownInSearchResultsPopup && myEnabled == source.myEnabled && myUseConsole == source.myUseConsole && + myShowConsoleOnStdOut == source.myShowConsoleOnStdOut && + myShowConsoleOnStdErr == source.myShowConsoleOnStdErr && mySynchronizeAfterExecution == source.mySynchronizeAfterExecution && Comparing.equal(myWorkingDirectory, source.myWorkingDirectory) && Comparing.equal(myProgram, source.myProgram) && diff --git a/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java b/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java index 35905c7b2688..98b4302c3b07 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java @@ -16,6 +16,7 @@ package com.intellij.tools; +import com.intellij.execution.ExecutionBundle; import com.intellij.ide.DataManager; import com.intellij.ide.macro.MacroManager; import com.intellij.ide.macro.MacrosDialog; @@ -36,8 +37,11 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.Consumer; +import net.miginfocom.swing.MigLayout; import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.text.BadLocationException; import java.awt.*; @@ -55,6 +59,8 @@ public class ToolEditorDialog extends DialogWrapper { private final JCheckBox myShowInProjectTreeCheckbox = new JCheckBox(ToolsBundle.message("tools.menu.project.checkbox")); private final JCheckBox myShowInSearchResultsPopupCheckbox = new JCheckBox(ToolsBundle.message("tools.menu.search.checkbox")); private final JCheckBox myUseConsoleCheckbox = new JCheckBox(ToolsBundle.message("tools.open.console.checkbox")); + private final JCheckBox myShowConsoleOnStdOutCheckbox = new JCheckBox(ExecutionBundle.message("logs.show.console.on.stdout")); + private final JCheckBox myShowConsoleOnStdErrCheckbox = new JCheckBox(ExecutionBundle.message("logs.show.console.on.stderr")); private final JCheckBox mySynchronizedAfterRunCheckbox = new JCheckBox(ToolsBundle.message("tools.synchronize.files.checkbox")); private boolean myEnabled; @@ -179,6 +185,8 @@ public class ToolEditorDialog extends DialogWrapper { setTitle(ToolsBundle.message("tools.edit.title")); init(); addListeners(); + myShowConsoleOnStdOutCheckbox.setVisible(false); + myShowConsoleOnStdErrCheckbox.setVisible(false); } private JPanel createCommandPane() { @@ -375,6 +383,14 @@ public class ToolEditorDialog extends DialogWrapper { handleOKButton(); } }); + + myUseConsoleCheckbox.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + myShowConsoleOnStdOutCheckbox.setVisible(myUseConsoleCheckbox.isSelected()); + myShowConsoleOnStdErrCheckbox.setVisible(myUseConsoleCheckbox.isSelected()); + } + }); } private void handleOKButton() { @@ -392,6 +408,8 @@ public class ToolEditorDialog extends DialogWrapper { tool.setShownInProjectViews(myShowInProjectTreeCheckbox.isSelected()); tool.setShownInSearchResultsPopup(myShowInSearchResultsPopupCheckbox.isSelected()); tool.setUseConsole(myUseConsoleCheckbox.isSelected()); + tool.setShowConsoleOnStdOut(myShowConsoleOnStdOutCheckbox.isSelected()); + tool.setShowConsoleOnStdErr(myShowConsoleOnStdErrCheckbox.isSelected()); tool.setFilesSynchronizedAfterRun(mySynchronizedAfterRunCheckbox.isSelected()); tool.setEnabled(myEnabled); @@ -428,6 +446,8 @@ public class ToolEditorDialog extends DialogWrapper { myShowInProjectTreeCheckbox.setSelected(tool.isShownInProjectViews()); myShowInSearchResultsPopupCheckbox.setSelected(tool.isShownInSearchResultsPopup()); myUseConsoleCheckbox.setSelected(tool.isUseConsole()); + myShowConsoleOnStdOutCheckbox.setSelected(tool.isShowConsoleOnStdOut()); + myShowConsoleOnStdErrCheckbox.setSelected(tool.isShowConsoleOnStdErr()); mySynchronizedAfterRunCheckbox.setSelected(tool.synchronizeAfterExecution()); myEnabled = tool.isEnabled(); myTfCommandWorkingDirectory.setText(toCurrentSystemFormat(tool.getWorkingDirectory())); @@ -453,11 +473,13 @@ public class ToolEditorDialog extends DialogWrapper { } private JPanel getOptionsPanel() { - JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); + JPanel panel = new JPanel(new MigLayout("fill, gap 10")); panel.setBorder(IdeBorderFactory.createTitledBorder(ToolsBundle.message("tools.options.group"), true)); panel.add(mySynchronizedAfterRunCheckbox); panel.add(myUseConsoleCheckbox); - panel.add(myOutputFiltersButton); + panel.add(myOutputFiltersButton, "ax right, wrap"); + panel.add(myShowConsoleOnStdOutCheckbox); + panel.add(myShowConsoleOnStdErrCheckbox, "spanx 2"); return panel; } diff --git a/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java b/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java index a257e0683989..08637f5fdc9f 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java @@ -16,21 +16,20 @@ package com.intellij.tools; import com.intellij.execution.ExecutionException; +import com.intellij.execution.ExecutionManager; import com.intellij.execution.ExecutionResult; import com.intellij.execution.Executor; import com.intellij.execution.configurations.*; import com.intellij.execution.filters.RegexpFilter; import com.intellij.execution.filters.TextConsoleBuilder; import com.intellij.execution.filters.TextConsoleBuilderFactory; -import com.intellij.execution.process.ColoredProcessHandler; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessHandler; -import com.intellij.execution.process.ProcessTerminatedListener; +import com.intellij.execution.process.*; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -89,11 +88,21 @@ public class ToolRunProfile implements ModuleRunProfile{ return processHandler; } + @NotNull public ExecutionResult execute(@NotNull final Executor executor, @NotNull ProgramRunner runner) throws ExecutionException { final ExecutionResult result = super.execute(executor, runner); final ProcessHandler processHandler = result.getProcessHandler(); if (processHandler != null) { processHandler.addProcessListener(new ToolProcessAdapter(project, myTool.synchronizeAfterExecution(), getName())); + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + if ((outputType == ProcessOutputTypes.STDOUT && myTool.isShowConsoleOnStdOut()) + || (outputType == ProcessOutputTypes.STDERR && myTool.isShowConsoleOnStdErr())) { + ExecutionManager.getInstance(project).getContentManager().toFrontRunContent(executor, processHandler); + } + } + }); } return result; } diff --git a/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java b/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java index 9a921d63c8a5..83aa9f30d07c 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java @@ -42,6 +42,8 @@ class ToolsProcessor extends BaseSchemeProcessor { @NonNls private static final String SHOW_IN_SEARCH_POPUP = "showInSearchPopup"; @NonNls private static final String DISABLED = "disabled"; @NonNls private static final String USE_CONSOLE = "useConsole"; + @NonNls private static final String SHOW_CONSOLE_ON_STDOUT = "showConsoleOnStdOut"; + @NonNls private static final String SHOW_CONSOLE_ON_STDERR = "showConsoleOnStdErr"; @NonNls private static final String SYNCHRONIZE_AFTER_EXECUTION = "synchronizeAfterRun"; @NonNls private static final String EXEC = "exec"; @NonNls private static final String WORKING_DIRECTORY = "WORKING_DIRECTORY"; @@ -76,6 +78,8 @@ class ToolsProcessor extends BaseSchemeProcessor { tool.setShownInSearchResultsPopup(Boolean.valueOf(element.getAttributeValue(SHOW_IN_SEARCH_POPUP)).booleanValue()); tool.setEnabled(!Boolean.valueOf(element.getAttributeValue(DISABLED)).booleanValue()); tool.setUseConsole(Boolean.valueOf(element.getAttributeValue(USE_CONSOLE)).booleanValue()); + tool.setShowConsoleOnStdOut(Boolean.valueOf(element.getAttributeValue(SHOW_CONSOLE_ON_STDOUT)).booleanValue()); + tool.setShowConsoleOnStdErr(Boolean.valueOf(element.getAttributeValue(SHOW_CONSOLE_ON_STDERR)).booleanValue()); tool.setFilesSynchronizedAfterRun(Boolean.valueOf(element.getAttributeValue(SYNCHRONIZE_AFTER_EXECUTION)).booleanValue()); Element exec = element.getChild(EXEC); @@ -150,6 +154,8 @@ class ToolsProcessor extends BaseSchemeProcessor { element.setAttribute(SHOW_IN_SEARCH_POPUP, Boolean.toString(tool.isShownInSearchResultsPopup())); element.setAttribute(DISABLED, Boolean.toString(!tool.isEnabled())); element.setAttribute(USE_CONSOLE, Boolean.toString(tool.isUseConsole())); + element.setAttribute(SHOW_CONSOLE_ON_STDOUT, Boolean.toString(tool.isShowConsoleOnStdOut())); + element.setAttribute(SHOW_CONSOLE_ON_STDERR, Boolean.toString(tool.isShowConsoleOnStdErr())); element.setAttribute(SYNCHRONIZE_AFTER_EXECUTION, Boolean.toString(tool.synchronizeAfterExecution())); Element taskElement = new Element(EXEC); diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index f2b6b490fbd1..ae8c13d27778 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -286,6 +286,8 @@ run.configuration.error.no.jdk.specified=No JDK specified run.configuration.cannot.find.vm.executable=Cannot find VM executable logs.tab.title=Logs +logs.show.console.on.stdout=Show console when standard out changes +logs.show.console.on.stderr=Show console when standard error changes before.launch.panel.title=Before launch before.launch.panel.empty=There are no tasks to run before launch before.launch.panel.cyclic_dependency_warning=''{0}'' has already configured to be launched before {1}.\nSuch cyclic dependencies are not allowed. diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java b/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java index e929f62670ed..753528386c8b 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java @@ -133,7 +133,7 @@ public abstract class BaseTestsOutputConsoleView implements ConsoleView, Observa myConsole = null; } - public void addChangeListener(final ChangeListener listener, final Disposable parent) { + public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) { if (myConsole instanceof ObservableConsoleView) { ((ObservableConsoleView)myConsole).addChangeListener(listener, parent); } else {