如何隐藏控制台视图的输出?

3

我正在编写一个Eclipse插件,用户可以通过控制台视图(在本例中为解释器)与另一个进程进行交互,例如评估表达式等。

有时程序需要向解释器请求某些值。然而,这些交互不应该显示给用户。

我有以下实例:

private IProcess process;
private ILaunch launch;
private IStreamsProxy proxy;

我的程序所做的查询是通过将IStreamListener添加到代理服务器来完成的:

proxy.getOutputStreamMonitor().addListener(new IStreamListener(){
    @Override
    public void streamAppended(String response, IStreamMonitor arg1) {
             doSomeStuffWiththeRepsonse(response);
        }
    });

当监听器正在监听代理的OutputStreamMonitor时,我不希望插件在控制台视图中弹出响应。该怎么办?
3个回答

3

好的,这是我实现它的方式。

Eclipse的启动系统工作如下:

1. 实现一个ILaunchConfigurationDelegate接口,该接口中唯一的方法是launch,它接收一个ILaunchConfiguration、一个模式、一个ILaunch和一个IProgressMonitor参数。

在我的程序中,使用命令行参数使用DebugPlugin.exec()启动一个inferiorProcess。然后通过调用DebugPlugin.newProcess()创建一个新进程,其中包含ILaunch、inferiorProcess、解释器名称和一些属性。此方法创建一个新的RuntimeProcess并将其添加到ILaunch中,反之亦然。

2. 通过使用扩展点org.eclipse.debug.core.launchConfigurationTypes定义一个LaunchConfigurationType,并将其添加到plugin.xml中:

<extension
    point="org.eclipse.debug.core.launchConfigurationTypes">
    <launchConfigurationType
            delegate="myplugin.MyLaunchConfigurationDelegate" (1)
            id="myplugin.myExternalProgram" (2)
            modes="run" (3)
            name="MyExternalProgram" (4)
            public="false"> (5)
      </launchConfigurationType>
</extension>

扩展点提供了创建ILaunchConfigurationDelegate类的确切路径(1)和一个唯一标识符(2),用于从启动程序使用的LaunchManager中检索ILaunchConfigurationType实例。(3)定义它可以运行的模式,rundebug。名称(4)稍后显示在控制台视图的顶部栏中。如果您只想以编程方式访问和启动外部程序(而不是通过“运行”下拉菜单)(5)必须设置为false。
创建一个存储IProcessILaunchIStreamsProxy实例的类,并调用适当的方法启动进程并写入streamsproxy。启动进程的方法可能如下所示:
// is the process already running?
public boolean isRunning() {
        boolean result = false;
        try {
            if (this.process != null) {
                result = true;
                this.process.getExitValue();
                result = false;
            }
        }
        catch (DebugException exception) {
        }
        return result;
}

// start the process
public void start() {
        try {
            if (!isRunning()) {
                // get the ILaunchConfigurationType from the platform
                ILaunchConfigurationType configType = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(myplugin.myExternalProgram);
                // the ILaunchConfigurationType can't be changed or worked with, so get a WorkingCopy
                ILaunchConfigurationWorkingCopy copy = configType.newInstance(null, "myExternalProgram");
                this.launch = copy.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
                IProcess[] processes = this.launch.getProcesses();

                if (processes.length > 0) {
                    // get the IProcess instance from the launch
                    this.process = this.launch.getProcesses()[0];
                    // get the streamsproxy from the process
                    this.proxy = this.process.getStreamsProxy();                       
                }
            }
        }
        catch (CoreException exception) {
        }
        if (isRunning())
            // bring up the console and show it in the workbench
            showConsole();
    }

public void showConsole() {
        if (this.process != null && this.process.getLaunch() != null) {
            IConsole console = DebugUITools.getConsole(this.process);                
            ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console);
            IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
            IViewPart view = page.findView("org.eclipse.ui.console.ConsoleView");
            if (view != null) 
                view.setFocus();
          }
    }

现在来看问题的起始点
控制台视图的IStreamsListener监听IStreamsProxyOutputStreamMonitor时无法检索,因此无法停止监听。无法防止向控制台打印。 OutputStreamMonitor没有提供获取当前监听器的方法。无法仅仅通过子类化并覆盖/添加一些方法来解决问题,因为重要的字段和方法是私有的。

http://www.java2s.com/Open-Source/Java-Document/IDE-Eclipse/debug/org/eclipse/debug/internal/core/OutputStreamMonitor.java.htm

只需复制代码并为fListeners字段添加一个get方法,然后将某些方法的修饰符更改为public。 要将自己的OutputStreamMonitor引入系统中,您需要创建自己的IStreamsProxy。同样,仅子类化不起作用,您需要再次复制代码并进行一些更改。

http://www.java2s.com/Open-Source/Java-Document/IDE-Eclipse/debug/org/eclipse/debug/internal/core/StreamsProxy.java.htm

重要:
public class MyStreamsProxy implements  IStreamsProxy, IStreamsProxy2 {
    /**
     * The monitor for the output stream (connected to standard out of the process)
     */
    private MyOutputStreamMonitor fOutputMonitor;
    /**
     * The monitor for the error stream (connected to standard error of the process)
     */
    private MyOutputStreamMonitor fErrorMonitor;

(...)

public MyStreamsProxy(Process process) {
        if (process == null) {
            return;
        }
        fOutputMonitor = new MyOutputStreamMonitor(process
                .getInputStream());
        fErrorMonitor = new MyOutputStreamMonitor(process
                .getErrorStream());
        fInputMonitor = new InputStreamMonitor(process
                .getOutputStream());
        fOutputMonitor.startMonitoring();
        fErrorMonitor.startMonitoring();
        fInputMonitor.startMonitoring();
    }

唯一需要完成的是提供您自己的 IProcess,该 IProcess 使用您的 IStreamsProxy。这次,只需子类化 RuntimeProcess 并覆盖方法 createStreamsProxy() 即可:
public class MyProcess extends RuntimeProcess {

    public MyProcess(ILaunch launch, Process process, String name,
            Map attributes) {
        super(launch, process, name, attributes);
    }

    @Override
    protected IStreamsProxy createStreamsProxy() {
        String encoding = getLaunch().getAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING);
        return new MyStreamsProxy(getSystemProcess());
    }
}

MyProcess 是通过在 ILaunchConfigurationDelegate 的 launch 方法中创建一个新实例来集成的,而不是使用 DebugPlugin.newProcess()

现在可以隐藏和显示控制台视图的输出。

    /**
     * Storage field for the console listener
     */
    private IStreamListener oldListener;


    /**
     * Hides the output coming from the process so the user doesn't see it.
     */
    protected void hideConsoleOutput() {
        MyOutputStreamMonitor out 
            = (MyOutputStreamMonitor) this.process.getStreamsProxy().getOutputStreamMonitor();
        List<IStreamListener> listeners = out.getListeners();
        // the console listener
        this.oldListener = listeners.get(0);
        out.removeListener(this.oldListener);

    }

    /**
     * Reverts the changes made by hideConsoleOutput() so the user sees the response from the process again.
     */
    protected void exposeConsoleOutput() {
        MyOutputStreamMonitor out 
        = (MyOutputStreamMonitor) this.process.getStreamsProxy().getOutputStreamMonitor();
        out.addListener(oldListener);
        this.oldListener = null;

    }

在添加任何其他监听器之前,必须调用hide和expose方法。可能有更好的解决方案,但这个方法可行。

1

之前的答案解决了问题,我最初也尝试了类似的方法,但经过数小时的尝试仍未能解决。最后,我采取了一些更简单却也有些恶心的方法...基本上是这样的:

...
ILaunch launch =  launcconf.launch(
        ILaunchManager.RUN_MODE, monitor);
DebugUIPlugin.getDefault().
        getProcessConsoleManager().launchRemoved(launch);
...

所以,我基本上告诉控制台管理器监听方法此启动程序已被删除,并且它会移除控制台。至少对我来说似乎很管用。


0
我不想在插件的控制台视图中弹出响应。我该怎么做?
既然这是你真正关心的问题,那么只需切换控制台视图上名为“当标准输出更改时显示控制台”的按钮即可。这比所有其他方法都更简单,并且可以随时打开或关闭。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接