/*
* Macros.java - Macro manager
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 1999, 2004 Slava Pestov
* Portions copyright (C) 2002 mike dillon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit;
//{{{ Imports
import org.gjt.sp.jedit.EditBus.EBHandler;
import org.gjt.sp.jedit.msg.BufferUpdate;
import org.gjt.sp.jedit.msg.DynamicMenuChanged;
import org.gjt.sp.util.Log;
import org.gjt.sp.util.StandardUtilities;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
//}}}
/**
* This class records and runs macros.<p>
*
* It also contains a few methods useful for displaying output messages
* or obtaining input from a macro:
*
* <ul>
* <li>{@link #confirm(Component,String,int)}</li>
* <li>{@link #confirm(Component,String,int,int)}</li>
* <li>{@link #error(Component,String)}</li>
* <li>{@link #input(Component,String)}</li>
* <li>{@link #input(Component,String,String)}</li>
* <li>{@link #message(Component,String)}</li>
* </ul>
*
* Note that plugins should not use the above methods. Call
* the methods in the {@link GUIUtilities} class instead.
*
* @author Slava Pestov
* @version $Id: Macros.java 23221 2013-09-29 20:03:32Z shlomy $
*/
public class Macros
{
//{{{ showRunScriptDialog() method
/**
* Prompts for one or more files to run as macros
* @param view The view
* @since jEdit 4.0pre7
*/
public static void showRunScriptDialog(View view)
{
String[] paths = GUIUtilities.showVFSFileDialog(view,
null,JFileChooser.OPEN_DIALOG,true);
if(paths != null)
{
Buffer buffer = view.getBuffer();
try
{
buffer.beginCompoundEdit();
for (String path : paths)
runScript(view, path, false);
}
finally
{
buffer.endCompoundEdit();
}
}
} //}}}
//{{{ runScript() method
/**
* Runs the specified script.
* Unlike the {@link BeanShell#runScript(View,String,Reader,boolean)}
* method, this method can run scripts supported
* by any registered macro handler.
* @param view The view
* @param path The VFS path of the script
* @param ignoreUnknown If true, then unknown file types will be
* ignored; otherwise, a warning message will be printed and they will
* be evaluated as BeanShell scripts.
*
* @since jEdit 4.1pre2
*/
public static void runScript(View view, String path, boolean ignoreUnknown)
{
Handler handler = getHandlerForPathName(path);
if(handler != null)
{
try
{
Macro newMacro = handler.createMacro(
MiscUtilities.getFileName(path), path);
newMacro.invoke(view);
}
catch (Exception e)
{
Log.log(Log.ERROR, Macros.class, e);
return;
}
return;
}
// only executed if above loop falls
// through, ie there is no handler for
// this file
if(ignoreUnknown)
{
Log.log(Log.NOTICE,Macros.class,path +
": Cannot find a suitable macro handler");
}
else
{
Log.log(Log.ERROR,Macros.class,path +
": Cannot find a suitable macro handler, "
+ "assuming BeanShell");
getHandler("beanshell").createMacro(
path,path).invoke(view);
}
} //}}}
//{{{ message() method
/**
* Utility method that can be used to display a message dialog in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param message The message
* @since jEdit 2.7pre2
*/
public static void message(final Component comp, final String message)
{
if (EventQueue.isDispatchThread())
{
GUIUtilities.hideSplashScreen();
JOptionPane.showMessageDialog(comp,message,
jEdit.getProperty("macro-message.title"),
JOptionPane.INFORMATION_MESSAGE);
}
else
{
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
message(comp, message);
}
});
}
catch (Exception e)
{
// ignored
}
}
} //}}}
//{{{ error() method
/**
* Utility method that can be used to display an error dialog in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param message The message
* @since jEdit 2.7pre2
*/
public static void error(final Component comp, final String message)
{
if (EventQueue.isDispatchThread())
{
GUIUtilities.hideSplashScreen();
JOptionPane.showMessageDialog(comp,message,
jEdit.getProperty("macro-message.title"),
JOptionPane.ERROR_MESSAGE);
}
else
{
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
message(comp, message);
}
});
}
catch (Exception e)
{
// ignored
}
}
} //}}}
//{{{ input() method
/**
* Utility method that can be used to prompt for input in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param prompt The prompt string
* @since jEdit 2.7pre2
*/
public static String input(Component comp, String prompt)
{
GUIUtilities.hideSplashScreen();
return input(comp,prompt,null);
} //}}}
//{{{ input() method
/**
* Utility method that can be used to prompt for input in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param prompt The prompt string
* @since jEdit 3.1final
*/
public static String input(final Component comp, final String prompt, final String defaultValue)
{
if (EventQueue.isDispatchThread())
{
GUIUtilities.hideSplashScreen();
return (String)JOptionPane.showInputDialog(comp,prompt,
jEdit.getProperty("macro-input.title"),
JOptionPane.QUESTION_MESSAGE,null,null,defaultValue);
}
final String[] retValue = new String[1];
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
retValue[0] = input(comp, prompt, defaultValue);
}
});
}
catch (Exception e)
{
return null;
}
return retValue[0];
} //}}}
//{{{ confirm() method
/**
* Utility method that can be used to ask for confirmation in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param prompt The prompt string
* @param buttons The buttons to display - for example,
* JOptionPane.YES_NO_CANCEL_OPTION
* @since jEdit 4.0pre2
*/
public static int confirm(final Component comp, final String prompt, final int buttons)
{
if (EventQueue.isDispatchThread())
{
GUIUtilities.hideSplashScreen();
return JOptionPane.showConfirmDialog(comp,prompt,
jEdit.getProperty("macro-confirm.title"),buttons,
JOptionPane.QUESTION_MESSAGE);
}
final int [] retValue = new int[1];
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
retValue[0] = confirm(comp, prompt, buttons);
}
});
}
catch (Exception e)
{
return JOptionPane.CANCEL_OPTION;
}
return retValue[0];
} //}}}
//{{{ confirm() method
/**
* Utility method that can be used to ask for confirmation in a macro.
* @param comp The component to show the dialog on behalf of, this
* will usually be a view instance
* @param prompt The prompt string
* @param buttons The buttons to display - for example,
* JOptionPane.YES_NO_CANCEL_OPTION
* @param type The dialog type - for example,
* JOptionPane.WARNING_MESSAGE
*/
public static int confirm(final Component comp, final String prompt, final int buttons, final int type)
{
if (EventQueue.isDispatchThread())
{
GUIUtilities.hideSplashScreen();
return JOptionPane.showConfirmDialog(comp,prompt,
jEdit.getProperty("macro-confirm.title"),buttons,type);
}
final int [] retValue = new int[1];
try
{
EventQueue.invokeAndWait(new Runnable()
{
@Override
public void run()
{
retValue[0] = confirm(comp, prompt, buttons, type);
}
});
}
catch (Exception e)
{
return JOptionPane.CANCEL_OPTION;
}
return retValue[0];
} //}}}
//{{{ loadMacros() method
/**
* Rebuilds the macros list, and sends a MacrosChanged message
* (views update their Macros menu upon receiving it)
* @since jEdit 2.2pre4
*/
public static void loadMacros()
{
jEdit.removeActionSet(macroActionSet);
macroActionSet.removeAllActions();
macroHierarchy.removeAllElements();
macroHash.clear();
// since subsequent macros with the same name are ignored,
// load user macros first so that they override the system
// macros.
String settings = jEdit.getSettingsDirectory();
if(settings != null)
{
userMacroPath = MiscUtilities.constructPath(
settings,"macros");
loadMacros(macroHierarchy,"",new File(userMacroPath));
}
if(jEdit.getJEditHome() != null)
{
systemMacroPath = MiscUtilities.constructPath(
jEdit.getJEditHome(),"macros");
loadMacros(macroHierarchy,"",new File(systemMacroPath));
}
jEdit.addActionSet(macroActionSet);
EditBus.send(new DynamicMenuChanged("macros"));
} //}}}
//{{{ registerHandler() method
/**
* Adds a macro handler to the handlers list
* @since jEdit 4.0pre6
*/
public static void registerHandler(Handler handler)
{
if (getHandler(handler.getName()) != null)
{
Log.log(Log.ERROR, Macros.class, "Cannot register more than one macro handler with the same name");
return;
}
Log.log(Log.DEBUG,Macros.class,"Registered " + handler.getName()
+ " macro handler");
macroHandlers.add(handler);
} //}}}
//{{{ unregisterHandler() method
/**
* Removes a macro handler from the handlers list
* @since jEdit 4.4.1
*/
public static void unregisterHandler(Handler handler)
{
if (macroHandlers.remove(handler))
{
Log.log(Log.DEBUG, Macros.class, "Unregistered " + handler.getName()
+ " macro handler");
}
else
{
Log.log(Log.ERROR, Macros.class, "Cannot unregister " + handler.getName()
+ " macro handler - it is not registered.");
}
} //}}}
//{{{ getHandlers() method
/**
* Returns an array containing the list of registered macro handlers
* @since jEdit 4.0pre6
*/
public static Handler[] getHandlers()
{
Handler[] handlers = new Handler[macroHandlers.size()];
return macroHandlers.toArray(handlers);
} //}}}
//{{{ getHandlerForFileName() method
/**
* Returns the macro handler suitable for running the specified file
* name, or null if there is no suitable handler.
* @since jEdit 4.1pre3
*/
public static Handler getHandlerForPathName(String pathName)
{
for (Handler handler : macroHandlers)
{
if (handler.accept(pathName))
return handler;
}
return null;
} //}}}
//{{{ getHandler() method
/**
* Returns the macro handler with the specified name, or null if
* there is no registered handler with that name.
* @since jEdit 4.0pre6
*/
public static Handler getHandler(String name)
{
for (Handler handler : macroHandlers)
{
if (handler.getName().equals(name))
return handler;
}
return null;
}
//}}}
//{{{ getMacroHierarchy() method
/**
* Returns a vector hierarchy with all known macros in it.
* Each element of this vector is either a macro name string,
* or another vector. If it is a vector, the first element is a
* string label, the rest are again, either macro name strings
* or vectors.
* @since jEdit 2.6pre1
*/
public static Vector getMacroHierarchy()
{
return macroHierarchy;
} //}}}
//{{{ getMacroActionSet() method
/**
* Returns an action set with all known macros in it.
* @since jEdit 4.0pre1
*/
public static ActionSet getMacroActionSet()
{
return macroActionSet;
} //}}}
//{{{ getMacro() method
/**
* Returns the macro with the specified name.
* @param macro The macro's name
* @since jEdit 2.6pre1
*/
public static Macro getMacro(String macro)
{
return macroHash.get(macro);
} //}}}
//{{{ getLastMacro() method
/**
* @since jEdit 4.3pre1
*/
public static Macro getLastMacro()
{
return lastMacro;
} //}}}
//{{{ setLastMacro() method
/**
* @since jEdit 4.3pre1
*/
public static void setLastMacro(Macro macro)
{
lastMacro = macro;
} //}}}
//{{{ Macro class
/**
* Encapsulates the macro's label, name and path.
* @since jEdit 2.2pre4
*/
public static class Macro extends EditAction
{
//{{{ Macro constructor
public Macro(Handler handler, String name, String label, String path)
{
super(name);
this.handler = handler;
this.label = label;
this.path = path;
} //}}}
//{{{ getHandler() method
public Handler getHandler()
{
return handler;
}
//}}}
//{{{ getPath() method
public String getPath()
{
return path;
} //}}}
//{{{ invoke() method
@Override
public void invoke(View view)
{
setLastMacro(this);
if(view == null)
handler.runMacro(null,this);
else
{
try
{
view.getBuffer().beginCompoundEdit();
handler.runMacro(view,this);
}
finally
{
view.getBuffer().endCompoundEdit();
}
}
} //}}}
//{{{ getCode() method
@Override
public String getCode()
{
return "Macros.getMacro(\"" + getName() + "\").invoke(view);";
} //}}}
//{{{ macroNameToLabel() method
public static String macroNameToLabel(String macroName)
{
int index = macroName.lastIndexOf('/');
return macroName.substring(index + 1).replace('_', ' ');
}
//}}}
//{{{ Private members
private Handler handler;
private String path;
String label;
//}}}
} //}}}
//{{{ recordTemporaryMacro() method
/**
* Starts recording a temporary macro.
* @param view The view
* @since jEdit 2.7pre2
*/
public static void recordTemporaryMacro(View view)
{
String settings = jEdit.getSettingsDirectory();
if(settings == null)
{
GUIUtilities.error(view,"no-settings",new String[0]);
return;
}
if(view.getMacroRecorder() != null)
{
GUIUtilities.error(view,"already-recording",new String[0]);
return;
}
Buffer buffer = jEdit.openFile((View)null,settings + File.separator
+ "macros","Temporary_Macro.bsh",true,null);
if(buffer == null)
return;
buffer.remove(0,buffer.getLength());
buffer.insert(0,jEdit.getProperty("macro.temp.header"));
recordMacro(view,buffer,true);
} //}}}
//{{{ recordMacro() method
/**
* Starts recording a macro.
* @param view The view
* @since jEdit 2.7pre2
*/
public static void recordMacro(View view)
{
String settings = jEdit.getSettingsDirectory();
if(settings == null)
{
GUIUtilities.error(view,"no-settings",new String[0]);
return;
}
if(view.getMacroRecorder() != null)
{
GUIUtilities.error(view,"already-recording",new String[0]);
return;
}
String name = GUIUtilities.input(view,"record",null);
if(name == null)
return;
name = name.replace(' ','_');
Buffer buffer = jEdit.openFile((View) null,null,
MiscUtilities.constructPath(settings,"macros",
name + ".bsh"),true,null);
if(buffer == null)
return;
buffer.remove(0,buffer.getLength());
buffer.insert(0,jEdit.getProperty("macro.header"));
recordMacro(view,buffer,false);
} //}}}
//{{{ stopRecording() method
/**
* Stops a recording currently in progress.
* @param view The view
* @since jEdit 2.7pre2
*/
public static void stopRecording(View view)
{
Recorder recorder = view.getMacroRecorder();
if(recorder == null)
GUIUtilities.error(view,"macro-not-recording",null);
else
{
view.setMacroRecorder(null);
if(!recorder.temporary)
view.setBuffer(recorder.buffer);
recorder.dispose();
}
} //}}}
//{{{ runTemporaryMacro() method
/**
* Runs the temporary macro.
* @param view The view
* @since jEdit 2.7pre2
*/
public static void runTemporaryMacro(View view)
{
String settings = jEdit.getSettingsDirectory();
if(settings == null)
{
GUIUtilities.error(view,"no-settings",null);
return;
}
String path = MiscUtilities.constructPath(
jEdit.getSettingsDirectory(),"macros",
"Temporary_Macro.bsh");
if(jEdit.getBuffer(path) == null)
{
GUIUtilities.error(view,"no-temp-macro",null);
return;
}
Handler handler = getHandler("beanshell");
Macro temp = handler.createMacro(path,path);
Buffer buffer = view.getBuffer();
try
{
buffer.beginCompoundEdit();
temp.invoke(view);
}
finally
{
/* I already wrote a comment expaining this in
* Macro.invoke(). */
if(buffer.insideCompoundEdit())
buffer.endCompoundEdit();
}
} //}}}
//{{{ Private members
//{{{ Static variables
private static String systemMacroPath;
private static String userMacroPath;
private static List<Handler> macroHandlers;
private static ActionSet macroActionSet;
private static Vector macroHierarchy;
private static Map<String, Macro> macroHash;
private static Macro lastMacro;
//}}}
//{{{ Class initializer
static
{
macroHandlers = new ArrayList<Handler>();
registerHandler(new BeanShellHandler());
macroActionSet = new ActionSet(jEdit.getProperty("action-set.macros"));
jEdit.addActionSet(macroActionSet);
macroHierarchy = new Vector();
macroHash = new Hashtable<String, Macro>();
} //}}}
//{{{ loadMacros() method
private static void loadMacros(List vector, String path, File directory)
{
lastMacro = null;
File[] macroFiles = directory.listFiles();
if(macroFiles == null || macroFiles.length == 0)
return;
for (File file : macroFiles)
{
String fileName = file.getName();
if (file.isHidden())
{
/* do nothing! */
}
else if (file.isDirectory())
{
String submenuName = fileName.replace('_', ' ');
List submenu = null;
//{{{ try to merge with an existing menu first
for (Object obj : vector)
{
if (obj instanceof List)
{
List vec = (List) obj;
if (submenuName.equals(vec.get(0)))
{
submenu = vec;
break;
}
}
} //}}}
if (submenu == null)
{
submenu = new Vector();
submenu.add(submenuName);
vector.add(submenu);
}
loadMacros(submenu, path + fileName + '/', file);
} else
{
addMacro(file, path, vector);
}
}
} //}}}
//{{{ addMacro() method
private static void addMacro(File file, String path, List vector)
{
String fileName = file.getName();
Handler handler = getHandlerForPathName(file.getPath());
if(handler == null)
return;
try
{
// in case macro file name has a space in it.
// spaces break the view.toolBar property, for instance,
// since it uses spaces to delimit action names.
String macroName = (path + fileName).replace(' ','_');
Macro newMacro = handler.createMacro(macroName,
file.getPath());
// ignore if already added.
// see comment in loadMacros().
if(macroHash.get(newMacro.getName()) != null)
return;
vector.add(newMacro.getName());
jEdit.setTemporaryProperty(newMacro.getName()
+ ".label",
newMacro.label);
jEdit.setTemporaryProperty(newMacro.getName()
+ ".mouse-over",
handler.getLabel() + " - " + file.getPath());
macroActionSet.addAction(newMacro);
macroHash.put(newMacro.getName(),newMacro);
}
catch (Exception e)
{
Log.log(Log.ERROR, Macros.class, e);
macroHandlers.remove(handler);
}
} //}}}
//{{{ recordMacro() method
/**
* Starts recording a macro.
* @param view The view
* @param buffer The buffer to record to
* @param temporary True if this is a temporary macro
* @since jEdit 3.0pre5
*/
private static void recordMacro(View view, Buffer buffer, boolean temporary)
{
view.setMacroRecorder(new Recorder(view,buffer,temporary));
// setting the message to 'null' causes the status bar to check
// if a recording is in progress
view.getStatus().setMessage(null);
} //}}}
//}}}
//{{{ Recorder class
/**
* Handles macro recording.
*/
public static class Recorder
{
View view;
Buffer buffer;
boolean temporary;
boolean lastWasInput;
boolean lastWasOverwrite;
int overwriteCount;
//{{{ Recorder constructor
public Recorder(View view, Buffer buffer, boolean temporary)
{
this.view = view;
this.buffer = buffer;
this.temporary = temporary;
EditBus.addToBus(this);
} //}}}
//{{{ record() method
public void record(String code)
{
if (BeanShell.isScriptRunning())
return;
flushInput();
append("\n");
append(code);
} //}}}
//{{{ record() method
public void record(int repeat, String code)
{
if(repeat == 1)
record(code);
else
{
record("for(int i = 1; i <= " + repeat + "; i++)\n"
+ "{\n"
+ code + '\n'
+ '}');
}
} //}}}
//{{{ recordInput() method
/**
* @since jEdit 4.2pre5
*/
public void recordInput(int repeat, char ch, boolean overwrite)
{
// record \n and \t on lines specially so that auto indent
// can take place
if(ch == '\n')
record(repeat,"textArea.userInput(\'\\n\');");
else if(ch == '\t')
record(repeat,"textArea.userInput(\'\\t\');");
else
{
StringBuilder buf = new StringBuilder(repeat);
for(int i = 0; i < repeat; i++)
buf.append(ch);
recordInput(buf.toString(),overwrite);
}
} //}}}
//{{{ recordInput() method
/**
* @since jEdit 4.2pre5
*/
public void recordInput(String str, boolean overwrite)
{
String charStr = StandardUtilities.charsToEscapes(str);
if(overwrite)
{
if(lastWasOverwrite)
{
overwriteCount++;
append(charStr);
}
else
{
flushInput();
overwriteCount = 1;
lastWasOverwrite = true;
append("\ntextArea.setSelectedText(\"" + charStr);
}
}
else
{
if(lastWasInput)
append(charStr);
else
{
flushInput();
lastWasInput = true;
append("\ntextArea.setSelectedText(\"" + charStr);
}
}
} //}}}
//{{{ handleBufferUpdate() method
@EBHandler
public void handleBufferUpdate(BufferUpdate bmsg)
{
if(bmsg.getWhat() == BufferUpdate.CLOSED)
{
if(bmsg.getBuffer() == buffer)
stopRecording(view);
}
} //}}}
//{{{ append() method
private void append(String str)
{
buffer.insert(buffer.getLength(),str);
} //}}}
//{{{ dispose() method
private void dispose()
{
flushInput();
for(int i = 0; i < buffer.getLineCount(); i++)
{
buffer.indentLine(i,true);
}
EditBus.removeFromBus(this);
// setting the message to 'null' causes the status bar to
// check if a recording is in progress
view.getStatus().setMessage(null);
} //}}}
//{{{ flushInput() method
/**
* We try to merge consecutive inputs. This helper method is
* called when something other than input is to be recorded.
*/
private void flushInput()
{
if(lastWasInput)
{
lastWasInput = false;
append("\");");
}
if(lastWasOverwrite)
{
lastWasOverwrite = false;
append("\");\n");
append("offset = buffer.getLineEndOffset("
+ "textArea.getCaretLine()) - 1;\n");
append("buffer.remove(textArea.getCaretPosition(),"
+ "Math.min(" + overwriteCount
+ ",offset - "
+ "textArea.getCaretPosition()));");
}
} //}}}
} //}}}
//{{{ Handler class
/**
* Encapsulates creating and invoking macros in arbitrary scripting languages
* @since jEdit 4.0pre6
*/
public abstract static class Handler
{
//{{{ getName() method
public String getName()
{
return name;
} //}}}
//{{{ getLabel() method
public String getLabel()
{
return label;
} //}}}
//{{{ accept() method
public boolean accept(String path)
{
return filter.matcher(MiscUtilities.getFileName(path)).matches();
} //}}}
//{{{ createMacro() method
public abstract Macro createMacro(String macroName, String path);
//}}}
//{{{ runMacro() method
/**
* Runs the specified macro.
* @param view The view - may be null.
* @param macro The macro.
*/
public abstract void runMacro(View view, Macro macro);
//}}}
//{{{ runMacro() method
/**
* Runs the specified macro. This method is optional; it is
* called if the specified macro is a startup script. The
* default behavior is to simply call {@link #runMacro(View,Macros.Macro)}.
*
* @param view The view - may be null.
* @param macro The macro.
* @param ownNamespace A hint indicating whenever functions and
* variables defined in the script are to be self-contained, or
* made available to other scripts. The macro handler may ignore
* this parameter.
* @since jEdit 4.1pre3
*/
public void runMacro(View view, Macro macro, boolean ownNamespace)
{
runMacro(view,macro);
} //}}}
//{{{ Handler constructor
protected Handler(String name)
{
this.name = name;
label = jEdit.getProperty("macro-handler."
+ name + ".label", name);
try
{
filter = Pattern.compile(StandardUtilities.globToRE(
jEdit.getProperty(
"macro-handler." + name + ".glob")));
}
catch (Exception e)
{
throw new InternalError("Missing or invalid glob for handler " + name);
}
} //}}}
//{{{ Private members
private String name;
private String label;
private Pattern filter;
//}}}
} //}}}
//{{{ BeanShellHandler class
private static class BeanShellHandler extends Handler
{
//{{{ BeanShellHandler constructor
BeanShellHandler()
{
super("beanshell");
} //}}}
//{{{ createMacro() method
@Override
public Macro createMacro(String macroName, String path)
{
// Remove '.bsh'
macroName = macroName.substring(0, macroName.length() - 4);
return new Macro(this, macroName,
Macro.macroNameToLabel(macroName), path);
} //}}}
//{{{ runMacro() method
@Override
public void runMacro(View view, Macro macro)
{
BeanShell.runScript(view,macro.getPath(),null,true);
} //}}}
//{{{ runMacro() method
@Override
public void runMacro(View view, Macro macro, boolean ownNamespace)
{
BeanShell.runScript(view,macro.getPath(),null,ownNamespace);
} //}}}
} //}}}
}