Source code: org/gjt/sp/jedit/Macros.java
1 /*
2 * Macros.java - Macro manager
3 * :tabSize=8:indentSize=8:noTabs=false:
4 * :folding=explicit:collapseFolds=1:
5 *
6 * Copyright (C) 1999, 2003 Slava Pestov
7 * Portions copyright (C) 2002 mike dillon
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 package org.gjt.sp.jedit;
25
26 //{{{ Imports
27 import gnu.regexp.RE;
28 import javax.swing.*;
29 import java.awt.*;
30 import java.io.*;
31 import java.util.*;
32 import org.gjt.sp.jedit.msg.*;
33 import org.gjt.sp.util.Log;
34 //}}}
35
36 /**
37 * This class records and runs macros.<p>
38 *
39 * It also contains a few methods useful for displaying output messages
40 * or obtaining input from a macro:
41 *
42 * <ul>
43 * <li>{@link #confirm(Component,String,int)}</li>
44 * <li>{@link #confirm(Component,String,int,int)}</li>
45 * <li>{@link #error(Component,String)}</li>
46 * <li>{@link #input(Component,String)}</li>
47 * <li>{@link #input(Component,String,String)}</li>
48 * <li>{@link #message(Component,String)}</li>
49 * </ul>
50 *
51 * Note that plugins should not use the above methods. Call
52 * the methods in the {@link GUIUtilities} class instead.
53 *
54 * @author Slava Pestov
55 * @version $Id: Macros.java,v 1.37 2003/08/20 20:23:53 spestov Exp $
56 */
57 public class Macros
58 {
59 //{{{ showRunScriptDialog() method
60 /**
61 * Prompts for one or more files to run as macros
62 * @param view The view
63 * @since jEdit 4.0pre7
64 */
65 public static void showRunScriptDialog(View view)
66 {
67 String[] paths = GUIUtilities.showVFSFileDialog(view,
68 null,JFileChooser.OPEN_DIALOG,true);
69 if(paths != null)
70 {
71 Buffer buffer = view.getBuffer();
72 try
73 {
74 buffer.beginCompoundEdit();
75
76 file_loop: for(int i = 0; i < paths.length; i++)
77 runScript(view,paths[i],false);
78 }
79 finally
80 {
81 buffer.endCompoundEdit();
82 }
83 }
84 } //}}}
85
86 //{{{ runScript() method
87 /**
88 * Runs the specified script.
89 * Unlike the {@link BeanShell#runScript(View,String,Reader,boolean)}
90 * method, this method can run scripts supported
91 * by any registered macro handler.
92 * @param view The view
93 * @param path The VFS path of the script
94 * @param ignoreUnknown If true, then unknown file types will be
95 * ignored; otherwise, a warning message will be printed and they will
96 * be evaluated as BeanShell scripts.
97 *
98 * @since jEdit 4.1pre2
99 */
100 public static void runScript(View view, String path, boolean ignoreUnknown)
101 {
102 Handler handler = getHandlerForPathName(path);
103 if(handler != null)
104 {
105 try
106 {
107 Macro newMacro = handler.createMacro(
108 MiscUtilities.getFileName(path), path);
109 newMacro.invoke(view);
110 }
111 catch (Exception e)
112 {
113 Log.log(Log.ERROR, Macros.class, e);
114 return;
115 }
116 return;
117 }
118
119 // only executed if above loop falls
120 // through, ie there is no handler for
121 // this file
122 if(ignoreUnknown)
123 {
124 Log.log(Log.NOTICE,Macros.class,path +
125 ": Cannot find a suitable macro handler");
126 }
127 else
128 {
129 Log.log(Log.ERROR,Macros.class,path +
130 ": Cannot find a suitable macro handler, "
131 + "assuming BeanShell");
132 getHandler("beanshell").createMacro(
133 path,path).invoke(view);
134 }
135 } //}}}
136
137 //{{{ message() method
138 /**
139 * Utility method that can be used to display a message dialog in a macro.
140 * @param comp The component to show the dialog on behalf of, this
141 * will usually be a view instance
142 * @param message The message
143 * @since jEdit 2.7pre2
144 */
145 public static void message(Component comp, String message)
146 {
147 GUIUtilities.hideSplashScreen();
148
149 JOptionPane.showMessageDialog(comp,message,
150 jEdit.getProperty("macro-message.title"),
151 JOptionPane.INFORMATION_MESSAGE);
152 } //}}}
153
154 //{{{ error() method
155 /**
156 * Utility method that can be used to display an error dialog in a macro.
157 * @param comp The component to show the dialog on behalf of, this
158 * will usually be a view instance
159 * @param message The message
160 * @since jEdit 2.7pre2
161 */
162 public static void error(Component comp, String message)
163 {
164 GUIUtilities.hideSplashScreen();
165
166 JOptionPane.showMessageDialog(comp,message,
167 jEdit.getProperty("macro-message.title"),
168 JOptionPane.ERROR_MESSAGE);
169 } //}}}
170
171 //{{{ input() method
172 /**
173 * Utility method that can be used to prompt for input in a macro.
174 * @param comp The component to show the dialog on behalf of, this
175 * will usually be a view instance
176 * @param prompt The prompt string
177 * @since jEdit 2.7pre2
178 */
179 public static String input(Component comp, String prompt)
180 {
181 GUIUtilities.hideSplashScreen();
182
183 return input(comp,prompt,null);
184 } //}}}
185
186 //{{{ input() method
187 /**
188 * Utility method that can be used to prompt for input in a macro.
189 * @param comp The component to show the dialog on behalf of, this
190 * will usually be a view instance
191 * @param prompt The prompt string
192 * @since jEdit 3.1final
193 */
194 public static String input(Component comp, String prompt, String defaultValue)
195 {
196 GUIUtilities.hideSplashScreen();
197
198 return (String)JOptionPane.showInputDialog(comp,prompt,
199 jEdit.getProperty("macro-input.title"),
200 JOptionPane.QUESTION_MESSAGE,null,null,defaultValue);
201 } //}}}
202
203 //{{{ confirm() method
204 /**
205 * Utility method that can be used to ask for confirmation in a macro.
206 * @param comp The component to show the dialog on behalf of, this
207 * will usually be a view instance
208 * @param prompt The prompt string
209 * @param buttons The buttons to display - for example,
210 * JOptionPane.YES_NO_CANCEL_OPTION
211 * @since jEdit 4.0pre2
212 */
213 public static int confirm(Component comp, String prompt, int buttons)
214 {
215 GUIUtilities.hideSplashScreen();
216
217 return JOptionPane.showConfirmDialog(comp,prompt,
218 jEdit.getProperty("macro-confirm.title"),buttons,
219 JOptionPane.QUESTION_MESSAGE);
220 } //}}}
221
222 //{{{ confirm() method
223 /**
224 * Utility method that can be used to ask for confirmation in a macro.
225 * @param comp The component to show the dialog on behalf of, this
226 * will usually be a view instance
227 * @param prompt The prompt string
228 * @param buttons The buttons to display - for example,
229 * JOptionPane.YES_NO_CANCEL_OPTION
230 * @param type The dialog type - for example,
231 * JOptionPane.WARNING_MESSAGE
232 */
233 public static int confirm(Component comp, String prompt, int buttons, int type)
234 {
235 GUIUtilities.hideSplashScreen();
236
237 return JOptionPane.showConfirmDialog(comp,prompt,
238 jEdit.getProperty("macro-confirm.title"),buttons,type);
239 } //}}}
240
241 //{{{ loadMacros() method
242 /**
243 * Rebuilds the macros list, and sends a MacrosChanged message
244 * (views update their Macros menu upon receiving it)
245 * @since jEdit 2.2pre4
246 */
247 public static void loadMacros()
248 {
249 macroActionSet.removeAllActions();
250 macroHierarchy.removeAllElements();
251 macroHash.clear();
252
253 if(jEdit.getJEditHome() != null)
254 {
255 systemMacroPath = MiscUtilities.constructPath(
256 jEdit.getJEditHome(),"macros");
257 loadMacros(macroHierarchy,"",new File(systemMacroPath));
258 }
259
260 String settings = jEdit.getSettingsDirectory();
261
262 if(settings != null)
263 {
264 userMacroPath = MiscUtilities.constructPath(
265 settings,"macros");
266 loadMacros(macroHierarchy,"",new File(userMacroPath));
267 }
268
269 EditBus.send(new DynamicMenuChanged("macros"));
270 } //}}}
271
272 //{{{ registerHandler() method
273 /**
274 * Adds a macro handler to the handlers list
275 * @since jEdit 4.0pre6
276 */
277 public static void registerHandler(Handler handler)
278 {
279 if (getHandler(handler.getName()) != null)
280 {
281 Log.log(Log.ERROR, Macros.class, "Cannot register more than one macro handler with the same name");
282 return;
283 }
284
285 Log.log(Log.DEBUG,Macros.class,"Registered " + handler.getName()
286 + " macro handler");
287 macroHandlers.add(handler);
288 } //}}}
289
290 //{{{ getHandlers() method
291 /**
292 * Returns an array containing the list of registered macro handlers
293 * @since jEdit 4.0pre6
294 */
295 public static Handler[] getHandlers()
296 {
297 Handler[] handlers = new Handler[macroHandlers.size()];
298 return (Handler[])macroHandlers.toArray(handlers);
299 } //}}}
300
301 //{{{ getHandlerForFileName() method
302 /**
303 * Returns the macro handler suitable for running the specified file
304 * name, or null if there is no suitable handler.
305 * @since jEdit 4.1pre3
306 */
307 public static Handler getHandlerForPathName(String pathName)
308 {
309 for (int i = 0; i < macroHandlers.size(); i++)
310 {
311 Handler handler = (Handler)macroHandlers.get(i);
312 if (handler.accept(pathName))
313 return handler;
314 }
315
316 return null;
317 } //}}}
318
319 //{{{ getHandler() method
320 /**
321 * Returns the macro handler with the specified name, or null if
322 * there is no registered handler with that name.
323 * @since jEdit 4.0pre6
324 */
325 public static Handler getHandler(String name)
326 {
327 Handler handler = null;
328 for (int i = 0; i < macroHandlers.size(); i++)
329 {
330 handler = (Handler)macroHandlers.get(i);
331 if (handler.getName().equals(name)) return handler;
332 }
333
334 return null;
335 }
336 //}}}
337
338 //{{{ getMacroHierarchy() method
339 /**
340 * Returns a vector hierarchy with all known macros in it.
341 * Each element of this vector is either a macro name string,
342 * or another vector. If it is a vector, the first element is a
343 * string label, the rest are again, either macro name strings
344 * or vectors.
345 * @since jEdit 2.6pre1
346 */
347 public static Vector getMacroHierarchy()
348 {
349 return macroHierarchy;
350 } //}}}
351
352 //{{{ getMacroActionSet() method
353 /**
354 * Returns an action set with all known macros in it.
355 * @since jEdit 4.0pre1
356 */
357 public static ActionSet getMacroActionSet()
358 {
359 return macroActionSet;
360 } //}}}
361
362 //{{{ getMacro() method
363 /**
364 * Returns the macro with the specified name.
365 * @param macro The macro's name
366 * @since jEdit 2.6pre1
367 */
368 public static Macro getMacro(String macro)
369 {
370 return (Macro)macroHash.get(macro);
371 } //}}}
372
373 //{{{ Macro class
374 /**
375 * Encapsulates the macro's label, name and path.
376 * @since jEdit 2.2pre4
377 */
378 public static class Macro extends EditAction
379 {
380 //{{{ Macro constructor
381 public Macro(Handler handler, String name, String label, String path)
382 {
383 // in case macro file name has a space in it.
384 // spaces break the view.toolBar property, for instance,
385 // since it uses spaces to delimit action names.
386 super(name.replace(' ','_'));
387 this.handler = handler;
388 this.label = label;
389 this.path = path;
390
391 jEdit.setTemporaryProperty(getName() + ".label",label);
392 jEdit.setTemporaryProperty(getName() + ".mouse-over",
393 handler.getLabel() + " - " + path);
394 } //}}}
395
396 //{{{ getHandler() method
397 public Handler getHandler()
398 {
399 return handler;
400 }
401 //}}}
402
403 //{{{ getPath() method
404 public String getPath()
405 {
406 return path;
407 } //}}}
408
409 //{{{ invoke() method
410 public void invoke(View view)
411 {
412 if(view == null)
413 handler.runMacro(null,this);
414 else
415 {
416 Buffer buffer = view.getBuffer();
417
418 try
419 {
420 buffer.beginCompoundEdit();
421 handler.runMacro(view,this);
422 }
423 finally
424 {
425 buffer.endCompoundEdit();
426 }
427 }
428 } //}}}
429
430 //{{{ getCode() method
431 public String getCode()
432 {
433 return "Macros.getMacro(\"" + getName() + "\").invoke(view);";
434 } //}}}
435
436 //{{{ macroNameToLabel() method
437 public static String macroNameToLabel(String macroName)
438 {
439 int index = macroName.lastIndexOf('/');
440 return macroName.substring(index + 1).replace('_', ' ');
441 }
442 //}}}
443
444 //{{{ Private members
445 private Handler handler;
446 private String path;
447 private String label;
448 //}}}
449 } //}}}
450
451 //{{{ recordTemporaryMacro() method
452 /**
453 * Starts recording a temporary macro.
454 * @param view The view
455 * @since jEdit 2.7pre2
456 */
457 public static void recordTemporaryMacro(View view)
458 {
459 String settings = jEdit.getSettingsDirectory();
460
461 if(settings == null)
462 {
463 GUIUtilities.error(view,"no-settings",new String[0]);
464 return;
465 }
466 if(view.getMacroRecorder() != null)
467 {
468 GUIUtilities.error(view,"already-recording",new String[0]);
469 return;
470 }
471
472 Buffer buffer = jEdit.openFile(null,settings + File.separator
473 + "macros","Temporary_Macro.bsh",true,null);
474
475 if(buffer == null)
476 return;
477
478 buffer.remove(0,buffer.getLength());
479 buffer.insert(0,jEdit.getProperty("macro.temp.header"));
480
481 recordMacro(view,buffer,true);
482 } //}}}
483
484 //{{{ recordMacro() method
485 /**
486 * Starts recording a macro.
487 * @param view The view
488 * @since jEdit 2.7pre2
489 */
490 public static void recordMacro(View view)
491 {
492 String settings = jEdit.getSettingsDirectory();
493
494 if(settings == null)
495 {
496 GUIUtilities.error(view,"no-settings",new String[0]);
497 return;
498 }
499
500 if(view.getMacroRecorder() != null)
501 {
502 GUIUtilities.error(view,"already-recording",new String[0]);
503 return;
504 }
505
506 String name = GUIUtilities.input(view,"record",null);
507 if(name == null)
508 return;
509
510 name = name.replace(' ','_');
511
512 Buffer buffer = jEdit.openFile(null,null,
513 MiscUtilities.constructPath(settings,"macros",
514 name + ".bsh"),true,null);
515
516 if(buffer == null)
517 return;
518
519 buffer.remove(0,buffer.getLength());
520 buffer.insert(0,jEdit.getProperty("macro.header"));
521
522 recordMacro(view,buffer,false);
523 } //}}}
524
525 //{{{ stopRecording() method
526 /**
527 * Stops a recording currently in progress.
528 * @param view The view
529 * @since jEdit 2.7pre2
530 */
531 public static void stopRecording(View view)
532 {
533 Recorder recorder = view.getMacroRecorder();
534
535 if(recorder == null)
536 GUIUtilities.error(view,"macro-not-recording",null);
537 else
538 {
539 view.setMacroRecorder(null);
540 if(!recorder.temporary)
541 view.setBuffer(recorder.buffer);
542 recorder.dispose();
543 }
544 } //}}}
545
546 //{{{ runTemporaryMacro() method
547 /**
548 * Runs the temporary macro.
549 * @param view The view
550 * @since jEdit 2.7pre2
551 */
552 public static void runTemporaryMacro(View view)
553 {
554 String settings = jEdit.getSettingsDirectory();
555
556 if(settings == null)
557 {
558 GUIUtilities.error(view,"no-settings",null);
559 return;
560 }
561
562 String path = MiscUtilities.constructPath(
563 jEdit.getSettingsDirectory(),"macros",
564 "Temporary_Macro.bsh");
565
566 if(jEdit.getBuffer(path) == null)
567 {
568 GUIUtilities.error(view,"no-temp-macro",null);
569 return;
570 }
571
572 Handler handler = getHandler("beanshell");
573 Macro temp = handler.createMacro(path,path);
574
575 Buffer buffer = view.getBuffer();
576
577 try
578 {
579 buffer.beginCompoundEdit();
580 temp.invoke(view);
581 }
582 finally
583 {
584 /* I already wrote a comment expaining this in
585 * Macro.invoke(). */
586 if(buffer.insideCompoundEdit())
587 buffer.endCompoundEdit();
588 }
589 } //}}}
590
591 //{{{ Private members
592
593 //{{{ Static variables
594 private static String systemMacroPath;
595 private static String userMacroPath;
596
597 private static ArrayList macroHandlers;
598
599 private static ActionSet macroActionSet;
600 private static Vector macroHierarchy;
601 private static Hashtable macroHash;
602 //}}}
603
604 //{{{ Class initializer
605 static
606 {
607 macroHandlers = new ArrayList();
608 registerHandler(new BeanShellHandler());
609 macroActionSet = new ActionSet(jEdit.getProperty("action-set.macros"));
610 jEdit.addActionSet(macroActionSet);
611 macroHierarchy = new Vector();
612 macroHash = new Hashtable();
613 } //}}}
614
615 //{{{ loadMacros() method
616 private static void loadMacros(Vector vector, String path, File directory)
617 {
618 File[] macroFiles = directory.listFiles();
619 if(macroFiles == null || macroFiles.length == 0)
620 return;
621
622 for(int i = 0; i < macroFiles.length; i++)
623 {
624 File file = macroFiles[i];
625 String fileName = file.getName();
626 if(file.isHidden())
627 {
628 /* do nothing! */
629 continue;
630 }
631 else if(file.isDirectory())
632 {
633 String submenuName = fileName.replace('_',' ');
634 Vector submenu = null;
635 //{{{ try to merge with an existing menu first
636 for(int j = 0; j < vector.size(); j++)
637 {
638 Object obj = vector.get(j);
639 if(obj instanceof Vector)
640 {
641 Vector vec = (Vector)obj;
642 if(((String)vec.get(0)).equals(submenuName))
643 {
644 submenu = vec;
645 break;
646 }
647 }
648 } //}}}
649 if(submenu == null)
650 {
651 submenu = new Vector();
652 submenu.addElement(submenuName);
653 vector.addElement(submenu);
654 }
655
656 loadMacros(submenu,path + fileName + '/',file);
657 }
658 else
659 {
660 Handler handler = getHandlerForPathName(file.getPath());
661
662 if(handler == null)
663 continue;
664
665 try
666 {
667 Macro newMacro = handler.createMacro(
668 path + fileName, file.getPath());
669 vector.addElement(newMacro.getName());
670 macroActionSet.addAction(newMacro);
671 macroHash.put(newMacro.getName(),newMacro);
672 }
673 catch (Exception e)
674 {
675 Log.log(Log.ERROR, Macros.class, e);
676 macroHandlers.remove(handler);
677 }
678 }
679 }
680 } //}}}
681
682 //{{{ recordMacro() method
683 /**
684 * Starts recording a macro.
685 * @param view The view
686 * @param buffer The buffer to record to
687 * @param temporary True if this is a temporary macro
688 * @since jEdit 3.0pre5
689 */
690 private static void recordMacro(View view, Buffer buffer, boolean temporary)
691 {
692 Handler handler = getHandler("beanshell");
693 String path = buffer.getPath();
694
695 view.setMacroRecorder(new Recorder(view,buffer,temporary));
696
697 // setting the message to 'null' causes the status bar to check
698 // if a recording is in progress
699 view.getStatus().setMessage(null);
700 } //}}}
701
702 //}}}
703
704 //{{{ Recorder class
705 /**
706 * Handles macro recording.
707 */
708 public static class Recorder implements EBComponent
709 {
710 View view;
711 Buffer buffer;
712 boolean temporary;
713
714 boolean lastWasInput;
715 boolean lastWasOverwrite;
716 int overwriteCount;
717
718 //{{{ Recorder constructor
719 public Recorder(View view, Buffer buffer, boolean temporary)
720 {
721 this.view = view;
722 this.buffer = buffer;
723 this.temporary = temporary;
724 EditBus.addToBus(this);
725 } //}}}
726
727 //{{{ record() method
728 public void record(String code)
729 {
730 flushInput();
731
732 append("\n");
733 append(code);
734 } //}}}
735
736 //{{{ record() method
737 public void record(int repeat, String code)
738 {
739 if(repeat == 1)
740 record(code);
741 else
742 {
743 record("for(int i = 1; i <= " + repeat + "; i++)\n"
744 + "{\n"
745 + code + "\n"
746 + "}");
747 }
748 } //}}}
749
750 //{{{ recordInput() method
751 /**
752 * @since jEdit 4.2pre5
753 */
754 public void recordInput(int repeat, char ch, boolean overwrite)
755 {
756 // record \n and \t on lines specially so that auto indent
757 // can take place
758 if(ch == '\n')
759 record(repeat,"textArea.userInput(\'\\n\');");
760 else if(ch == '\t')
761 record(repeat,"textArea.userInput(\'\\t\');");
762 else
763 {
764 StringBuffer buf = new StringBuffer();
765 for(int i = 0; i < repeat; i++)
766 buf.append(ch);
767 recordInput(buf.toString(),overwrite);
768 }
769 } //}}}
770
771 //{{{ recordInput() method
772 /**
773 * @since jEdit 4.2pre5
774 */
775 public void recordInput(String str, boolean overwrite)
776 {
777 String charStr = MiscUtilities.charsToEscapes(str);
778
779 if(overwrite)
780 {
781 if(lastWasOverwrite)
782 {
783 overwriteCount++;
784 append(charStr);
785 }
786 else
787 {
788 flushInput();
789 overwriteCount = 1;
790 lastWasOverwrite = true;
791 append("\ntextArea.setSelectedText(\"" + charStr);
792 }
793 }
794 else
795 {
796 if(lastWasInput)
797 append(charStr);
798 else
799 {
800 flushInput();
801 lastWasInput = true;
802 append("\ntextArea.setSelectedText(\"" + charStr);
803 }
804 }
805 } //}}}
806
807 //{{{ handleMessage() method
808 public void handleMessage(EBMessage msg)
809 {
810 if(msg instanceof BufferUpdate)
811 {
812 BufferUpdate bmsg = (BufferUpdate)msg;
813 if(bmsg.getWhat() == BufferUpdate.CLOSED)
814 {
815 if(bmsg.getBuffer() == buffer)
816 stopRecording(view);
817 }
818 }
819 } //}}}
820
821 //{{{ append() method
822 private void append(String str)
823 {
824 buffer.insert(buffer.getLength(),str);
825 } //}}}
826
827 //{{{ dispose() method
828 private void dispose()
829 {
830 flushInput();
831
832 for(int i = 0; i < buffer.getLineCount(); i++)
833 {
834 buffer.indentLine(i,true);
835 }
836
837 EditBus.removeFromBus(this);
838
839 // setting the message to 'null' causes the status bar to
840 // check if a recording is in progress
841 view.getStatus().setMessage(null);
842 } //}}}
843
844 //{{{ flushInput() method
845 /**
846 * We try to merge consecutive inputs. This helper method is
847 * called when something other than input is to be recorded.
848 */
849 private void flushInput()
850 {
851 if(lastWasInput)
852 {
853 lastWasInput = false;
854 append("\");");
855 }
856
857 if(lastWasOverwrite)
858 {
859 lastWasOverwrite = false;
860 append("\");\n");
861 append("offset = buffer.getLineEndOffset("
862 + "textArea.getCaretLine()) - 1;\n");
863 append("buffer.remove(textArea.getCaretPosition(),"
864 + "Math.min(" + overwriteCount
865 + ",offset - "
866 + "textArea.getCaretPosition()));");
867 }
868 } //}}}
869 } //}}}
870
871 //{{{ Handler class
872 /**
873 * Encapsulates creating and invoking macros in arbitrary scripting languages
874 * @since jEdit 4.0pre6
875 */
876 public static abstract class Handler
877 {
878 //{{{ getName() method
879 public String getName()
880 {
881 return name;
882 } //}}}
883
884 //{{{ getLabel() method
885 public String getLabel()
886 {
887 return label;
888 } //}}}
889
890 //{{{ accept() method
891 public boolean accept(String path)
892 {
893 return filter.isMatch(MiscUtilities.getFileName(path));
894 } //}}}
895
896 //{{{ createMacro() method
897 public abstract Macro createMacro(String macroName, String path);
898 //}}}
899
900 //{{{ runMacro() method
901 /**
902 * Runs the specified macro.
903 * @param view The view - may be null.
904 * @param macro The macro.
905 */
906 public abstract void runMacro(View view, Macro macro);
907 //}}}
908
909 //{{{ runMacro() method
910 /**
911 * Runs the specified macro. This method is optional; it is
912 * called if the specified macro is a startup script. The
913 * default behavior is to simply call {@link #runMacro(View,Macros.Macro)}.
914 *
915 * @param view The view - may be null.
916 * @param macro The macro.
917 * @param ownNamespace A hint indicating whenever functions and
918 * variables defined in the script are to be self-contained, or
919 * made available to other scripts. The macro handler may ignore
920 * this parameter.
921 * @since jEdit 4.1pre3
922 */
923 public void runMacro(View view, Macro macro, boolean ownNamespace)
924 {
925 runMacro(view,macro);
926 } //}}}
927
928 //{{{ Handler constructor
929 protected Handler(String name)
930 {
931 this.name = name;
932 label = jEdit.getProperty("macro-handler."
933 + name + ".label", name);
934 try
935 {
936 filter = new RE(MiscUtilities.globToRE(
937 jEdit.getProperty(
938 "macro-handler." + name + ".glob")));
939 }
940 catch (Exception e)
941 {
942 throw new InternalError("Missing or invalid glob for handler " + name);
943 }
944 } //}}}
945
946 //{{{ Private members
947 private String name;
948 private String label;
949 private RE filter;
950 //}}}
951 } //}}}
952
953 //{{{ BeanShellHandler class
954 static class BeanShellHandler extends Handler
955 {
956 //{{{ BeanShellHandler constructor
957 BeanShellHandler()
958 {
959 super("beanshell");
960 } //}}}
961
962 //{{{ createMacro() method
963 public Macro createMacro(String macroName, String path)
964 {
965 // Remove '.bsh'
966 macroName = macroName.substring(0, macroName.length() - 4);
967
968 return new Macro(this, macroName,
969 Macro.macroNameToLabel(macroName), path);
970 } //}}}
971
972 //{{{ runMacro() method
973 public void runMacro(View view, Macro macro)
974 {
975 BeanShell.runScript(view,macro.getPath(),null,true);
976 } //}}}
977
978 //{{{ runMacro() method
979 public void runMacro(View view, Macro macro, boolean ownNamespace)
980 {
981 BeanShell.runScript(view,macro.getPath(),null,ownNamespace);
982 } //}}}
983 } //}}}
984 }