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