001package jmri.script.swing;
002
003import java.io.IOException;
004import java.io.PipedReader;
005import java.io.PipedWriter;
006import javax.script.ScriptContext;
007import javax.swing.JTextArea;
008import jmri.InstanceManager;
009import jmri.script.JmriScriptEngineManager;
010import jmri.util.PipeListener;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 *
016 * @author Randall Wood
017 */
018public class ScriptOutput {
019
020    /**
021     * JTextArea containing the output
022     */
023    private JTextArea output = null;
024    private final static Logger log = LoggerFactory.getLogger(ScriptOutput.class);
025
026    /**
027     * Provide access to the JTextArea containing all ScriptEngine output.
028     * <p>
029     * The output JTextArea is not created until this is invoked, so that code
030     * that doesn't use this feature can run on GUI-less machines.
031     * <p>
032     * This creates a "ScriptOutput PipeListener" thread which is not normally terminated.
033     * @return component containing script output
034     */
035    public JTextArea getOutputArea() {
036        if (output == null) {
037            // convert to stored output
038
039            try {
040                // create the output area
041                output = new JTextArea();
042
043                // Add the I/O pipes
044                PipedWriter pw = new PipedWriter();
045
046                ScriptContext context = JmriScriptEngineManager.getDefault().getDefaultContext();
047                context.setErrorWriter(pw);
048                context.setWriter(pw);
049
050                // ensure the output pipe is read and stored into a
051                // Swing TextArea data model
052                PipedReader pr = new PipedReader(pw);
053                PipeListener pl = new PipeListener(pr, output);
054                pl.setName("ScriptOutput PipeListener");
055                pl.setDaemon(true);
056                pl.start();
057            } catch (IOException e) {
058                log.error("Exception creating script output area", e);
059                return null;
060            }
061        }
062        return output;
063    }
064
065    static public ScriptOutput getDefault() {
066        if (InstanceManager.getNullableDefault(ScriptOutput.class) == null) {
067            InstanceManager.store(new ScriptOutput(), ScriptOutput.class);
068        }
069        return InstanceManager.getDefault(ScriptOutput.class);
070    }
071
072    /**
073     * Write a script to the output area. The output is prepended with a leading
074     * "&gt;&gt;&gt;" on the first line and a leading ellipsis on subsequent
075     * lines.
076     *
077     * @param script The script to write.
078     */
079    static public void writeScript(final String script) {
080        String output = ">>> " + script; // NOI18N
081        // Strip ending newlines
082        while (output.endsWith("\n")) { // NOI18N
083            output = output.substring(0, output.length() - 1);
084        }
085        output = output.replaceAll("\n", "\n... "); // NOI18N
086        output += "\n"; // NOI18N
087        ScriptOutput.getDefault().getOutputArea().append(output);
088    }
089}