PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/doc/users-guide/macro-basics.xml

#
XML | 785 lines | 673 code | 96 blank | 16 comment | 0 complexity | f56bfef3c4d58a0ccaab63f1fe0efbb6 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. <!-- jEdit 4.0 Macro Guide, (C) 2001, 2002 John Gellene -->
  2. <!-- -->
  3. <!-- jEdit buffer-local properties: -->
  4. <!-- :indentSize=1:noTabs=yes:maxLineLen=72:tabSize=2: -->
  5. <!-- :xml.root=users-guide.xml: -->
  6. <!-- -->
  7. <!-- This file cover the introductory section of the macro guide -->
  8. <!-- $Id: macro-basics.xml 5136 2004-10-17 04:36:32Z spestov $
  9. -->
  10. <chapter id="macro-basics"><title>Macro Basics</title>
  11. <sect1 id="beanshell-intro"><title>Introducing BeanShell</title>
  12. <para>
  13. Here is how BeanShell's author, Pat Niemeyer, describes his creation:
  14. </para>
  15. <blockquote>
  16. <para>
  17. <quote>BeanShell is a small, free, embeddable, Java source
  18. interpreter with object scripting language features, written in
  19. Java. BeanShell executes standard Java statements and
  20. expressions, in addition to obvious scripting commands and
  21. syntax. BeanShell supports scripted objects as simple method
  22. closures like those in Perl and JavaScript.</quote>
  23. </para>
  24. </blockquote>
  25. <para>
  26. You do not have to know anything about Java to begin writing your own
  27. jEdit macros. But if you know how to program in Java, you already know
  28. how to write BeanShell scripts. The major strength of using
  29. BeanShell with a program written in Java is that it allows the user to
  30. customize the program's behavior using the same interfaces
  31. designed and used by the program itself. BeanShell can
  32. turn a well-designed application into a powerful, extensible toolkit.
  33. </para>
  34. <para>
  35. This guide focuses on using BeanShell in macros. If you are interested
  36. in learning more about BeanShell generally, consult the <ulink
  37. url="http://www.beanshell.org">BeanShell web site</ulink>. Information
  38. on how to run and organize macros, whether included with the jEdit
  39. installation or written by you, can be found in
  40. <xref linkend="using-macros"/>.
  41. </para>
  42. </sect1>
  43. <sect1 id="single-macros"><title>Single Execution Macros</title>
  44. <para>
  45. As noted in <xref linkend="organizing-macros" />, you can save a BeanShell
  46. script of any length as a text file with the <filename>.bsh</filename>
  47. extension and run it from the <guimenu>Macros</guimenu> menu.
  48. There are three other ways jEdit lets you use BeanShell quickly,
  49. without saving a script to storage, on a <quote>one time only</quote>
  50. basis. You will find them in the <guimenu>Utilities</guimenu> menu.
  51. </para>
  52. <para>
  53. <guimenu>Utilities</guimenu>&gt;<guisubmenu>BeanShell</guisubmenu>&gt;<guimenuitem>Evaluate BeanShell
  54. Expression</guimenuitem> displays a text input dialog
  55. that asks you to type a single line of BeanShell commands. You can type
  56. more than one BeanShell statement so long as each of them ends with a
  57. semicolon. If BeanShell successfully interprets your input, a message
  58. box will appear with the return value of the last statement.
  59. </para>
  60. <para>
  61. <guimenu>Utilities</guimenu>&gt;<guisubmenu>BeanShell</guisubmenu>&gt;<guimenuitem>Evaluate For Selected
  62. Lines</guimenuitem> displays a text input dialog that asks you to
  63. type a single line of BeanShell commands. The commands are evaluated
  64. for each line of the selection. In addition to the standard set of
  65. variables described in <xref linkend="predefined-variables" />,
  66. this command defines the following:
  67. </para>
  68. <itemizedlist>
  69. <listitem><para><varname>line</varname> - the line number, from the
  70. start of the buffer. The first line is numbered 0.
  71. </para></listitem>
  72. <listitem><para><varname>index</varname> - the line number, from the
  73. start of the selection. The first line is numbered 0.
  74. </para></listitem>
  75. <listitem><para><varname>text</varname> - the text of the line.
  76. </para></listitem>
  77. </itemizedlist>
  78. <informalexample>
  79. <para>
  80. Try typing an expression like <userinput>(line + 1) + ": " + text</userinput>
  81. in the <guimenuitem>Evaluate For Selected Lines</guimenuitem> dialog
  82. box. This will add a line number to each selected line beginning with
  83. the number <userinput>1</userinput>.
  84. </para>
  85. </informalexample>
  86. <para>
  87. The BeanShell expression you enter will be evaluated and substituted in place of
  88. the entire text of a selected line. If you want to leave the line's current
  89. text as an element of the modified line, you must include the defined variable
  90. <userinput>text</userinput> as part of the BeanShell expression that you enter.
  91. </para>
  92. <para>
  93. <guimenu>Utilities</guimenu>&gt;<guisubmenu>BeanShell</guisubmenu>&gt;<guimenuitem>Evaluate Selection</guimenuitem>
  94. evaluates the selected text as a BeanShell script and
  95. replaces it with the return value of the statement.
  96. </para>
  97. <para>
  98. Using <guimenuitem>Evaluate Selection</guimenuitem> is an
  99. easy way to do arithmetic calculations inline while editing. BeanShell
  100. uses numbers and arithmetic operations in an ordinary, intuitive way.
  101. </para>
  102. <informalexample>
  103. <para>
  104. Try typing an expression like <userinput>(3745*856)+74</userinput>
  105. in the buffer, select it, and choose
  106. <guimenu>Utilities</guimenu>&gt;<guisubmenu>BeanShell</guisubmenu>&gt;<guimenuitem>Evaluate
  107. Selection</guimenuitem>. The selected text will be replaced by the
  108. answer, <userinput>3205794</userinput>.
  109. <!-- Irrelevant? -->
  110. <!-- Since this is a text file
  111. and not a spreadsheet, the original values that BeanShell evaluated are
  112. not retained or saved as part of the buffer's contents. -->
  113. </para>
  114. </informalexample>
  115. <sidebar><title>Console plugin</title>
  116. <para>
  117. You can also do
  118. the same thing using the BeanShell interpreter option of the
  119. <application>Console</application> plugin.
  120. </para>
  121. </sidebar>
  122. </sect1>
  123. <sect1 id="first-example" ><title>The Mandatory First Example</title>
  124. <informalexample><!-- <title>A first one-line macro</title> -->
  125. <programlisting>Macros.message(view, "Hello world!");</programlisting>
  126. </informalexample>
  127. <para>
  128. Running this one line script causes jEdit to display a message
  129. box (more precisely, a <classname>JOptionPane</classname> object) with
  130. the traditional beginner's message and an <guilabel>OK</guilabel> button.
  131. Let's see what is happening here.
  132. </para>
  133. <para>
  134. This statement calls a static method (or function) named
  135. <function>message</function> in jEdit's <ulink
  136. url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink>
  137. class. If you don't know anything about classes or static methods or
  138. Java (or C++, which employs the same concept), you will need to gain
  139. some understanding of a few terms. Obviously this is not the place for
  140. academic precision, but if you are entirely new to object-oriented
  141. programming, here are a few skeleton ideas to help you with BeanShell.
  142. </para>
  143. <itemizedlist>
  144. <listitem>
  145. <para>
  146. An <glossterm>object</glossterm> is a collection of data that can be
  147. initialized, accessed and manipulated in certain defined ways.
  148. </para>
  149. </listitem>
  150. <listitem>
  151. <para>
  152. A <glossterm>class</glossterm> is a specification of what data an object
  153. contains and what methods can be used to work with the data. A Java
  154. application consists of one or more classes (in the case of jEdit ,over
  155. 600 classes) written by the programmer that defines the application's
  156. behavior. A BeanShell macro uses these classes, along with built-in
  157. classes that are supplied with the Java platform, to define its own
  158. behavior.
  159. </para>
  160. </listitem>
  161. <listitem>
  162. <para>
  163. A <glossterm>subclass</glossterm> (or child class) is a class which
  164. uses (or <quote>inherits</quote>) the data and methods of its parent
  165. class along with additions or modifications that alter the subclass's
  166. behavior. Classes are typically organized in hierarchies of parent
  167. and child classes to organize program code, to define common
  168. behavior in shared parent class code, and to specify the types of
  169. similar behavior that child classes will perform in their own specific ways.
  170. </para>
  171. </listitem>
  172. <listitem>
  173. <para>
  174. A <glossterm>method</glossterm> (or function) is a procedure that works
  175. with data in a particular object, other data (including other objects)
  176. supplied as <glossterm>parameters</glossterm>, or both. Methods
  177. typically are applied to a particular object which is an
  178. <glossterm>instance</glossterm> of the class to which the method
  179. belongs.
  180. </para>
  181. </listitem>
  182. <listitem>
  183. <para>
  184. A <glossterm>static method</glossterm> differs from other methods
  185. in that it does not deal with the data in a particular object but is
  186. included within a class for the sake of convenience.
  187. </para>
  188. </listitem>
  189. </itemizedlist>
  190. <para>
  191. Java has a rich set of classes defined as part of the Java platform.
  192. Like all Java applications, jEdit is organized as a set of classes that
  193. are themselves derived from the Java platform's classes. We will refer
  194. to <firstterm>Java classes</firstterm> and <firstterm>jEdit
  195. classes</firstterm> to make this distinction. Some of jEdit's classes
  196. (such as those dealing with regular expressions and XML) are derived
  197. from or make use of classes in other open-source Java packages. Except
  198. for BeanShell itself, we won't be discussing them in this guide.
  199. </para>
  200. <para>
  201. In our one line script, the static method
  202. <function>Macros.message()</function> has two parameters because that is
  203. the way the method is defined in the <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink>
  204. class. You must specify both parameters when you call the function. The
  205. first parameter, <parameter>view</parameter>, is a variable naming
  206. the current, active <ulink url="../api/org/gjt/sp/jedit/View.html">View</ulink> object. Information
  207. about pre-defined variables can be found in <xref linkend="predefined-variables" />.
  208. </para>
  209. <para>
  210. The second parameter, which appears to be quoted text, is a
  211. <glossterm>string literal</glossterm> - a sequence of characters of
  212. fixed length and content. Behind the scenes, BeanShell and Java take
  213. this string literal and use it to create a <classname>String</classname>
  214. object. Normally, if you want to create an object in Java or BeanShell,
  215. you must construct the object using the <function>new</function> keyword
  216. and a <firstterm>constructor</firstterm> method that is part of the
  217. object's class. We'll show an example of that later. However, both Java
  218. and BeanShell let you use a string literal anytime a method's parameter
  219. calls for a <classname>String</classname>.
  220. </para>
  221. <para>
  222. If you are a Java programmer, you might wonder about a few things
  223. missing from this one line program. There is no class definition, for
  224. example. You can think of a BeanShell script as an implicit definition
  225. of a <function>main()</function> method in an anonymous class. That is
  226. in fact how BeanShell is implemented; the class is derived from
  227. a BeanShell class called <ulink url="../api/bsh/XThis.html">XThis</ulink>. If you
  228. don't find that helpful, just think of a script as one or more blocks of
  229. procedural statements conforming to Java syntax rules. You will also get
  230. along fine (for the most part) with C or C++ syntax if you leave out
  231. anything to do with pointers or memory management - Java and BeanShell
  232. do not have pointers and deal with memory management automatically.
  233. </para>
  234. <para>
  235. Another missing item from a Java perspective is a
  236. <function>package</function> statement. In Java, such a statement is
  237. used to bundle together a number of files so that their classes become
  238. visible to one another. Packages are not part of BeanShell,
  239. and you don't need to know anything about them to write
  240. BeanShell macros.
  241. </para>
  242. <para>
  243. Finally, there are no <function>import</function> statements in this
  244. script. In Java, an <function>import</function> statement makes public
  245. classes from other packages visible within the file in which the
  246. statement occurs without having to specify a fully
  247. qualified class name. Without an import statement or a fully qualified
  248. name, Java cannot identify most classes using a single name as an identifier.
  249. </para>
  250. <para>
  251. jEdit automatically imports a number of commonly-used packages into the
  252. namespace of every BeanShell script. Because of this, the script output
  253. of a recorded macro does not contain <function>import</function>
  254. statements. For the same reason, most BeanShell scripts you write will
  255. not require <function>import</function> statements.
  256. </para>
  257. <para>
  258. Java requires <literal>import</literal> statement to be located
  259. at the beginning of a source file. BeanShell allows you to place
  260. <literal>import</literal>
  261. statements anywhere in a script, including inside a block of
  262. statements. The <literal>import</literal> statement will cover all names
  263. used following the statement in the enclosing block.
  264. </para>
  265. <para>
  266. If you try to use a class that is not imported without its
  267. fully-qualified name, the BeanShell interpreter will complain with an
  268. error message relating to the offending line of code.
  269. </para>
  270. <sidebar>
  271. <para>
  272. Here is the full list of packages automatically imported by jEdit:
  273. </para>
  274. <programlisting>java.awt
  275. java.awt.event
  276. java.net
  277. java.util
  278. java.io
  279. java.lang
  280. javax.swing
  281. javax.swing.event
  282. org.gjt.sp.jedit
  283. org.gjt.sp.jedit.browser
  284. org.gjt.sp.jedit.buffer
  285. org.gjt.sp.jedit.gui
  286. org.gjt.sp.jedit.help
  287. org.gjt.sp.jedit.io
  288. org.gjt.sp.jedit.msg
  289. org.gjt.sp.jedit.options
  290. org.gjt.sp.jedit.pluginmgr
  291. org.gjt.sp.jedit.print
  292. org.gjt.sp.jedit.search
  293. org.gjt.sp.jedit.syntax
  294. org.gjt.sp.jedit.textarea
  295. org.gjt.sp.util</programlisting>
  296. </sidebar>
  297. </sect1>
  298. <sect1 id="predefined-variables"><title>Predefined Variables in BeanShell</title>
  299. <para>
  300. The following variables are always available for use in
  301. BeanShell scripts:
  302. </para>
  303. <itemizedlist>
  304. <listitem><para><varname>buffer</varname> -
  305. a <ulink url="../api/org/gjt/sp/jedit/Buffer.html">Buffer</ulink> object represents the contents of the currently visible open text
  306. file.
  307. </para></listitem>
  308. <listitem><para><varname>view</varname> -
  309. A <ulink url="../api/org/gjt/sp/jedit/View.html">View</ulink>
  310. represents the current top-level editor window, extending Java's <classname>JFrame</classname>
  311. class, that
  312. contains the various visible components of the program, including the
  313. text area, menu bar, toolbar, and any docked windows.
  314. </para>
  315. <para>
  316. This variable has the same value as the return value of:
  317. </para>
  318. <programlisting>jEdit.getActiveView()</programlisting>
  319. </listitem>
  320. <listitem><para><varname>editPane</varname> -
  321. an <ulink url="../api/org/gjt/sp/jedit/EditPane.html">EditPane</ulink> object contains a text area and
  322. buffer switcher. A view can be split to display edit panes. Among other things, the
  323. <ulink url="../api/org/gjt/sp/jedit/EditPane.html">EditPane</ulink> class contains methods for selecting
  324. the buffer to edit.
  325. </para>
  326. <para>
  327. Most of the time your macros will manipulate the <varname>buffer</varname>
  328. or the <varname>textArea</varname>. Sometimes you will need to use
  329. <varname>view</varname> as a parameter in a method call. You will probably
  330. only need to use <varname>editPane</varname> if your macros work with
  331. split views.
  332. </para>
  333. <para>
  334. This variable has the same value as the return value of:
  335. </para>
  336. <programlisting>view.getEditPane()</programlisting>
  337. </listitem>
  338. <listitem><para><varname>textArea</varname> -
  339. a <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> is the visible component that
  340. displays the current buffer.
  341. </para>
  342. <para>
  343. This variable has the same value as the return value of:
  344. </para>
  345. <programlisting>editPane.getTextArea()</programlisting></listitem>
  346. <listitem><para><varname>wm</varname> -
  347. a <ulink url="../api/org/gjt/sp/jedit/gui/DockableWindowManager.html">DockableWindowManager</ulink> is the visible component that
  348. manages dockable windows in the current view. This class is discussed in detail in <xref linkend="writing-plugins-part"/>. This object is useful for writing macros that interface with, open, or close plugin windows.
  349. </para>
  350. <para>
  351. This variable has the same value the return value of:
  352. </para>
  353. <programlisting>view.getDockableWindowManager()</programlisting></listitem>
  354. <listitem><para><varname>scriptPath</varname> - set to the full path
  355. of the script currently being executed.
  356. </para></listitem>
  357. <listitem><para><varname>scriptPath</varname> - set to the full path
  358. of the script currently being executed.
  359. </para></listitem>
  360. </itemizedlist>
  361. <para>
  362. Note that these variables are set at the beginning of macro
  363. execution. If the macro switches views, buffers or edit panes,
  364. the variable values will be out of date. In that case, you can use
  365. the equivalent method calls.
  366. </para>
  367. </sect1>
  368. <sect1 id="helpful-methods"><title>Helpful Methods in the
  369. Macros Class</title>
  370. <para>
  371. Including <function>message()</function>, there are five static methods
  372. in the <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class that allow you to converse
  373. easily with your macros. They all encapsulate calls to methods of the
  374. Java platform's <classname>JOptionPane</classname> class.
  375. </para>
  376. <itemizedlist>
  377. <listitem>
  378. <funcsynopsis>
  379. <funcprototype>
  380. <funcdef>public static void <function>message</function></funcdef>
  381. <paramdef>Component <parameter>comp</parameter></paramdef>
  382. <paramdef>String <parameter>message</parameter></paramdef>
  383. </funcprototype>
  384. </funcsynopsis>
  385. </listitem>
  386. <listitem>
  387. <funcsynopsis>
  388. <funcprototype>
  389. <funcdef>public static void <function>error</function></funcdef>
  390. <paramdef>Component <parameter>comp</parameter></paramdef>
  391. <paramdef>String <parameter>message</parameter></paramdef>
  392. </funcprototype>
  393. </funcsynopsis>
  394. </listitem>
  395. <listitem>
  396. <funcsynopsis>
  397. <funcprototype>
  398. <funcdef>public static String <function>input</function></funcdef>
  399. <paramdef>Component <parameter>comp</parameter></paramdef>
  400. <paramdef>String <parameter>prompt</parameter></paramdef>
  401. </funcprototype>
  402. </funcsynopsis>
  403. </listitem>
  404. <listitem>
  405. <funcsynopsis>
  406. <funcprototype>
  407. <funcdef>public static String <function>input</function></funcdef>
  408. <paramdef>Component <parameter>comp</parameter></paramdef>
  409. <paramdef>String <parameter>prompt</parameter></paramdef>
  410. <paramdef>String <parameter>defaultValue</parameter></paramdef>
  411. </funcprototype>
  412. </funcsynopsis>
  413. </listitem>
  414. <listitem>
  415. <funcsynopsis>
  416. <funcprototype>
  417. <funcdef>public static int <function>confirm</function></funcdef>
  418. <paramdef>Component <parameter>comp</parameter></paramdef>
  419. <paramdef>String <parameter>prompt</parameter></paramdef>
  420. <paramdef>int <parameter>buttons</parameter></paramdef>
  421. </funcprototype>
  422. </funcsynopsis>
  423. </listitem>
  424. </itemizedlist>
  425. <para>
  426. The format of these four <glossterm>declarations</glossterm> provides a
  427. concise reference to the way in which the methods may be used. The
  428. keyword <function>public</function> means that the method can be used
  429. outside the <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class. The alternatives are
  430. <function>private</function> and <function>protected</function>. For
  431. purposes of BeanShell, you just have to know that BeanShell can only use
  432. public methods of other Java classes. The keyword
  433. <function>static</function> we have already discussed. It means that the
  434. method does not operate on a particular object. You call a static
  435. function using the name of the class (like
  436. <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink>) rather than the name of a particular
  437. object (like <varname>view</varname>). The third word is the type of the
  438. value returned by the method. The keyword <function>void</function> is
  439. Java's way of saying the the method does not have a return value.
  440. </para>
  441. <para>
  442. The <function>error()</function> method works just like
  443. <function>message()</function> but displays an error icon in the message
  444. box. The <function>input()</function> method furnishes a text field for
  445. input, an <guilabel>OK</guilabel> button and a
  446. <guilabel>Cancel</guilabel> button. If <guilabel>Cancel</guilabel> is pressed,
  447. the method returns <constant>null</constant>. If <guilabel>OK</guilabel>
  448. is pressed, a <classname>String</classname> containing the contents of
  449. the text field is returned. Note that there are two forms of the
  450. <function>input()</function> method; the first form with two parameters
  451. displays an empty input field, the other forms lets you specify an initial,
  452. default input value.
  453. </para>
  454. <para>
  455. For those without Java experience, it is important to know that
  456. <constant>null</constant> is <emphasis>not</emphasis> the same as an
  457. empty, <quote>zero-length</quote> <classname>String</classname>. It is
  458. Java's way of saying that there is no object associated with this
  459. variable. Whenever you seek to use a return value from
  460. <function>input()</function> in your macro, you should test it to see if
  461. it is <constant>null</constant>. In most cases, you will
  462. want to exit gracefully from the script with a
  463. <function>return</function> statement, because the presence of a null
  464. value for an input variable usually means that the user intended to
  465. cancel macro execution. BeanShell will complain if you call any
  466. methods on a <constant>null</constant> object.
  467. </para>
  468. <para>
  469. The <function>confirm()</function> method in the
  470. <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class is a little more complex. The
  471. <varname>buttons</varname> parameter has an <classname>int</classname>
  472. type, and the usual way to supply a value is to use one of
  473. the predefined values taken from Java's
  474. <classname>JOptionPane</classname> class. You can choose among
  475. <constant>JOptionPane.YES_NO_OPTION</constant>,
  476. <constant>JOptionPane.YES_NO_CANCEL_OPTION</constant>, or
  477. <constant>JOptionPane.OK_CANCEL_OPTION</constant>. The return
  478. value of the method is also an <classname>int</classname>, and should be tested
  479. against the value of other predefined constants:
  480. <constant>JOptionPane.YES_OPTION</constant>,
  481. <constant>JOptionPane.NO_OPTION</constant>,
  482. <constant>JOptionPane.OK_OPTION</constant> or
  483. <constant>JOptionPane.CANCEL_OPTION</constant>.
  484. </para>
  485. <para>
  486. We've looked at using <function>Macros.message()</function>. To
  487. use the other methods, you would write something like the
  488. following:
  489. </para>
  490. <informalexample><!-- <title>Using <function>Macros.error()</function> and
  491. <function>Macros.input()</function></title> -->
  492. <programlisting>Macros.error(view, "Goodbye, cruel world!");
  493. String result = Macros.input(view, "Type something here.");
  494. String result = Macros.input(view, "When were you born?",
  495. "I don't remember, I was very young at the time");
  496. int result = Macros.confirm(view, "Do you really want to learn"
  497. + " about BeanShell?",JOptionPane.YES_NO_OPTION);
  498. </programlisting>
  499. </informalexample>
  500. <para>
  501. In the last three examples, placing the word <classname>String</classname>
  502. or <classname>int</classname>
  503. before the variable name <varname>result</varname> tells BeanShell that
  504. the variable refers to an integer or a <classname>String</classname> object, even
  505. before a particular value is assigned to the variable.
  506. In BeanShell, this <glossterm>declaration</glossterm> of the
  507. <glossterm>type</glossterm> of <varname>result</varname> is not
  508. necessary; BeanShell can figure it out when the macro runs. This can be
  509. helpful if you are not comfortable with specifying types and classes;
  510. just use your variables and let BeanShell worry about it.
  511. </para>
  512. <para>
  513. Note that macros are not limited to using these methods for presenting a user interface. In fact, full-blown user interfaces using the Java Swing APIs are also possible, and will be covered later on in <xref linkend="dialog-macro"/>.
  514. </para>
  515. </sect1>
  516. <sect1 id="dynamic-typing"><title>BeanShell Dynamic Typing</title>
  517. <para>
  518. Without an explicit <glossterm>type declaration</glossterm> like
  519. <classname>String</classname> <varname>result</varname>, BeanShell
  520. variables can change their type at runtime depending on the object or
  521. data assigned to it. This dynamic typing allows you to write code like
  522. this (if you really wanted to):
  523. </para>
  524. <informalexample><!-- <title>Dynamic typing of variables</title> -->
  525. <programlisting>// note: no type declaration
  526. result = Macros.input(view, <quote>Type something here.</quote>);
  527. // this is our predefined, current View
  528. result = view;
  529. // this is an <quote>int</quote> (for integer);
  530. // in Java and BeanShell, int is one of a small number
  531. // of <quote>primitive</quote> data types which are not classes
  532. result = 14;</programlisting>
  533. </informalexample>
  534. <para>
  535. However, if you first declared <varname>result</varname> to be type
  536. <classname>String</classname> and and then tried these reassignments,
  537. BeanShell would complain. While avoiding explicit type declaration makes
  538. writing macro code simpler, using them can act as a check to make sure you are
  539. not using the wrong variable type of object at a later point in your
  540. script. It also makes it easier (if you are so inclined) to take a
  541. BeanShell <quote>prototype</quote> and incorporate it in a Java program.
  542. </para>
  543. <para>
  544. One last thing before we bury our first macro. The double slashes in the
  545. examples just above signify that everything following them on that line
  546. should be ignored by BeanShell as a comment. As in Java and C/C++, you
  547. can also embed comments in your BeanShell code by setting them off with
  548. pairs of <userinput>/* */</userinput>, as in the following example:
  549. </para>
  550. <informalexample>
  551. <programlisting>/* This is a long comment that covers several lines
  552. and will be totally ignored by BeanShell regardless of how
  553. many lines it covers */</programlisting>
  554. </informalexample>
  555. </sect1>
  556. <sect1 id="something-useful"><title>Now For Something Useful</title>
  557. <para>
  558. Here is a macro that inserts the path of the current buffer in
  559. the text:
  560. </para>
  561. <informalexample>
  562. <!-- <title>Insert buffer path in text</title> -->
  563. <programlisting>String newText = buffer.getPath();
  564. textArea.setSelectedText(newText);</programlisting>
  565. </informalexample>
  566. <para>
  567. Unlike in our first macro example, here we are calling class methods on
  568. particular objects. First, we call <function>getPath()</function> on the
  569. current <ulink url="../api/org/gjt/sp/jedit/Buffer.html">Buffer</ulink> object to get the full path of the
  570. text file currently being edited. Next, we call
  571. <function>setSelectedText()</function> on the current text display
  572. component, specifying the text to be inserted as a parameter.
  573. </para>
  574. <para>
  575. In precise terms, the <function>setSelectedText()</function> method
  576. substitutes the contents of the <classname>String</classname>
  577. parameter for a range of selected text that includes the current caret
  578. position. If no text is selected at the caret position, the effect
  579. of this operation is simply to insert the new text at that position.
  580. </para>
  581. <para>
  582. Here's a few alternatives to the full file path that you could
  583. use to insert various useful things:
  584. </para>
  585. <informalexample><!-- <title>Items to use with
  586. <function>setSelectedText()</function></title> -->
  587. <programlisting>// the file name (without full path)
  588. String newText = buffer.getName();
  589. // today's date
  590. import java.text.DateFormat;
  591. String newText = DateFormat.getDateInstance()
  592. .format(new Date());
  593. // a line count for the current buffer
  594. String newText = "This file contains "
  595. + textArea.getLineCount() + " lines.";</programlisting>
  596. </informalexample>
  597. <para>
  598. Here are brief comments on each:
  599. </para>
  600. <itemizedlist>
  601. <listitem>
  602. <para>
  603. In the first, the call to <function>getName()</function> invokes
  604. another method of the <ulink url="../api/org/gjt/sp/jedit/Buffer.html">Buffer</ulink> class.
  605. </para>
  606. </listitem>
  607. <listitem>
  608. <para>
  609. The syntax of the second example chains the results of
  610. several methods. You could write it this way:
  611. </para>
  612. <programlisting>import java.text.DateFormat;
  613. Date d = new Date();
  614. DateFormat df = DateFormat.getDateInstance();
  615. String result = df.format(d);
  616. </programlisting>
  617. <para>
  618. Taking the pieces in order:
  619. </para>
  620. <itemizedlist>
  621. <listitem>
  622. <para>
  623. A Java <classname>Date</classname> object is created using the
  624. <function>new</function> keyword. The empty parenthesis after
  625. <classname>Date</classname> signify a call on the <glossterm>
  626. constructor method</glossterm> of <classname>Date</classname> having no
  627. parameters; here, a <classname>Date</classname> is created representing
  628. the current date and time.
  629. </para>
  630. </listitem>
  631. <listitem>
  632. <para>
  633. <function>DateFormat.getDateInstance()</function> is a static method
  634. that creates and returns a <classname>DateFormat</classname> object. As
  635. the name implies, <classname>DateFormat</classname> is a Java class
  636. that takes <classname>Date</classname> objects and produces readable
  637. text. The method <function>getDateInstance()</function> returns a
  638. <classname>DateFormat</classname> object that parses and formats dates.
  639. It will use the default <glossterm>locale</glossterm> or text format
  640. specified in the user's Java installation.
  641. </para>
  642. </listitem>
  643. <listitem>
  644. <para>
  645. Finally, <classname>DateFormat.format()</classname> is called on the
  646. new <classname>DateFormat</classname> object using the
  647. <classname>Date</classname> object as a parameter. The result is a
  648. <classname>String</classname> containing the date in the default
  649. locale.
  650. </para>
  651. </listitem>
  652. <listitem>
  653. <para>
  654. Note that the <classname>Date</classname> class is contained in
  655. the <literal>java.util</literal> package, so an explicit import
  656. statement is not required. However, <classname>DateFormat</classname>
  657. is part of the <literal>java.text</literal> package, which is
  658. not automatically imported, so an explicit
  659. <function>import</function> statement must be used.
  660. </para>
  661. </listitem>
  662. </itemizedlist>
  663. </listitem>
  664. <listitem>
  665. <para>
  666. The third example shows three items of note:
  667. <itemizedlist>
  668. <listitem>
  669. <para>
  670. <function>getLineCount()</function> is a method in jEdit's
  671. <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> class. It returns an
  672. <classname>int</classname> representing the number of lines in the
  673. current text buffer. We call it on <varname>textArea</varname>, the
  674. pre-defined, current <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> object.
  675. </para>
  676. </listitem>
  677. <listitem>
  678. <para>
  679. The use of the <function>+</function> operator (which can be chained,
  680. as here) appends objects and string
  681. literals to return a single, concatenated <classname>String</classname>.
  682. </para>
  683. </listitem>
  684. </itemizedlist>
  685. </para>
  686. </listitem>
  687. </itemizedlist>
  688. </sect1>
  689. </chapter>