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 * ">>>" 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}