PageRenderTime 82ms CodeModel.GetById 61ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms


XML | 614 lines | 528 code | 74 blank | 12 comment | 0 complexity | b5269877bc4edc5b18db98cd41f03cc1 MD5 | raw file
  1<!-- jEdit 3.2 Macro Guide, (C) 2001 John Gellene -->
  3<!-- jEdit buffer-local properties: -->
  4<!-- :indentSize=1:noTabs=yes:maxLineLen=72:tabSize=2: -->
  6<!-- Tue Jun 19 18:36:20 EDT 2001 @983 /Internet Time/ -->
  8<!-- This file covers the chapter "A few simple macros",        -->
  9<!-- which introduces BeanShell through a "Hello world" script. -->
 10<!-- It provides a little background on Java syntax and         -->
 11<!-- class structure.  A few simple methods and macros are also -->
 12<!-- discussed.                                                 -->
 14<chapter id="simple-macros"><title>A Few Simple Macros</title>
 16 <sect1 id="first-example"><title>The Mandatory First Example</title>
 17  <informalexample><!-- <title>A first one-line macro</title> -->
 18   <programlisting>Macros.message(view, "Hello world!");</programlisting>
 19  </informalexample>
 20  <para>
 21   Running this one line script causes jEdit to display a message
 22   box (more precisely, a <classname>JOptionPane</classname> object) with
 23   the traditional beginner's message and an <guilabel>OK</guilabel> button.
 24   Let's see what is happening here.
 25  </para>
 26  <para>
 27   This statement calls a static method (or function) named
 28   <function>message</function> in jEdit's <classname>Macros</classname>
 29   class. If you don't know anything about classes or static methods or
 30   Java (or C++, which employs the same concept), you will need to gain
 31   some understanding of a few terms. Obviously this is not the place for
 32   academic precision, but if you are entirely new to object-oriented
 33   programming, here are a few skeleton ideas to help you with BeanShell.
 34  </para>
 35  <itemizedlist>
 36   <listitem>
 37    <para>
 38     An <glossterm>object</glossterm> is a collection of data that can be
 39     initialized, accessed and manipulated in certain defined ways.
 40    </para>
 41   </listitem>
 43   <listitem>
 44    <para>
 45     A <glossterm>class</glossterm> is a specification of what data an object
 46     contains and what methods can be used to work with the data. A Java
 47     application consists of one or more classes (in the case of jEdit over
 48     200 classes) written by the programmer that defines the application's
 49     behavior. A BeanShell macro uses these classes, along with built-in
 50     classes that are supplied with the Java platform, to define its own
 51     behavior.
 52    </para>
 53   </listitem>
 55   <listitem>
 56    <para>
 57     A <glossterm>subclass</glossterm> (or child class) is a class which
 58     uses (or <quote>inherits</quote>) the data and methods of its parent
 59     class along with additions or modifications that alter the subclass's
 60     behavior.  Classes are typically organized in hierarchies of parent
 61     and child classes to organize program code, to define common
 62     behavior in shared parent class code, and to specify the types of
 63     similar behavior that child classes will perform in their own specific ways.
 64    </para>
 65   </listitem>
 67   <listitem>
 68    <para>
 69     A <glossterm>method</glossterm> (or function) is a procedure that works
 70     with data in a particular object, other data (including other objects)
 71     supplied as <glossterm>parameters</glossterm>, or both. Methods
 72     typically are applied to a particular object which is an
 73     <glossterm>instance</glossterm> of the class to which the method
 74     belongs.
 75    </para>
 76   </listitem>
 78   <listitem>
 79    <para>
 80     A <glossterm>static method</glossterm> differs from other methods
 81     in that it does not deal with the data in a particular object but is
 82     included within a class for the sake of convenience.
 83    </para>
 84   </listitem>
 86  </itemizedlist>
 88  <para>
 89   Java has a rich set of classes defined as part of the Java platform.
 90   Like all Java applications, jEdit is organized as a set of classes that
 91   are themselves derived from the Java platform's classes. We will refer
 92   to <firstterm>Java classes</firstterm> and <firstterm>jEdit
 93   classes</firstterm> to make this distinction. Some of jEdit's classes
 94   (such as those dealing with regular expressions and XML) are derived
 95   from or make use of classes in other open-source Java packages. Except
 96   for BeanShell itself, we won't be discussing them in this guide.
 97  </para>
 99  <para>
100   In our one line script, the static method
101   <function>Macros.message()</function> has two parameters because that is
102   the way the method is defined in the <classname>Macros</classname>
103   class. You must specify both parameters when you call the function. The
104   first parameter, <parameter>view</parameter>, is a a variable naming a
105   <classname>View</classname> object - an instance of jEdit's
106   <classname>View</classname> class. A <classname>View</classname>
107   represents a <quote>parent</quote> or top-level frame window that
108   contains the various visible components of the program, including the
109   text area, menu bar, toolbar, and any docked windows. It is a
110   subclass of Java's <classname>JFrame</classname> class.
111   With jEdit, you can create and display multiple views simultaneously.
112   The variable <varname>view</varname> is predefined for purposes of
113   BeanShell as the current, active <classname>View</classname> object.
114   This is in fact the variable you want to specify as the first parameter.
115   Normally you would not want to associate a message box with anything
116   other than the current <classname>View</classname>.
117  </para>
119  <para>
120   The second parameter, which appears to be quoted text, is a
121   <glossterm>string literal</glossterm> - a sequence of characters of
122   fixed length and content. Behind the scenes, BeanShell and Java take
123   this string literal and use it to create a <classname>String</classname>
124   object. Normally, if you want to create an object in Java or BeanShell,
125   you must construct the object using the <function>new</function> keyword
126   and a <firstterm>constructor</firstterm> method that is part of the
127   object's class. We'll show an example of that later. However, both Java
128   and BeanShell let you use a string literal anytime a method's parameter
129   calls for a <classname>String</classname>.
130  </para>
132  <para>
133   If you are a Java programmer, you might wonder about a few things
134   missing from this one line program. There is no class definition, for
135   example. You can think of a BeanShell script as an implicit definition
136   of a <function>main()</function> method in an anonymous class. That is
137   in fact how BeanShell is implemented; the class is derived from
138   a BeanShell class called <classname>XThis</classname>. If you
139   don't find that helpful, just think of a script as one or more blocks of
140   procedural statements conforming to Java syntax rules. You will also get
141   along fine (for the most part) with C or C++ syntax if you leave out
142   anything to do with pointers or memory management - Java and BeanShell
143   do not have pointers and deal with memory management automatically.
144  </para>
146  <para>
147    Another missing item from a Java perspective is a
148    <function>package</function> statement. In Java, such a statement is
149    used to bundle together a number of files so that their classes become
150    visible to one another. Packages are not part of BeanShell,
151    and you don't need to know anything about them to write
152    BeanShell macros.
153  </para>
155  <para>
156    Finally, there are no <function>import</function> statements in this
157    script. In Java, an <function>import</function> statement makes public
158    classes from other packages visible within the file in which the
159    statement occurs without having to specify a fully
160    qualified class name. Without an import statement or a fully qualified
161    name, Java cannot identify most classes using a single name as an identifier.
162  </para>
164  <para>
165   jEdit automatically imports a number of commonly-used packages into the
166   namespace of every BeanShell script. Because of this, the script output
167   of a recorded macro does not contain <function>import</function>
168   statements. For the same reason, most BeanShell scripts you write will
169   not require <function>import</function> statements.
170  </para>
172  <para>
173    Java requires <literal>import</literal> statement at the beginning of a
174    source file. BeanShell allows you to place <literal>import</literal>
175    statements anywhere in a script, including inside of block of
176    statements. The <literal>import</literal> statement will cover all names
177    used following the statement in the enclosing block.
178  </para>
180  <para>
181    If you try to use a class that is not imported without its
182    fully-qualified name, the BeanShell interpreter will complain with an
183    error message relating to the offending line of code.
184  </para>
186  <sidebar>
187   <para>
188    Here is the full list of packages automatically imported by jEdit:
189   </para>
190   <programlisting>java.awt
209  </sidebar>
210 </sect1>
212 <sect1 id="helpful-methods"><title>Helpful Methods in the
213  Macros Class</title>
215  <para>
216   Including <function>message()</function>, there are five static methods
217   in the <classname>Macros</classname> class that allow you to converse
218   easily with your macros. They all encapsulate calls to methods of the
219   Java platform's <classname>JOptionPane</classname> class.
220  </para>
222  <itemizedlist>
224    <listitem>
225      <funcsynopsis>
226         <funcprototype>
227           <funcdef>public static void <function>message</function></funcdef>
228           <paramdef>Component <parameter>comp</parameter></paramdef>
229           <paramdef>String <parameter>message</parameter></paramdef>
230         </funcprototype>
231       </funcsynopsis>
232     </listitem>
234     <listitem>
235       <funcsynopsis>
236         <funcprototype>
237          <funcdef>public static void <function>error</function></funcdef>
238          <paramdef>Component <parameter>comp</parameter></paramdef>
239          <paramdef>String <parameter>message</parameter></paramdef>
240         </funcprototype>
241       </funcsynopsis>
242     </listitem>
244     <listitem>
245      <funcsynopsis>
246        <funcprototype>
247          <funcdef>public static String <function>input</function></funcdef>
248          <paramdef>Component <parameter>comp</parameter></paramdef>
249          <paramdef>String <parameter>prompt</parameter></paramdef>
250        </funcprototype>
251      </funcsynopsis>
252     </listitem>
254     <listitem>
255      <funcsynopsis>
256        <funcprototype>
257          <funcdef>public static String <function>input</function></funcdef>
258          <paramdef>Component <parameter>comp</parameter></paramdef>
259          <paramdef>String <parameter>prompt</parameter></paramdef>
260          <paramdef>String <parameter>defaultValue</parameter></paramdef>
261        </funcprototype>
262      </funcsynopsis>
263     </listitem>
265     <listitem>
266      <funcsynopsis>
267        <funcprototype>
268          <funcdef>public static String <function>confirm</function></funcdef>
269          <paramdef>Component <parameter>comp</parameter></paramdef>
270          <paramdef>String <parameter>prompt</parameter></paramdef>
271          <paramdef>int <parameter>buttons</parameter></paramdef>
272        </funcprototype>
273      </funcsynopsis>
274     </listitem>
276  </itemizedlist>
278  <para>
279    The format of these four <glossterm>declarations</glossterm> provides a
280    concise reference to the way in which the methods may be used. The
281    keyword <function>public</function> means that the method can be used
282    outside the <classname>Macros</classname> class. The alternatives are
283    <function>private</function> and <function>protected</function>. For
284    purposes of BeanShell, you just have to know that BeanShell can only use
285    public methods of other Java classes. The keyword
286    <function>static</function> we have already discussed. It means that the
287    method does not operate on a particular object. You call a static
288    function using the name of the class (like
289    <classname>Macros</classname>) rather than the name of a particular
290    object (like <varname>view</varname>). The third word is the type of the
291    value returned by the method. The keyword <function>void</function> is
292    Java's way of saying the the method does not have a return value.
293  </para>
295  <para>
296   The <function>error()</function> method works just like
297   <function>message()</function> but displays an error icon in the message
298   box. The <function>input()</function> method furnishes a text field for
299   input, an <guilabel>OK</guilabel> button and a
300   <guilabel>Cancel</guilabel> button. If <quote>Cancel</quote> is pressed,
301   the method returns <constant>null</constant>. If <guilabel>OK</guilabel>
302   is pressed, a <classname>String</classname> containing the contents of
303   the text field is returned. Note that there are two forms of the
304   <function>input()</function> method; the first form with two parameters
305   displays an empty input field, the other lets you specify an initial
306   default value.
307  </para>
309  <para>
310   The <function>confirm()</function> method is the trickiest. The
311   <varname>buttons</varname> parameter should either be
312   <constant>JOptionPane.YES_NO_OPTION</constant> or
313   <constant>JOptionPane.YES_NO_CANCEL_OPTION</constant>. The return
314   value of the method is either
315   <constant>JOptionPane.YES_OPTION</constant>,
316   <constant>JOptionPane.NO_OPTION</constant> or
317   <constant>JOptionPane.CANCEL_OPTION</constant>
318  </para>
320  <para>
321   For those without Java experience, it is important to know that
322   <constant>null</constant> is <emphasis>not</emphasis> the same as an
323   empty, <quote>zero-length</quote> <classname>String</classname>. It is
324   Java's way of saying that there is no object associated with this
325   variable. Whenever you seek to use a return value from
326   <function>input()</function> in your macro, you should test it to see if
327   it is <constant>null</constant>. In most cases, you will
328   want to exit gracefully from the script with a
329   <function>return</function> statement, because the presence of a null
330   value for an input variable usually means that the user intended to
331   cancel macro execution. BeanShell will complain if you call any
332   methods on a <constant>null</constant> object.
333  </para>
335  <para>
336   We've looked at using <function>Macros.message()</function>. To
337   use the other methods, you would write something like the
338   following:
339  </para>
341  <informalexample><!-- <title>Using <function>Macros.error()</function> and
342  <function>Macros.input()</function></title> -->
343   <programlisting>Macros.error(view, "Goodbye, cruel world!");
345String result = Macros.input(view, "Type something here.");
347String result = Macros.input(view, "What is your name?",
348    "John Gellene");</programlisting>
349  </informalexample>
351  <para>
352    In the last two examples, placing the word <classname>String</classname>
353    before the variable name <varname>result</varname> tells BeanShell that
354    the variable refers to a <classname>String</classname> object, even
355    before a particular <classname>String</classname> object is assigned to
356    it. In BeanShell, this <glossterm>declaration</glossterm> of the
357    <glossterm>type</glossterm> of <varname>result</varname> is not
358    necessary; BeanShell can figure it out when the macro runs. This can be
359    helpful if you are not comfortable with types and classes; just use your
360    variables and let BeanShell worry about it.
361  </para>
363  <para>
364    Without an explicit <glossterm>type declaration</glossterm> like
365    <classname>String</classname> <varname>result</varname>, BeanShell
366    variables can change their type at runtime depending on the object or
367    data assigned to it. This dynamic typing allows you to write code like
368    this (if you really wanted to):
369  </para>
371  <informalexample><!-- <title>Dynamic typing of variables</title> -->
372   <programlisting>// note: no type declaration
373result = Macros.input(view, <quote>Type something here.</quote>);
375// this is our predefined, current View
376result = view;
378// this is an <quote>int</quote> (for integer);
379// in Java and BeanShell, int is one of a small number
380// of <quote>primitive</quote> data types which are not classes
381result = 14;</programlisting>
382  </informalexample>
384  <para>
385    However, if you first declared <varname>result</varname> to be type
386    <classname>String</classname> and and then tried these reassignments,
387    BeanShell would complain.
388  </para>
390  <para>
391    One last thing before we bury our first macro. The double slashes in the
392    examples just above signify that everything following them on that line
393    should be ignored by BeanShell as a comment. As in Java and C/C++, you
394    can also embed comments in your BeanShell code by setting them off with
395    pairs of <userinput>/* */</userinput>, as in the following example:
396  </para>
399  <informalexample>
400   <programlisting>/* This is a long comment that covers several lines
401and will be totally ignored by BeanShell regardless of how
402many lines it covers */</programlisting>
403  </informalexample>
404 </sect1>
406 <sect1 id="something-useful"><title>Now For Something Useful</title>
408  <para>
409    Here is a macro that inserts the path of the current buffer in
410    the text:
411  </para>
414  <informalexample>
415  <!-- <title>Insert buffer path in text</title> -->
416   <programlisting>String newText = buffer.getPath();
418  </informalexample>
420  <para>
421    Two of the new names we see here, <varname>buffer</varname> and
422    <varname>textArea</varname>, are predefined variables like
423    <varname>view</varname>. The variable <varname>buffer</varname>
424    represents a jEdit <varname>Buffer</varname> object, and
425    <varname>textArea</varname> represents a
426    <classname>JEditTextArea</classname> object.
427  </para>
429  <itemizedlist>
430    <listitem>
431      <para>
432        A <classname>Buffer</classname> represents the contents of an open text
433        file. It is derived from Java's <classname>PlainDocument</classname>
434        class. The variable <varname>buffer</varname> is predefined as the
435        current buffer.
436      </para>
437    </listitem>
438    <listitem>
439      <para>
440        A <classname>JEditTextArea</classname> is the visible component that
441        displays the file being edited. It is derived from the
442        <classname>JComponent</classname> class. The variable
443        <varname>textArea</varname> represents the current
444        <classname>JEditTextArea</classname> object, which in turn displays
445        the current buffer.
446      </para>
447    </listitem>
448  </itemizedlist>
450  <para>
451    Unlike in our first macro example, here we are calling class methods on
452    particular objects. First, we call <function>getPath()</function> on the
453    current <classname>Buffer</classname> object to get the full path of the
454    text file currently being edited. Next, we call
455    <function>setSelectedText()</function> on the current text display
456    component, specifying the text to be inserted as a parameter.
457  </para>
459  <para>
460    In precise terms, the <function>setSelectedText()</function> method
461    substitutes the contents of the <classname>String</classname>
462    parameter for a range of selected text that includes the current caret
463    position. If no text is selected at the caret position, the effect
464    of this operation is simply to insert the new text at that position.
465  </para>
467  <para>
468    Here's a few alternatives to the full file path that you could
469    use to insert various useful things:
470  </para>
473  <informalexample><!-- <title>Items to use with
474  <function>setSelectedText()</function></title> -->
475<programlisting>// the file name (without full path)
476String newText = buffer.getName();
478// today's date
479import java.text.DateFormat;
481String newText = DateFormat.getDateInstance()
482    .format(new Date());
484// a line count for the current buffer
485String newText = "This file contains "
486    + textArea.getLineCount() + " lines.";</programlisting>
489  <para>
490    Here are brief comments on each:
491  </para>
493  <itemizedlist>
494   <listitem>
495    <para>
496      In the first, the call to <function>getName()</function> invokes
497      another method of the <classname>Buffer</classname> class.
498    </para>
499   </listitem>
501   <listitem>
502    <para>
503      The syntax of the second example chains the results of
504      several methods. You could write it this way:
505    </para>
507<programlisting>import java.text.DateFormat;
508Date d = new Date();
509DateFormat df = DateFormat.getDateInstance();
510String result = df.format(d);
513   <para>
514	  Taking the pieces in order:
515   </para>
517   <itemizedlist>
518	   <listitem>
519	     <para>
520         A Java <classname>Date</classname> object is created using the
521         <function>new</function> keyword. The empty parenthesis after
522         <classname>Date</classname> signify a call on the <glossterm>
523         constructor method</glossterm> of <classname>Date</classname> having no
524         parameters; here, a <classname>Date</classname> is created representing
525         the current date and time.
526       </para>
527	   </listitem>
529	   <listitem>
530	     <para>
531         <function>DateFormat.getDateInstance()</function> is a static method
532         that creates and returns a <classname>DateFormat</classname> object. As
533         the name implies, <classname>DateFormat</classname> is a Java class
534         that takes <classname>Date</classname> objects and produces readable
535         text. The method <function>getDateInstance()</function> returns a
536         <classname>DateFormat</classname> object that parses and formats dates.
537         It will use the default <glossterm>locale</glossterm> or text format
538         specified in the user's Java installation.
539       </para>
540	  </listitem>
542	  <listitem>
543	    <para>
544        Finally, <classname>DateFormat.format()</classname> is called on the
545        new <classname>DateFormat</classname> object using the
546        <classname>Date</classname> object as a parameter. The result is a
547        <classname>String</classname> containing the date in the default
548        locale.
549      </para>
550	  </listitem>
552    <listitem>
553      <para>
554        Note that the <classname>Date</classname> class is contained in
555        the <literal>java.util</literal> package, so an explicit import
556        statement is not required. However, <classname>DateFormat</classname>
557        is part of the <literal>java.text</literal> package, which is
558        not automatically imported, so an explicit
559        <function>import</function> statement must be used.
560      </para>
561    </listitem>
562	</itemizedlist>
564   </listitem>
566   <listitem>
567    <para>
568    The third example shows three items of note:
569	 <itemizedlist>
570	  <listitem>
571	   <para>
572       <function>getLineCount()</function> is a method in jEdit's
573       <classname>JEditTextArea</classname> class. It returns an
574       <type>int</type> representing the number of lines in the
575       current text buffer. We call it on <varname>textArea</varname>, the
576       pre-defined, current <classname>JEditTextArea</classname> object.
577      </para>
578	  </listitem>
580	  <listitem>
581	   <para>
582       The use of the <function>+</function> operator (which can be chained,
583       as here) appends objects and string
584       literals to return a single, concatenated <classname>String</classname>.
585       </para>
586	  </listitem>
587	 </itemizedlist>
588   </para>
589   </listitem>
590  </itemizedlist>
592  <sidebar><title>The other pre-defined variable</title>
593   <para>
594    In addition to <varname>view</varname>, <varname>buffer</varname> and
595    <varname>textArea</varname>, there is one more pre-defined variable
596    available for use in macros -- <varname>editPane</varname>. That
597    variable is set to the current <classname>EditPane</classname> instance.
598    An <classname>EditPane</classname> object contains a text area and
599    buffer switcher. A view can be split to display multiple
600    buffers, each in its own edit pane. Among other things, the
601    <classname>EditPane</classname> class contains methods for selecting
602    the buffer to edit.
603   </para>
604   <para>
605    Most of the time your macros will manipulate the <varname>buffer</varname>
606    or the <varname>textArea</varname>. Sometimes you will need to use
607    <varname>view</varname> as a parameter in a method call. You will probably
608    only need to use <varname>editPane</varname> if your macros work with
609    split views.
610   </para>
611  </sidebar>
612 </sect1>