genjava / articles / jedit plugins
// default package
import java.util.Vector;
import org.gjt.sp.jedit.EBPlugin;
import org.gjt.sp.jedit.GUIUtilities;
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.jEdit;
public class FoodPlugin extends EBPlugin {
static public void doFood(View view) {
System.err.println("DO FOOD CALLED");
}
public void start() {
// register my Action
jEdit.addAction( new FoodAction() );
}
// register my menu item in the plugin's menu.
public void createMenuItems(Vector menuItems) {
menuItems.addElement(GUIUtilities.loadMenuItem("Food"));
}
}
Things of note in this class:
We extend the EBPlugin class.
We register an Action.
We add a menu under the name 'Food'
EBPlugin has no abstract methods, so you don't have to implement any. However
the start and createMenuItems methods seem essential if you want to have a
working plugin.
import java.util.Vector;
import org.gjt.sp.jedit.*;
import org.gjt.sp.jedit.io.VFSManager;
import org.gjt.sp.jedit.gui.OptionsDialog;
import org.gjt.sp.util.Log;
public class FoodAction extends EditAction {
public FoodAction() {
super("Food");
}
public void invoke(View view) {
Buffer buffer = view.getBuffer();
String bufferFilename = buffer.getName();
if (!bufferFilename.toLowerCase().endsWith(".java") &&
!buffer.getMode().getName().equals("java"))
{
GUIUtilities.error(view, "food.error.noJavaBuffer", null);
return;
}
// is the current buffer editable?
if (view != null && !view.getTextArea().isEditable()) {
GUIUtilities.error(view, "food.error.isNotEditable", null);
return;
}
VFSManager.runInAWTThread( new FoodDoit(view) );
}
}
Things to note in this class:
We supply an invoke(View) method.
We get a Buffer from it.
We do some checks to see if it's a java source file. If not then we
use some errors.
We fire off a thread called FoodDoit.
FoodDoit is the class that does the actual change. FoodAction could happily
have implemented Runnable and contained the run method. My habits make
me prefer to keep them separate.
import org.gjt.sp.jedit.View;
import org.gjt.sp.jedit.textarea.JEditTextArea;
import org.gjt.sp.util.Log;
public class FoodDoit implements Runnable {
private View view;
public FoodDoit(View view) {
this.view = view;
}
public void run() {
JEditTextArea textArea = view.getTextArea();
textArea.setText( "Foo'd" );
}
}
This class is pretty simple. The only thing of real interest is the
run() method. We get the textarea from the view. Then we set text on it.
Voila, important java document is gone and replaced with a request for
food.
plugin.FoodPlugin.name=GenerationJava Food Example
plugin.FoodPlugin.author=bayard@generationjava.com
plugin.FoodPlugin.version=0.1.1
plugin.FoodPlugin.docs=Food.html
plugin.FoodPlugin.depend.0=jedit 03.01.03.00
food.error.noJavaBuffer.title=JavaStyle
food.error.noJavaBuffer.message=\
This is not a Java buffer.\n\
Make sure the buffer is in Java mode,\n\
or the filename ends with ".java".
food.error.isNotEditable.title=JavaStyle
food.error.isNotEditable.message=\
Cannot reformat the current buffer, because it is not editable.
It's easy to tell the two types apart. The ones beginning with plugin are
for jEdit, the ones with food are for this particular plugin.
The first 4 plugin ones, you can put what you want. The docs property is
the file it will show for help. The others it just shows when discussing
your plugin. The 5th property says what version of jEdit the user needs.
To be honest I've just copied JavaStyle's at the moment.
Then we have the plugin specific properies. You'll recognise these as the
errors which were thrown out in FoodAction. For each error you send to
GUIUtilities.error, you need a title and a message. Note that the backslash
allows you to continue using the next line.
<?xml version="1.0"?>
<!DOCTYPE ACTIONS SYSTEM "actions.dtd">
<ACTIONS>
<ACTION NAME="Food">
<CODE>
FoodPlugin.doFood(view);
</CODE>
</ACTION>
</ACTIONS>