Displaying the console in your RCP application

This question has been asked on eclipse.newcomer a couple of times now, so I thought it might be worthwhile to put a response in the blogosphere.

How do I display the System.out console in a view in my Eclipse RCP application?

The answer has two parts. To start, you can redirect console output to an arbitrary PrintStream using System.setOut(somePrintStream);. The second part is that you need a useful PrintStream to write on.

It’s relatively easy to make a plug-in that does exactly what we need. Here’s how you construct the view.

package org.eclipse.console.ui.views;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class LightweightConsoleView extends ViewPart {
private Text text;

public void createPartControl(Composite parent) {
text = new Text(parent, SWT.READ_ONLY | SWT.MULTI);
OutputStream out = new OutputStream() {
@Override
public void write(int b) throws IOException {
if (text.isDisposed()) return;
text.append(String.valueOf((char) b));
}
};
final PrintStream oldOut = System.out;
System.setOut(new PrintStream(out));
text.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
System.setOut(oldOut);
}
});
}

public void setFocus() {
text.setFocus();
}
}

You’ll notice that I’ve created a read-only Text to contain the output. Then I create an anonymous OutputStream that–when told to dump some bytes–appends output to the end of the Text; I wrap that OutputStream in a PrintStream, and we’re off to the races.

The one part that I’m not so comfortable with is making things right again after the console view closes. In this implementation, I remember where output used to be directed and reset it after the view closes. As long as this view is the only one that tries to mess with the console, this will work. As soon as another view tries, things will get a little spooky.

This entry was posted in Uncategorized. Bookmark the permalink.

29 Responses to Displaying the console in your RCP application

  1. Jeroen Leenarts says:

    A logical follow-up would be this one: Any ideas on how to implement a “power-user console”?Sort of to satisfy any text based itches one might have? I can imagine that it can be usefull to be able to edit/query an application’s model through a mini language. :DShould be easy to implement the laguage side with any java based scripting language. (The name of one of those is sitting at the tip of my tongue, can’t remember…😦 )

  2. Anonymous says:

    Converting every byte in the stream to a string and then appending the string to a text field (which is going to cause a repaint) has got to be slow…

  3. Dominique Boucher says:

    Wayne,I translated your Java code in Scheme to show how one can script Eclipse using the SchemeScript plugin.

  4. Anonymous says:

    Not bad. But I think that would be more interested in seeying how to integrate the *eclipse console view* in your RCP application than seeying how to reimplement the wheel.

  5. Anonymous says:

    Hello,I’m using MessageConsole (RCP) and ConsoleManager.There is a bar that you can open new consoles and I want to DO NOT open new consoles.Anyone have ideas?Thanks

  6. spocket says:

    My version of the write-method. This one can also handle calls from threads other than the UI-Thread.@Overridepublic void write(int b) throws IOException{ final String toAppend = String.valueOf( (char) b ); display.asyncExec( new Runnable() { public void run() { if (text.isDisposed()) return; text.append( toAppend ); } } );}

  7. Wayne says:

    Very nice. That should also handle multiple concurrent threads attempting to write to System.out.

  8. Anonymous says:

    I needed to do this in my RCP application, but I wanted the features/feel of the Eclipse console… So, in my Application.java run() I have the following before creating and running the workbench:MessageConsole console = new MessageConsole(“System Output”, null); ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console }); ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console); MessageConsoleStream stream = console.newMessageStream();System.setOut(new PrintStream(stream));System.setErr(new PrintStream(stream)); logger = LoggerFactory.getLogger(Application.class); // Previously declared.This makes System.out, System.err, and anything that any subclass in my RCP app logs using logback magically appear in the standard Eclipse console view. I haven’t tested performance, but it seems fine so far. Feedback is welcome!

  9. Sebastien says:

    Hello!I am currently developing a console that will recieve logging events (for logback, too).So far, I’ve been able to send content to a MessageConsole, and add it to the ConsolePlugin tab.What I would like to do is 3 things:1. Integrate the MessageConsole in my view, and not add it to the ConsoleView.2. Color some logging statements3. Remove old lines, so that my view does not eat all the memory available if 10000 events are recieved.Could anybody give me some hints on how to procede? The first of the previous points is what I’m on at the moment and I am not that close to having a nice result… :(Thanks!🙂

  10. acorona says:

    Very useful tip. But I found it kind of slow. So I changed the implementation of the OutputStream to buffer the output causing a quicker display of the output. Here is my version of the OutputStream: OutputStream out = new OutputStream() { StringBuffer buffer = new StringBuffer(); @Override public void write(final int b) throws IOException { if (text.isDisposed()) return; buffer.append((char) b); } @Override public void write(byte[] b, int off, int len) throws IOException { super.write(b, off, len); flush(); } @Override public void flush() throws IOException { final String newText = buffer.toString(); top.getDisplay().syncExec(new Runnable() { public void run() { text.append(newText); } }); buffer = new StringBuffer(); } };

  11. acorona says:

    The OutputStream I posted before has a problem with multiple threads. I’ve since changed the code and this seems to work better.—–OutputStream out = new OutputStream() { private StringBuffer buffer = new StringBuffer(); private final Object obj = new Object(); @Override public void write(final int b) throws IOException { synchronized (obj) { if (text.isDisposed()) return; buffer.append((char) b); } } @Override public void write(byte[] b, int off, int len) throws IOException { super.write(b, off, len); flush(); } @Override public void flush() throws IOException { synchronized (obj) { final String newText = buffer.toString(); text.append(newText); buffer = new StringBuffer(); } } };

  12. Pingback: Albert G

  13. Pingback: MOBY

  14. Pingback: A blue

  15. Pingback: America the Beautiful Flag Silver Charm

  16. Pingback: Mr.Rick

  17. Pingback: Lavender Awareness Ribbon Photo Charm

  18. Pingback: Kenneth Killin

  19. Pingback: roll control bolsters

  20. Pingback: design padding specialized

  21. Pingback: Mr.Roy

  22. Pingback: Isaac Baber

  23. Pingback: joel bolster

  24. Pingback: pillow talk meaning

  25. Pingback: que bebo se que fumo

  26. Pingback: register for bebo

  27. Thank you for the post, useful !

  28. Vítor Moscon says:

    Hi Mr. Wayne,
    I found your post “Displaying the console in your RCP application” some days ago. I am trying to create a console for an RCP interface (Eclipse 4, Juno) which should show the prompt of a CLI Command-Line Interface of an application. I have used your solution to redirect the output from this CLI to the Text (console), but know I can’t find a way to make the input part of the console. I mean, allow the user input commands in the org.eclipse.swt.widgets.Text. Please, could you please give me any tip, glue, help?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s