PageRenderTime 135ms CodeModel.GetById 105ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/XInsert/src/XScripter.java

#
Java | 327 lines | 187 code | 21 blank | 119 comment | 66 complexity | f246e2d2ce759ce41c6ed1327718aae1 MD5 | raw file
  1/*
  2* Wed Jul 26 16:09:28 2000
  3*
  4* XScripter.java - Running/Managing XInsert Scripts
  5* Copyright (C) 1999 Dominic Stolerman
  6* dominic@sspd.org.uk
  7*
  8* This program is free software; you can redistribute it and/or
  9* modify it under the terms of the GNU General Public License
 10* as published by the Free Software Foundation; either version 2
 11* of the License, or any later version.
 12*
 13* This program is distributed in the hope that it will be useful,
 14* but WITHOUT ANY WARRANTY; without even the implied warranty of
 15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16* GNU General Public License for more details.
 17*
 18* You should have received a copy of the GNU General Public License
 19* along with this program; if not, write to the Free Software
 20* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21*/
 22import org.gjt.sp.jedit.*;
 23import org.gjt.sp.util.Log;
 24
 25import javax.swing.JOptionPane;
 26import javax.swing.SwingUtilities;
 27import java.io.File;
 28
 29
 30/**
 31*
 32* @author     Dominic Stolerman
 33* @created    20 September 2000
 34*/
 35public class XScripter
 36{
 37/**
 38  * Constructor for the XScripter object
 39  */
 40  private XScripter() {}
 41
 42/**
 43 * @deprecated use getSubstituteFor(View, String, XtreeNode) instead as it does exactly the same
 44 */
 45  @Deprecated
 46  public static String _getSubstituteFor(View view, String in, XTreeNode node) {
 47    return getSubstituteFor(view, in, node);
 48    }
 49
 50  private static Command getCommand(View view, XTreeNode node, String command) {
 51    char c = command.charAt(0);
 52    if(c == '$') {
 53      // Substitute variable
 54      //Log.log(Log.DEBUG, XScripter.class, "Adding substitute variable (\"" + command + "\") command to queue");
 55      return new SubVariableCommand(command);
 56      }
 57    else if(c == '!') {
 58      // Run Java function
 59      //Log.log(Log.DEBUG, XScripter.class, "Adding run java (\"" + command + "\") command to queue");
 60      return new RunJavaCommand(command);
 61      }
 62    else if(c == '@') {
 63      // Run macro comand
 64      //Log.log(Log.DEBUG, XScripter.class, "Adding run macro (\"" + command + "\") command to queue");
 65      return new MacroCommand(command);
 66      }
 67    else if(c == '%') {
 68      // Set variable
 69      //Log.log(Log.DEBUG, XScripter.class, "Adding set variable (\"" + command + "\") command to queue");
 70      return new ShowDialogCommand(command);
 71      }
 72    else {
 73      doError(command, "Command not recognised");
 74      return new InsertTextCommand(command);
 75      }
 76    }
 77
 78//{{{ invokeAction method
 79  /**
 80  *  invokes an Action.
 81  *
 82  * @param  view    The view to run the script in.
 83  * @param  name    The name of the node item
 84  * @param  content The node content to be invoked as an action.
 85  */
 86  public static void invokeAction(View view, String name, String content) {
 87    // borrowed from jedit/gui/ActionBar.java
 88    Log.log(Log.DEBUG, XScripter.class, "Invoking action for item named = " + name);
 89    final int repeatCount = 1; //  is it worthwhile to make this configurable?
 90    final View v = view;
 91    final EditAction action = (content == null ? null : jEdit.getAction(content));
 92    if (action == null) {
 93       if(content != null) 
 94	   view.getStatus().setMessageAndClear(jEdit.getProperty("view.action.no-completions"));
 95       }
 96    SwingUtilities.invokeLater(new Runnable() {
 97       public void run(){
 98	   v.getInputHandler().setRepeatCount(repeatCount);
 99           v.getInputHandler().invokeAction(action);
100           }
101       });
102    } //}}}
103
104//{{{ runMacro method
105  /**
106  *  runs the node content as a BeanShell macro.
107  *
108  * @param  view    The view to run the script in.
109  * @param  name    The name of the node item
110  * @param  macro   The node content to be evaluated as a macro
111  */
112  public static void runMacro(View view, String name, String macro) {
113    Log.log(Log.DEBUG, XScripter.class, "Running runMacro for item named = " + name);
114    BeanShell.eval(view, BeanShell.getNameSpace(), macro);
115    } //}}}
116
117//{{{ runNamedMacro method
118  /**
119  *  runs a named (existing) macro
120  *
121  * @param  view    The view to run the script in.
122  * @param  name    The name of the node item
123  * @param  path    The node content giving the internal name or full path of the macro.
124  */
125  public static void runNamedMacro(View view, String name, String path) {
126	Log.log(Log.DEBUG, XScripter.class, "Running runNamedMacro for item named = " + name + ", path=" + path);
127	// NOTE: old-style macro names
128	if(path.startsWith("play-macro@")) {
129		path = path.substring(11);
130		}
131	Macros.Macro macro = Macros.getMacro(path);
132	if(macro != null) {
133		// NOTE: this is the internal representation of a macro
134		macro.invoke(view);
135		}
136	else {
137		// NOTE: this is the alternative representation: the macro's full path
138		File macroFile = new File(path);
139		if(macroFile.exists()) {
140			BeanShell.runScript(view, path, null, true);
141			}
142		else {
143			Log.log(Log.ERROR, XScripter.class,
144				"Could not find macro named " + path);
145			}
146		}
147  	} //}}}
148
149
150  /**
151  *  searches for a variable recursivley through nodes for variable, returns
152  *  the first it finds.
153  *
154  * @param  view    the view to be used for view specific variables
155  * @param  key     the variable name
156  * @param  node    the tree node from where to start the search
157  * @return         the variable value or null if the variable is not found
158  */
159
160//{{{ getSubstituteFor method
161  public static String getSubstituteFor(View view, String key, XTreeNode node) {
162	XTreeNode parentNode = node;
163	String val = null;
164	do {
165		if(parentNode.hasVariables() && parentNode.containsVariable(key)) {
166			val = parentNode.getVariable(key);
167			}
168	} while ((parentNode = (XTreeNode) parentNode.getParent()) != null);
169	if(val == null && XInsertPlugin.containsVariable(key)) {
170		val = XInsertPlugin.getVariable(key);
171		}
172	if(val == null && view != null) {
173		val = XInsertPlugin.getViewSpecificVariable(view, key);
174		}
175	return val == null ? null : MiscUtilities.escapesToChars(val);
176	} //}}}
177
178  /**
179  *  insert text.
180  *
181  /**
182  *  invokes an Action.
183  *
184  * @param  view    The view to run the script in.
185  * @param  node    The node item
186  * @param  text  The node content to be inserted.
187  */
188  public static void insertText(View view, String text, XTreeNode node) {
189    CommandQueue queue = new CommandQueue();
190    ScriptContext context = new ScriptContext(view, node, queue);
191    Buffer buffer = view.getBuffer();
192    buffer.beginCompoundEdit();
193    InsertTextCommand.insertText(text, context);
194    buffer.endCompoundEdit();
195    }
196
197//{{{ runXInsertScript method
198  /**
199  *  runs an XInsertScript.
200  *
201  * @param  view    The view to run the script in.
202  * @param  script  The node content to be run as a script.
203  * @param  node    The node from where to start searching for variable substitutions
204  */
205  public static void runXInsertScript(View view, String script, XTreeNode node) {
206    CommandQueue queue = new CommandQueue();
207    Buffer buffer = view.getBuffer();
208    buffer.beginCompoundEdit();
209    try {
210      char[] chars = script.toCharArray();
211      int start = 0;
212      for(int i = start; i < chars.length; i++) {
213        switch (chars[i]) {
214          case '{':
215            if( chars[i + 1] == '$' || chars[i + 1] == '@' || chars[i + 1] == '!' ||
216            chars[i + 1] == '%' || chars[i + 1] == '#' || chars[i + 1] == '*' ||
217            chars[i + 1] == '&') {
218                //Log.log(Log.DEBUG, XScripter.class, "Adding insert text (\"" + text + "\") command to queue");
219                //Insert the text between the last command and this one
220                String text = script.substring(start, i);
221                queue.add(new InsertTextCommand(text));
222                int j;
223                inner:
224                for(j = i; j < chars.length; j++) {
225                    if(chars[j] == '}' && chars[j - 1] != '\\') { //If end of command
226                        String cmd = script.substring(i + 1, j);
227                        cmd = Utilities.replace(cmd, "\\}", "}");
228                        queue.add(getCommand(view, node, cmd));  //Add this command to queue
229                        break inner;
230                        }
231                    }
232                i = j; //set parsing to continue at the end of the command
233                start = j + 1; //set the start position for the next insert text command
234                }
235            break;
236            }
237          }
238      String remainder = script.substring(start, script.length());
239      queue.add(new InsertTextCommand(remainder)); //Insert the text left over
240      //Run commands in queue
241      ScriptContext context = new ScriptContext(view, node, queue);
242      queue.executeAll(context);
243      }
244    catch (StringIndexOutOfBoundsException e) {
245      doError("Unknown", "Missing \"}\"");
246      return;
247      }
248    catch (Exception e) {
249	  doError("Unknown", "Syntax error in script - Execution Aborted", e);
250	  return;
251	  }
252    finally {
253      buffer.endCompoundEdit();
254      }
255    } //}}}
256
257//{{{ findWordEnd method
258  /**
259  *  Finds the end of the word at position <code>pos</code> in <code>line</code>.
260  *  <p>this is a slightly modified version of {@link org.gjt.sp.jedit.textarea.TextUtilities#findWordEnd(String, int, String)}</P>
261  */
262  public static int findWordEnd(String line, int pos, String noWordSep) {
263    if(pos != 0) pos--;
264    char ch = line.charAt(pos);
265    if(noWordSep == null) {
266      noWordSep = "";
267      }
268    boolean selectNoLetter = (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1);
269    int wordEnd = line.length();
270    for(int i = pos; i < line.length(); i++) {
271      ch = line.charAt(i);
272      if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1)) {
273        wordEnd = i;
274        break;
275        }
276      }
277    return wordEnd;
278    } //}}}
279
280//{{{ doError methods
281/**
282  *  There was an error in executing the script
283  *
284  * @param  command  The command that was running
285  * @param  message  A message to the user
286  */
287  public static void doError(String command, String message) {
288    doError(command, message, null);
289    } 
290
291/**
292  *  Logs an error which threw an exception
293  *
294  * @param  command  The command that was running
295  * @param  message  A message to the user
296  * @param  ex       The exception
297  */
298  public static void doError(String command, String message, Exception ex) {
299    JOptionPane.showMessageDialog(null, "There was an error running the XInsert Script:\nCommand: "
300       + command
301       + ((message == null) ? "" : "\nMessage: " + message)
302       + ((ex == null) ? "" : "\nException: " + ex.toString()),
303       "Error Running XinsertScript", JOptionPane.ERROR_MESSAGE);
304    Log.log(Log.ERROR, XScripter.class, command + ":" + message);
305    Log.log(Log.ERROR, XScripter.class, ex);
306  }
307
308  public static void doError(String command, Exception ex) {
309    doError(command, null, ex);
310    } //}}}
311
312//{{{ inputDialog methods
313  public static String showInputDialog(View view, String key, String defValue) {
314    return showInputDialog(view, "Please enter a value for \"" + key + "\"", key, defValue);
315    }
316
317  public static String showInputDialog(View view, String message, String key, String defValue) {
318    InputDialog id = new InputDialog(view, key, message, defValue);
319    return id.showDialog();
320    }
321
322  public static String showComboDialog(View view, String message, String key, String[] opts, String defValue, boolean allowUser) {
323    InputDialog id = new InputDialog(view, key, message, defValue, opts, allowUser);
324    return id.showDialog();
325    } //}}}
326  }
327