1 23 24 package org.gjt.sp.jedit; 25 26 import javax.swing.*; 28 import java.awt.*; 29 import java.io.*; 30 import java.util.*; 31 import java.util.regex.Pattern ; 32 import org.gjt.sp.jedit.msg.*; 33 import org.gjt.sp.util.Log; 34 import org.gjt.sp.util.StandardUtilities; 35 37 58 public class Macros 59 { 60 66 public static void showRunScriptDialog(View view) 67 { 68 String [] paths = GUIUtilities.showVFSFileDialog(view, 69 null,JFileChooser.OPEN_DIALOG,true); 70 if(paths != null) 71 { 72 Buffer buffer = view.getBuffer(); 73 try 74 { 75 buffer.beginCompoundEdit(); 76 77 file_loop: for(int i = 0; i < paths.length; i++) 78 runScript(view,paths[i],false); 79 } 80 finally 81 { 82 buffer.endCompoundEdit(); 83 } 84 } 85 } 87 101 public static void runScript(View view, String path, boolean ignoreUnknown) 102 { 103 Handler handler = getHandlerForPathName(path); 104 if(handler != null) 105 { 106 try 107 { 108 Macro newMacro = handler.createMacro( 109 MiscUtilities.getFileName(path), path); 110 newMacro.invoke(view); 111 } 112 catch (Exception e) 113 { 114 Log.log(Log.ERROR, Macros.class, e); 115 return; 116 } 117 return; 118 } 119 120 if(ignoreUnknown) 124 { 125 Log.log(Log.NOTICE,Macros.class,path + 126 ": Cannot find a suitable macro handler"); 127 } 128 else 129 { 130 Log.log(Log.ERROR,Macros.class,path + 131 ": Cannot find a suitable macro handler, " 132 + "assuming BeanShell"); 133 getHandler("beanshell").createMacro( 134 path,path).invoke(view); 135 } 136 } 138 146 public static void message(Component comp, String message) 147 { 148 GUIUtilities.hideSplashScreen(); 149 150 JOptionPane.showMessageDialog(comp,message, 151 jEdit.getProperty("macro-message.title"), 152 JOptionPane.INFORMATION_MESSAGE); 153 } 155 163 public static void error(Component comp, String message) 164 { 165 GUIUtilities.hideSplashScreen(); 166 167 JOptionPane.showMessageDialog(comp,message, 168 jEdit.getProperty("macro-message.title"), 169 JOptionPane.ERROR_MESSAGE); 170 } 172 180 public static String input(Component comp, String prompt) 181 { 182 GUIUtilities.hideSplashScreen(); 183 184 return input(comp,prompt,null); 185 } 187 195 public static String input(Component comp, String prompt, String defaultValue) 196 { 197 GUIUtilities.hideSplashScreen(); 198 199 return (String )JOptionPane.showInputDialog(comp,prompt, 200 jEdit.getProperty("macro-input.title"), 201 JOptionPane.QUESTION_MESSAGE,null,null,defaultValue); 202 } 204 214 public static int confirm(Component comp, String prompt, int buttons) 215 { 216 GUIUtilities.hideSplashScreen(); 217 218 return JOptionPane.showConfirmDialog(comp,prompt, 219 jEdit.getProperty("macro-confirm.title"),buttons, 220 JOptionPane.QUESTION_MESSAGE); 221 } 223 234 public static int confirm(Component comp, String prompt, int buttons, int type) 235 { 236 GUIUtilities.hideSplashScreen(); 237 238 return JOptionPane.showConfirmDialog(comp,prompt, 239 jEdit.getProperty("macro-confirm.title"),buttons,type); 240 } 242 248 public static void loadMacros() 249 { 250 macroActionSet.removeAllActions(); 251 macroHierarchy.removeAllElements(); 252 macroHash.clear(); 253 254 String settings = jEdit.getSettingsDirectory(); 258 259 if(settings != null) 260 { 261 userMacroPath = MiscUtilities.constructPath( 262 settings,"macros"); 263 loadMacros(macroHierarchy,"",new File(userMacroPath)); 264 } 265 266 if(jEdit.getJEditHome() != null) 267 { 268 systemMacroPath = MiscUtilities.constructPath( 269 jEdit.getJEditHome(),"macros"); 270 loadMacros(macroHierarchy,"",new File(systemMacroPath)); 271 } 272 273 EditBus.send(new DynamicMenuChanged("macros")); 274 } 276 281 public static void registerHandler(Handler handler) 282 { 283 if (getHandler(handler.getName()) != null) 284 { 285 Log.log(Log.ERROR, Macros.class, "Cannot register more than one macro handler with the same name"); 286 return; 287 } 288 289 Log.log(Log.DEBUG,Macros.class,"Registered " + handler.getName() 290 + " macro handler"); 291 macroHandlers.add(handler); 292 } 294 299 public static Handler[] getHandlers() 300 { 301 Handler[] handlers = new Handler[macroHandlers.size()]; 302 return (Handler[])macroHandlers.toArray(handlers); 303 } 305 311 public static Handler getHandlerForPathName(String pathName) 312 { 313 for (int i = 0; i < macroHandlers.size(); i++) 314 { 315 Handler handler = (Handler)macroHandlers.get(i); 316 if (handler.accept(pathName)) 317 return handler; 318 } 319 320 return null; 321 } 323 329 public static Handler getHandler(String name) 330 { 331 Handler handler = null; 332 for (int i = 0; i < macroHandlers.size(); i++) 333 { 334 handler = (Handler)macroHandlers.get(i); 335 if (handler.getName().equals(name)) return handler; 336 } 337 338 return null; 339 } 340 342 351 public static Vector getMacroHierarchy() 352 { 353 return macroHierarchy; 354 } 356 361 public static ActionSet getMacroActionSet() 362 { 363 return macroActionSet; 364 } 366 372 public static Macro getMacro(String macro) 373 { 374 return (Macro)macroHash.get(macro); 375 } 377 381 public static Macro getLastMacro() 382 { 383 return lastMacro; 384 } 386 390 public static void setLastMacro(Macro macro) 391 { 392 lastMacro = macro; 393 } 395 400 public static class Macro extends EditAction 401 { 402 public Macro(Handler handler, String name, String label, String path) 404 { 405 super(name); 406 this.handler = handler; 407 this.label = label; 408 this.path = path; 409 } 411 public Handler getHandler() 413 { 414 return handler; 415 } 416 418 public String getPath() 420 { 421 return path; 422 } 424 public void invoke(View view) 426 { 427 setLastMacro(this); 428 429 if(view == null) 430 handler.runMacro(null,this); 431 else 432 { 433 try 434 { 435 view.getBuffer().beginCompoundEdit(); 436 handler.runMacro(view,this); 437 } 438 finally 439 { 440 view.getBuffer().endCompoundEdit(); 441 } 442 } 443 } 445 public String getCode() 447 { 448 return "Macros.getMacro(\"" + getName() + "\").invoke(view);"; 449 } 451 public static String macroNameToLabel(String macroName) 453 { 454 int index = macroName.lastIndexOf('/'); 455 return macroName.substring(index + 1).replace('_', ' '); 456 } 457 459 private Handler handler; 461 private String path; 462 String label; 463 } 466 472 public static void recordTemporaryMacro(View view) 473 { 474 String settings = jEdit.getSettingsDirectory(); 475 476 if(settings == null) 477 { 478 GUIUtilities.error(view,"no-settings",new String [0]); 479 return; 480 } 481 if(view.getMacroRecorder() != null) 482 { 483 GUIUtilities.error(view,"already-recording",new String [0]); 484 return; 485 } 486 487 Buffer buffer = jEdit.openFile(null,settings + File.separator 488 + "macros","Temporary_Macro.bsh",true,null); 489 490 if(buffer == null) 491 return; 492 493 buffer.remove(0,buffer.getLength()); 494 buffer.insert(0,jEdit.getProperty("macro.temp.header")); 495 496 recordMacro(view,buffer,true); 497 } 499 505 public static void recordMacro(View view) 506 { 507 String settings = jEdit.getSettingsDirectory(); 508 509 if(settings == null) 510 { 511 GUIUtilities.error(view,"no-settings",new String [0]); 512 return; 513 } 514 515 if(view.getMacroRecorder() != null) 516 { 517 GUIUtilities.error(view,"already-recording",new String [0]); 518 return; 519 } 520 521 String name = GUIUtilities.input(view,"record",null); 522 if(name == null) 523 return; 524 525 name = name.replace(' ','_'); 526 527 Buffer buffer = jEdit.openFile(null,null, 528 MiscUtilities.constructPath(settings,"macros", 529 name + ".bsh"),true,null); 530 531 if(buffer == null) 532 return; 533 534 buffer.remove(0,buffer.getLength()); 535 buffer.insert(0,jEdit.getProperty("macro.header")); 536 537 recordMacro(view,buffer,false); 538 } 540 546 public static void stopRecording(View view) 547 { 548 Recorder recorder = view.getMacroRecorder(); 549 550 if(recorder == null) 551 GUIUtilities.error(view,"macro-not-recording",null); 552 else 553 { 554 view.setMacroRecorder(null); 555 if(!recorder.temporary) 556 view.setBuffer(recorder.buffer); 557 recorder.dispose(); 558 } 559 } 561 567 public static void runTemporaryMacro(View view) 568 { 569 String settings = jEdit.getSettingsDirectory(); 570 571 if(settings == null) 572 { 573 GUIUtilities.error(view,"no-settings",null); 574 return; 575 } 576 577 String path = MiscUtilities.constructPath( 578 jEdit.getSettingsDirectory(),"macros", 579 "Temporary_Macro.bsh"); 580 581 if(jEdit.getBuffer(path) == null) 582 { 583 GUIUtilities.error(view,"no-temp-macro",null); 584 return; 585 } 586 587 Handler handler = getHandler("beanshell"); 588 Macro temp = handler.createMacro(path,path); 589 590 Buffer buffer = view.getBuffer(); 591 592 try 593 { 594 buffer.beginCompoundEdit(); 595 temp.invoke(view); 596 } 597 finally 598 { 599 601 if(buffer.insideCompoundEdit()) 602 buffer.endCompoundEdit(); 603 } 604 } 606 608 private static String systemMacroPath; 610 private static String userMacroPath; 611 612 private static ArrayList macroHandlers; 613 614 private static ActionSet macroActionSet; 615 private static Vector macroHierarchy; 616 private static Hashtable macroHash; 617 618 private static Macro lastMacro; 619 621 static 623 { 624 macroHandlers = new ArrayList(); 625 registerHandler(new BeanShellHandler()); 626 macroActionSet = new ActionSet(jEdit.getProperty("action-set.macros")); 627 jEdit.addActionSet(macroActionSet); 628 macroHierarchy = new Vector(); 629 macroHash = new Hashtable(); 630 } 632 private static void loadMacros(Vector vector, String path, File directory) 634 { 635 lastMacro = null; 636 637 File[] macroFiles = directory.listFiles(); 638 if(macroFiles == null || macroFiles.length == 0) 639 return; 640 641 for(int i = 0; i < macroFiles.length; i++) 642 { 643 File file = macroFiles[i]; 644 String fileName = file.getName(); 645 if(file.isHidden()) 646 { 647 648 continue; 649 } 650 else if(file.isDirectory()) 651 { 652 String submenuName = fileName.replace('_',' '); 653 Vector submenu = null; 654 for(int j = 0; j < vector.size(); j++) 656 { 657 Object obj = vector.get(j); 658 if(obj instanceof Vector) 659 { 660 Vector vec = (Vector)obj; 661 if(((String )vec.get(0)).equals(submenuName)) 662 { 663 submenu = vec; 664 break; 665 } 666 } 667 } if(submenu == null) 669 { 670 submenu = new Vector(); 671 submenu.addElement(submenuName); 672 vector.addElement(submenu); 673 } 674 675 loadMacros(submenu,path + fileName + '/',file); 676 } 677 else 678 { 679 addMacro(file,path,vector); 680 } 681 } 682 } 684 private static void addMacro(File file, String path, Vector vector) 686 { 687 String fileName = file.getName(); 688 Handler handler = getHandlerForPathName(file.getPath()); 689 690 if(handler == null) 691 return; 692 693 try 694 { 695 String macroName = (path + fileName).replace(' ','_'); 699 Macro newMacro = handler.createMacro(macroName, 700 file.getPath()); 701 if(macroHash.get(newMacro.getName()) != null) 704 return; 705 706 vector.addElement(newMacro.getName()); 707 jEdit.setTemporaryProperty(newMacro.getName() 708 + ".label", 709 newMacro.label); 710 jEdit.setTemporaryProperty(newMacro.getName() 711 + ".mouse-over", 712 handler.getLabel() + " - " + file.getPath()); 713 macroActionSet.addAction(newMacro); 714 macroHash.put(newMacro.getName(),newMacro); 715 } 716 catch (Exception e) 717 { 718 Log.log(Log.ERROR, Macros.class, e); 719 macroHandlers.remove(handler); 720 } 721 } 723 731 private static void recordMacro(View view, Buffer buffer, boolean temporary) 732 { 733 view.setMacroRecorder(new Recorder(view,buffer,temporary)); 734 735 view.getStatus().setMessage(null); 738 } 740 742 746 public static class Recorder implements EBComponent 747 { 748 View view; 749 Buffer buffer; 750 boolean temporary; 751 752 boolean lastWasInput; 753 boolean lastWasOverwrite; 754 int overwriteCount; 755 756 public Recorder(View view, Buffer buffer, boolean temporary) 758 { 759 this.view = view; 760 this.buffer = buffer; 761 this.temporary = temporary; 762 EditBus.addToBus(this); 763 } 765 public void record(String code) 767 { 768 flushInput(); 769 770 append("\n"); 771 append(code); 772 } 774 public void record(int repeat, String code) 776 { 777 if(repeat == 1) 778 record(code); 779 else 780 { 781 record("for(int i = 1; i <= " + repeat + "; i++)\n" 782 + "{\n" 783 + code + "\n" 784 + "}"); 785 } 786 } 788 792 public void recordInput(int repeat, char ch, boolean overwrite) 793 { 794 if(ch == '\n') 797 record(repeat,"textArea.userInput(\'\\n\');"); 798 else if(ch == '\t') 799 record(repeat,"textArea.userInput(\'\\t\');"); 800 else 801 { 802 StringBuffer buf = new StringBuffer (); 803 for(int i = 0; i < repeat; i++) 804 buf.append(ch); 805 recordInput(buf.toString(),overwrite); 806 } 807 } 809 813 public void recordInput(String str, boolean overwrite) 814 { 815 String charStr = MiscUtilities.charsToEscapes(str); 816 817 if(overwrite) 818 { 819 if(lastWasOverwrite) 820 { 821 overwriteCount++; 822 append(charStr); 823 } 824 else 825 { 826 flushInput(); 827 overwriteCount = 1; 828 lastWasOverwrite = true; 829 append("\ntextArea.setSelectedText(\"" + charStr); 830 } 831 } 832 else 833 { 834 if(lastWasInput) 835 append(charStr); 836 else 837 { 838 flushInput(); 839 lastWasInput = true; 840 append("\ntextArea.setSelectedText(\"" + charStr); 841 } 842 } 843 } 845 public void handleMessage(EBMessage msg) 847 { 848 if(msg instanceof BufferUpdate) 849 { 850 BufferUpdate bmsg = (BufferUpdate)msg; 851 if(bmsg.getWhat() == BufferUpdate.CLOSED) 852 { 853 if(bmsg.getBuffer() == buffer) 854 stopRecording(view); 855 } 856 } 857 } 859 private void append(String str) 861 { 862 buffer.insert(buffer.getLength(),str); 863 } 865 private void dispose() 867 { 868 flushInput(); 869 870 for(int i = 0; i < buffer.getLineCount(); i++) 871 { 872 buffer.indentLine(i,true); 873 } 874 875 EditBus.removeFromBus(this); 876 877 view.getStatus().setMessage(null); 880 } 882 887 private void flushInput() 888 { 889 if(lastWasInput) 890 { 891 lastWasInput = false; 892 append("\");"); 893 } 894 895 if(lastWasOverwrite) 896 { 897 lastWasOverwrite = false; 898 append("\");\n"); 899 append("offset = buffer.getLineEndOffset(" 900 + "textArea.getCaretLine()) - 1;\n"); 901 append("buffer.remove(textArea.getCaretPosition()," 902 + "Math.min(" + overwriteCount 903 + ",offset - " 904 + "textArea.getCaretPosition()));"); 905 } 906 } } 909 914 public static abstract class Handler 915 { 916 public String getName() 918 { 919 return name; 920 } 922 public String getLabel() 924 { 925 return label; 926 } 928 public boolean accept(String path) 930 { 931 return filter.matcher(MiscUtilities.getFileName(path)).matches(); 932 } 934 public abstract Macro createMacro(String macroName, String path); 936 938 944 public abstract void runMacro(View view, Macro macro); 945 947 961 public void runMacro(View view, Macro macro, boolean ownNamespace) 962 { 963 runMacro(view,macro); 964 } 966 protected Handler(String name) 968 { 969 this.name = name; 970 label = jEdit.getProperty("macro-handler." 971 + name + ".label", name); 972 try 973 { 974 filter = Pattern.compile(StandardUtilities.globToRE( 975 jEdit.getProperty( 976 "macro-handler." + name + ".glob"))); 977 } 978 catch (Exception e) 979 { 980 throw new InternalError ("Missing or invalid glob for handler " + name); 981 } 982 } 984 private String name; 986 private String label; 987 private Pattern filter; 988 } 991 static class BeanShellHandler extends Handler 993 { 994 BeanShellHandler() 996 { 997 super("beanshell"); 998 } 1000 public Macro createMacro(String macroName, String path) 1002 { 1003 macroName = macroName.substring(0, macroName.length() - 4); 1005 1006 return new Macro(this, macroName, 1007 Macro.macroNameToLabel(macroName), path); 1008 } 1010 public void runMacro(View view, Macro macro) 1012 { 1013 BeanShell.runScript(view,macro.getPath(),null,true); 1014 } 1016 public void runMacro(View view, Macro macro, boolean ownNamespace) 1018 { 1019 BeanShell.runScript(view,macro.getPath(),null,ownNamespace); 1020 } } } 1023 | Popular Tags |