PageRenderTime 159ms CodeModel.GetById 145ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms


XML | 616 lines | 530 code | 74 blank | 12 comment | 0 complexity | 561773487aed243df754e77e0f5fb9d4 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 int <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>,
313   <constant>JOptionPane.YES_NO_CANCEL_OPTION</constant>, or
314   <constant>JOptionPane.OK_CANCEL_OPTION</constant>. The return
315   value of the method is one of
316   <constant>JOptionPane.YES_OPTION</constant>,
317   <constant>JOptionPane.NO_OPTION</constant>,
318   <constant>JOptionPane.OK_OPTION</constant> or
319   <constant>JOptionPane.CANCEL_OPTION</constant>.
320  </para>
322  <para>
323   For those without Java experience, it is important to know that
324   <constant>null</constant> is <emphasis>not</emphasis> the same as an
325   empty, <quote>zero-length</quote> <classname>String</classname>. It is
326   Java's way of saying that there is no object associated with this
327   variable. Whenever you seek to use a return value from
328   <function>input()</function> in your macro, you should test it to see if
329   it is <constant>null</constant>. In most cases, you will
330   want to exit gracefully from the script with a
331   <function>return</function> statement, because the presence of a null
332   value for an input variable usually means that the user intended to
333   cancel macro execution. BeanShell will complain if you call any
334   methods on a <constant>null</constant> object.
335  </para>
337  <para>
338   We've looked at using <function>Macros.message()</function>. To
339   use the other methods, you would write something like the
340   following:
341  </para>
343  <informalexample><!-- <title>Using <function>Macros.error()</function> and
344  <function>Macros.input()</function></title> -->
345   <programlisting>Macros.error(view, "Goodbye, cruel world!");
347String result = Macros.input(view, "Type something here.");
349String result = Macros.input(view, "What is your name?",
350    "John Gellene");</programlisting>
351  </informalexample>
353  <para>
354    In the last two examples, placing the word <classname>String</classname>
355    before the variable name <varname>result</varname> tells BeanShell that
356    the variable refers to a <classname>String</classname> object, even
357    before a particular <classname>String</classname> object is assigned to
358    it. In BeanShell, this <glossterm>declaration</glossterm> of the
359    <glossterm>type</glossterm> of <varname>result</varname> is not
360    necessary; BeanShell can figure it out when the macro runs. This can be
361    helpful if you are not comfortable with types and classes; just use your
362    variables and let BeanShell worry about it.
363  </para>
365  <para>
366    Without an explicit <glossterm>type declaration</glossterm> like
367    <classname>String</classname> <varname>result</varname>, BeanShell
368    variables can change their type at runtime depending on the object or
369    data assigned to it. This dynamic typing allows you to write code like
370    this (if you really wanted to):
371  </para>
373  <informalexample><!-- <title>Dynamic typing of variables</title> -->
374   <programlisting>// note: no type declaration
375result = Macros.input(view, <quote>Type something here.</quote>);
377// this is our predefined, current View
378result = view;
380// this is an <quote>int</quote> (for integer);
381// in Java and BeanShell, int is one of a small number
382// of <quote>primitive</quote> data types which are not classes
383result = 14;</programlisting>
384  </informalexample>
386  <para>
387    However, if you first declared <varname>result</varname> to be type
388    <classname>String</classname> and and then tried these reassignments,
389    BeanShell would complain.
390  </para>
392  <para>
393    One last thing before we bury our first macro. The double slashes in the
394    examples just above signify that everything following them on that line
395    should be ignored by BeanShell as a comment. As in Java and C/C++, you
396    can also embed comments in your BeanShell code by setting them off with
397    pairs of <userinput>/* */</userinput>, as in the following example:
398  </para>
401  <informalexample>
402   <programlisting>/* This is a long comment that covers several lines
403and will be totally ignored by BeanShell regardless of how
404many lines it covers */</programlisting>
405  </informalexample>
406 </sect1>
408 <sect1 id="something-useful"><title>Now For Something Useful</title>
410  <para>
411    Here is a macro that inserts the path of the current buffer in
412    the text:
413  </para>
416  <informalexample>
417  <!-- <title>Insert buffer path in text</title> -->
418   <programlisting>String newText = buffer.getPath();
420  </informalexample>
422  <para>
423    Two of the new names we see here, <varname>buffer</varname> and
424    <varname>textArea</varname>, are predefined variables like
425    <varname>view</varname>. The variable <varname>buffer</varname>
426    represents a jEdit <varname>Buffer</varname> object, and
427    <varname>textArea</varname> represents a
428    <classname>JEditTextArea</classname> object.
429  </para>
431  <itemizedlist>
432    <listitem>
433      <para>
434        A <classname>Buffer</classname> represents the contents of an open text
435        file. It is derived from Java's <classname>PlainDocument</classname>
436        class. The variable <varname>buffer</varname> is predefined as the
437        current buffer.
438      </para>
439    </listitem>
440    <listitem>
441      <para>
442        A <classname>JEditTextArea</classname> is the visible component that
443        displays the file being edited. It is derived from the
444        <classname>JComponent</classname> class. The variable
445        <varname>textArea</varname> represents the current
446        <classname>JEditTextArea</classname> object, which in turn displays
447        the current buffer.
448      </para>
449    </listitem>
450  </itemizedlist>
452  <para>
453    Unlike in our first macro example, here we are calling class methods on
454    particular objects. First, we call <function>getPath()</function> on the
455    current <classname>Buffer</classname> object to get the full path of the
456    text file currently being edited. Next, we call
457    <function>setSelectedText()</function> on the current text display
458    component, specifying the text to be inserted as a parameter.
459  </para>
461  <para>
462    In precise terms, the <function>setSelectedText()</function> method
463    substitutes the contents of the <classname>String</classname>
464    parameter for a range of selected text that includes the current caret
465    position. If no text is selected at the caret position, the effect
466    of this operation is simply to insert the new text at that position.
467  </para>
469  <para>
470    Here's a few alternatives to the full file path that you could
471    use to insert various useful things:
472  </para>
475  <informalexample><!-- <title>Items to use with
476  <function>setSelectedText()</function></title> -->
477<programlisting>// the file name (without full path)
478String newText = buffer.getName();
480// today's date
481import java.text.DateFormat;
483String newText = DateFormat.getDateInstance()
484    .format(new Date());
486// a line count for the current buffer
487String newText = "This file contains "
488    + textArea.getLineCount() + " lines.";</programlisting>
491  <para>
492    Here are brief comments on each:
493  </para>
495  <itemizedlist>
496   <listitem>
497    <para>
498      In the first, the call to <function>getName()</function> invokes
499      another method of the <classname>Buffer</classname> class.
500    </para>
501   </listitem>
503   <listitem>
504    <para>
505      The syntax of the second example chains the results of
506      several methods. You could write it this way:
507    </para>
509<programlisting>import java.text.DateFormat;
510Date d = new Date();
511DateFormat df = DateFormat.getDateInstance();
512String result = df.format(d);
515   <para>
516	  Taking the pieces in order:
517   </para>
519   <itemizedlist>
520	   <listitem>
521	     <para>
522         A Java <classname>Date</classname> object is created using the
523         <function>new</function> keyword. The empty parenthesis after
524         <classname>Date</classname> signify a call on the <glossterm>
525         constructor method</glossterm> of <classname>Date</classname> having no
526         parameters; here, a <classname>Date</classname> is created representing
527         the current date and time.
528       </para>
529	   </listitem>
531	   <listitem>
532	     <para>
533         <function>DateFormat.getDateInstance()</function> is a static method
534         that creates and returns a <classname>DateFormat</classname> object. As
535         the name implies, <classname>DateFormat</classname> is a Java class
536         that takes <classname>Date</classname> objects and produces readable
537         text. The method <function>getDateInstance()</function> returns a
538         <classname>DateFormat</classname> object that parses and formats dates.
539         It will use the default <glossterm>locale</glossterm> or text format
540         specified in the user's Java installation.
541       </para>
542	  </listitem>
544	  <listitem>
545	    <para>
546        Finally, <classname>DateFormat.format()</classname> is called on the
547        new <classname>DateFormat</classname> object using the
548        <classname>Date</classname> object as a parameter. The result is a
549        <classname>String</classname> containing the date in the default
550        locale.
551      </para>
552	  </listitem>
554    <listitem>
555      <para>
556        Note that the <classname>Date</classname> class is contained in
557        the <literal>java.util</literal> package, so an explicit import
558        statement is not required. However, <classname>DateFormat</classname>
559        is part of the <literal>java.text</literal> package, which is
560        not automatically imported, so an explicit
561        <function>import</function> statement must be used.
562      </para>
563    </listitem>
564	</itemizedlist>
566   </listitem>
568   <listitem>
569    <para>
570    The third example shows three items of note:
571	 <itemizedlist>
572	  <listitem>
573	   <para>
574       <function>getLineCount()</function> is a method in jEdit's
575       <classname>JEditTextArea</classname> class. It returns an
576       <type>int</type> representing the number of lines in the
577       current text buffer. We call it on <varname>textArea</varname>, the
578       pre-defined, current <classname>JEditTextArea</classname> object.
579      </para>
580	  </listitem>
582	  <listitem>
583	   <para>
584       The use of the <function>+</function> operator (which can be chained,
585       as here) appends objects and string
586       literals to return a single, concatenated <classname>String</classname>.
587       </para>
588	  </listitem>
589	 </itemizedlist>
590   </para>
591   </listitem>
592  </itemizedlist>
594  <sidebar><title>The other pre-defined variable</title>
595   <para>
596    In addition to <varname>view</varname>, <varname>buffer</varname> and
597    <varname>textArea</varname>, there is one more pre-defined variable
598    available for use in macros -- <varname>editPane</varname>. That
599    variable is set to the current <classname>EditPane</classname> instance.
600    An <classname>EditPane</classname> object contains a text area and
601    buffer switcher. A view can be split to display multiple
602    buffers, each in its own edit pane. Among other things, the
603    <classname>EditPane</classname> class contains methods for selecting
604    the buffer to edit.
605   </para>
606   <para>
607    Most of the time your macros will manipulate the <varname>buffer</varname>
608    or the <varname>textArea</varname>. Sometimes you will need to use
609    <varname>view</varname> as a parameter in a method call. You will probably
610    only need to use <varname>editPane</varname> if your macros work with
611    split views.
612   </para>
613  </sidebar>
614 </sect1>