PageRenderTime 151ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/doc/users-guide/macro-basics.xml

#
XML | 781 lines | 670 code | 95 blank | 16 comment | 0 complexity | 17b26e7a05005f715dceb9e9f9a554ed 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 4777 2003-06-11 23:55:39Z 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 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 an open text
  306. file. The variable <varname>buffer</varname> is predefined as the
  307. current, visible buffer being edited.
  308. </para></listitem>
  309. <listitem><para><varname>view</varname> -
  310. A <ulink url="../api/org/gjt/sp/jedit/View.html">View</ulink>
  311. represents a top-level window, extending Java's <classname>JFrame</classname>
  312. class, that
  313. contains the various visible components of the program, including the
  314. text area, menu bar, toolbar, and any docked windows.
  315. The variable <varname>view</varname> is defined
  316. as the current, active <ulink url="../api/org/gjt/sp/jedit/View.html">View</ulink> object.
  317. </para>
  318. <para>
  319. This variable has the same value as calling:
  320. </para>
  321. <programlisting>jEdit.getActiveView()</programlisting>
  322. </listitem>
  323. <listitem><para><varname>editPane</varname> -
  324. an <ulink url="../api/org/gjt/sp/jedit/EditPane.html">EditPane</ulink> object contains a text area and
  325. buffer switcher. A view can be split to display multiple
  326. buffers, each in its own edit pane. Among other things, the
  327. <ulink url="../api/org/gjt/sp/jedit/EditPane.html">EditPane</ulink> class contains methods for selecting
  328. the buffer to edit.
  329. </para>
  330. <para>
  331. Most of the time your macros will manipulate the <varname>buffer</varname>
  332. or the <varname>textArea</varname>. Sometimes you will need to use
  333. <varname>view</varname> as a parameter in a method call. You will probably
  334. only need to use <varname>editPane</varname> if your macros work with
  335. split views.
  336. </para>
  337. <para>
  338. This variable has the same value as calling:
  339. </para>
  340. <programlisting>view.getEditPane()</programlisting>
  341. </listitem>
  342. <listitem><para><varname>textArea</varname> -
  343. a <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> is the visible component that
  344. displays the file being edited. It is derived from the
  345. <classname>JComponent</classname> class. The variable
  346. <varname>textArea</varname> represents the current
  347. <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> object, which in turn displays
  348. the current buffer.
  349. </para>
  350. <para>
  351. This variable has the same value as calling:
  352. </para>
  353. <programlisting>editPane.getTextArea()</programlisting></listitem>
  354. <listitem><para><varname>scriptPath</varname> - set to the full path
  355. of the script currently being executed.
  356. </para></listitem>
  357. </itemizedlist>
  358. <para>
  359. Note that these variables are set at the beginning of macro
  360. execution. If the macro switches views, buffers or edit panes,
  361. the variables will be out of date. In that case, you can use
  362. the method calls equivalent to the values of the variables.
  363. </para>
  364. </sect1>
  365. <sect1 id="helpful-methods"><title>Helpful Methods in the
  366. Macros Class</title>
  367. <para>
  368. Including <function>message()</function>, there are five static methods
  369. in the <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class that allow you to converse
  370. easily with your macros. They all encapsulate calls to methods of the
  371. Java platform's <classname>JOptionPane</classname> class.
  372. </para>
  373. <itemizedlist>
  374. <listitem>
  375. <funcsynopsis>
  376. <funcprototype>
  377. <funcdef>public static void <function>message</function></funcdef>
  378. <paramdef>Component <parameter>comp</parameter></paramdef>
  379. <paramdef>String <parameter>message</parameter></paramdef>
  380. </funcprototype>
  381. </funcsynopsis>
  382. </listitem>
  383. <listitem>
  384. <funcsynopsis>
  385. <funcprototype>
  386. <funcdef>public static void <function>error</function></funcdef>
  387. <paramdef>Component <parameter>comp</parameter></paramdef>
  388. <paramdef>String <parameter>message</parameter></paramdef>
  389. </funcprototype>
  390. </funcsynopsis>
  391. </listitem>
  392. <listitem>
  393. <funcsynopsis>
  394. <funcprototype>
  395. <funcdef>public static String <function>input</function></funcdef>
  396. <paramdef>Component <parameter>comp</parameter></paramdef>
  397. <paramdef>String <parameter>prompt</parameter></paramdef>
  398. </funcprototype>
  399. </funcsynopsis>
  400. </listitem>
  401. <listitem>
  402. <funcsynopsis>
  403. <funcprototype>
  404. <funcdef>public static String <function>input</function></funcdef>
  405. <paramdef>Component <parameter>comp</parameter></paramdef>
  406. <paramdef>String <parameter>prompt</parameter></paramdef>
  407. <paramdef>String <parameter>defaultValue</parameter></paramdef>
  408. </funcprototype>
  409. </funcsynopsis>
  410. </listitem>
  411. <listitem>
  412. <funcsynopsis>
  413. <funcprototype>
  414. <funcdef>public static int <function>confirm</function></funcdef>
  415. <paramdef>Component <parameter>comp</parameter></paramdef>
  416. <paramdef>String <parameter>prompt</parameter></paramdef>
  417. <paramdef>int <parameter>buttons</parameter></paramdef>
  418. </funcprototype>
  419. </funcsynopsis>
  420. </listitem>
  421. </itemizedlist>
  422. <para>
  423. The format of these four <glossterm>declarations</glossterm> provides a
  424. concise reference to the way in which the methods may be used. The
  425. keyword <function>public</function> means that the method can be used
  426. outside the <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class. The alternatives are
  427. <function>private</function> and <function>protected</function>. For
  428. purposes of BeanShell, you just have to know that BeanShell can only use
  429. public methods of other Java classes. The keyword
  430. <function>static</function> we have already discussed. It means that the
  431. method does not operate on a particular object. You call a static
  432. function using the name of the class (like
  433. <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink>) rather than the name of a particular
  434. object (like <varname>view</varname>). The third word is the type of the
  435. value returned by the method. The keyword <function>void</function> is
  436. Java's way of saying the the method does not have a return value.
  437. </para>
  438. <para>
  439. The <function>error()</function> method works just like
  440. <function>message()</function> but displays an error icon in the message
  441. box. The <function>input()</function> method furnishes a text field for
  442. input, an <guilabel>OK</guilabel> button and a
  443. <guilabel>Cancel</guilabel> button. If <guilabel>Cancel</guilabel> is pressed,
  444. the method returns <constant>null</constant>. If <guilabel>OK</guilabel>
  445. is pressed, a <classname>String</classname> containing the contents of
  446. the text field is returned. Note that there are two forms of the
  447. <function>input()</function> method; the first form with two parameters
  448. displays an empty input field, the other forms lets you specify an initial,
  449. default input value.
  450. </para>
  451. <para>
  452. For those without Java experience, it is important to know that
  453. <constant>null</constant> is <emphasis>not</emphasis> the same as an
  454. empty, <quote>zero-length</quote> <classname>String</classname>. It is
  455. Java's way of saying that there is no object associated with this
  456. variable. Whenever you seek to use a return value from
  457. <function>input()</function> in your macro, you should test it to see if
  458. it is <constant>null</constant>. In most cases, you will
  459. want to exit gracefully from the script with a
  460. <function>return</function> statement, because the presence of a null
  461. value for an input variable usually means that the user intended to
  462. cancel macro execution. BeanShell will complain if you call any
  463. methods on a <constant>null</constant> object.
  464. </para>
  465. <para>
  466. The <function>confirm()</function> method in the
  467. <ulink url="../api/org/gjt/sp/jedit/Macros.html">Macros</ulink> class is a little more complex. The
  468. <varname>buttons</varname> parameter has an <classname>int</classname>
  469. type, and the usual way to supply a value is to use one of
  470. the predefined values taken from Java's
  471. <classname>JOptionPane</classname> class. You can choose among
  472. <constant>JOptionPane.YES_NO_OPTION</constant>,
  473. <constant>JOptionPane.YES_NO_CANCEL_OPTION</constant>, or
  474. <constant>JOptionPane.OK_CANCEL_OPTION</constant>. The return
  475. value of the method is also an <classname>int</classname>, and should be tested
  476. against the value of other predefined constants:
  477. <constant>JOptionPane.YES_OPTION</constant>,
  478. <constant>JOptionPane.NO_OPTION</constant>,
  479. <constant>JOptionPane.OK_OPTION</constant> or
  480. <constant>JOptionPane.CANCEL_OPTION</constant>.
  481. </para>
  482. <para>
  483. We've looked at using <function>Macros.message()</function>. To
  484. use the other methods, you would write something like the
  485. following:
  486. </para>
  487. <informalexample><!-- <title>Using <function>Macros.error()</function> and
  488. <function>Macros.input()</function></title> -->
  489. <programlisting>Macros.error(view, "Goodbye, cruel world!");
  490. String result = Macros.input(view, "Type something here.");
  491. String result = Macros.input(view, "When were you born?",
  492. "I don't remember, I was very young at the time");
  493. int result = Macros.confirm("Do you really want to learn"
  494. + " about BeanShell?",JOptionPane.YES_NO_OPTION);
  495. </programlisting>
  496. </informalexample>
  497. <para>
  498. In the last three examples, placing the word <classname>String</classname>
  499. or <classname>int</classname>
  500. before the variable name <varname>result</varname> tells BeanShell that
  501. the variable refers to an integer or a <classname>String</classname> object, even
  502. before a particular value is assigned to the variable.
  503. In BeanShell, this <glossterm>declaration</glossterm> of the
  504. <glossterm>type</glossterm> of <varname>result</varname> is not
  505. necessary; BeanShell can figure it out when the macro runs. This can be
  506. helpful if you are not comfortable with specifying types and classes;
  507. just use your variables and let BeanShell worry about it.
  508. </para>
  509. <para>
  510. 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"/>.
  511. </para>
  512. </sect1>
  513. <sect1 id="dynamic-typing"><title>BeanShell Dynamic Typing</title>
  514. <para>
  515. Without an explicit <glossterm>type declaration</glossterm> like
  516. <classname>String</classname> <varname>result</varname>, BeanShell
  517. variables can change their type at runtime depending on the object or
  518. data assigned to it. This dynamic typing allows you to write code like
  519. this (if you really wanted to):
  520. </para>
  521. <informalexample><!-- <title>Dynamic typing of variables</title> -->
  522. <programlisting>// note: no type declaration
  523. result = Macros.input(view, <quote>Type something here.</quote>);
  524. // this is our predefined, current View
  525. result = view;
  526. // this is an <quote>int</quote> (for integer);
  527. // in Java and BeanShell, int is one of a small number
  528. // of <quote>primitive</quote> data types which are not classes
  529. result = 14;</programlisting>
  530. </informalexample>
  531. <para>
  532. However, if you first declared <varname>result</varname> to be type
  533. <classname>String</classname> and and then tried these reassignments,
  534. BeanShell would complain. While avoiding explicit type declaration makes
  535. writing macro code simpler, using them can act as a check to make sure you are
  536. not using the wrong variable type of object at a later point in your
  537. script. It also makes it easier (if you are so inclined) to take a
  538. BeanShell <quote>prototype</quote> and incorporate it in a Java program.
  539. </para>
  540. <para>
  541. One last thing before we bury our first macro. The double slashes in the
  542. examples just above signify that everything following them on that line
  543. should be ignored by BeanShell as a comment. As in Java and C/C++, you
  544. can also embed comments in your BeanShell code by setting them off with
  545. pairs of <userinput>/* */</userinput>, as in the following example:
  546. </para>
  547. <informalexample>
  548. <programlisting>/* This is a long comment that covers several lines
  549. and will be totally ignored by BeanShell regardless of how
  550. many lines it covers */</programlisting>
  551. </informalexample>
  552. </sect1>
  553. <sect1 id="something-useful"><title>Now For Something Useful</title>
  554. <para>
  555. Here is a macro that inserts the path of the current buffer in
  556. the text:
  557. </para>
  558. <informalexample>
  559. <!-- <title>Insert buffer path in text</title> -->
  560. <programlisting>String newText = buffer.getPath();
  561. textArea.setSelectedText(newText);</programlisting>
  562. </informalexample>
  563. <para>
  564. Unlike in our first macro example, here we are calling class methods on
  565. particular objects. First, we call <function>getPath()</function> on the
  566. current <ulink url="../api/org/gjt/sp/jedit/Buffer.html">Buffer</ulink> object to get the full path of the
  567. text file currently being edited. Next, we call
  568. <function>setSelectedText()</function> on the current text display
  569. component, specifying the text to be inserted as a parameter.
  570. </para>
  571. <para>
  572. In precise terms, the <function>setSelectedText()</function> method
  573. substitutes the contents of the <classname>String</classname>
  574. parameter for a range of selected text that includes the current caret
  575. position. If no text is selected at the caret position, the effect
  576. of this operation is simply to insert the new text at that position.
  577. </para>
  578. <para>
  579. Here's a few alternatives to the full file path that you could
  580. use to insert various useful things:
  581. </para>
  582. <informalexample><!-- <title>Items to use with
  583. <function>setSelectedText()</function></title> -->
  584. <programlisting>// the file name (without full path)
  585. String newText = buffer.getName();
  586. // today's date
  587. import java.text.DateFormat;
  588. String newText = DateFormat.getDateInstance()
  589. .format(new Date());
  590. // a line count for the current buffer
  591. String newText = "This file contains "
  592. + textArea.getLineCount() + " lines.";</programlisting>
  593. </informalexample>
  594. <para>
  595. Here are brief comments on each:
  596. </para>
  597. <itemizedlist>
  598. <listitem>
  599. <para>
  600. In the first, the call to <function>getName()</function> invokes
  601. another method of the <ulink url="../api/org/gjt/sp/jedit/Buffer.html">Buffer</ulink> class.
  602. </para>
  603. </listitem>
  604. <listitem>
  605. <para>
  606. The syntax of the second example chains the results of
  607. several methods. You could write it this way:
  608. </para>
  609. <programlisting>import java.text.DateFormat;
  610. Date d = new Date();
  611. DateFormat df = DateFormat.getDateInstance();
  612. String result = df.format(d);
  613. </programlisting>
  614. <para>
  615. Taking the pieces in order:
  616. </para>
  617. <itemizedlist>
  618. <listitem>
  619. <para>
  620. A Java <classname>Date</classname> object is created using the
  621. <function>new</function> keyword. The empty parenthesis after
  622. <classname>Date</classname> signify a call on the <glossterm>
  623. constructor method</glossterm> of <classname>Date</classname> having no
  624. parameters; here, a <classname>Date</classname> is created representing
  625. the current date and time.
  626. </para>
  627. </listitem>
  628. <listitem>
  629. <para>
  630. <function>DateFormat.getDateInstance()</function> is a static method
  631. that creates and returns a <classname>DateFormat</classname> object. As
  632. the name implies, <classname>DateFormat</classname> is a Java class
  633. that takes <classname>Date</classname> objects and produces readable
  634. text. The method <function>getDateInstance()</function> returns a
  635. <classname>DateFormat</classname> object that parses and formats dates.
  636. It will use the default <glossterm>locale</glossterm> or text format
  637. specified in the user's Java installation.
  638. </para>
  639. </listitem>
  640. <listitem>
  641. <para>
  642. Finally, <classname>DateFormat.format()</classname> is called on the
  643. new <classname>DateFormat</classname> object using the
  644. <classname>Date</classname> object as a parameter. The result is a
  645. <classname>String</classname> containing the date in the default
  646. locale.
  647. </para>
  648. </listitem>
  649. <listitem>
  650. <para>
  651. Note that the <classname>Date</classname> class is contained in
  652. the <literal>java.util</literal> package, so an explicit import
  653. statement is not required. However, <classname>DateFormat</classname>
  654. is part of the <literal>java.text</literal> package, which is
  655. not automatically imported, so an explicit
  656. <function>import</function> statement must be used.
  657. </para>
  658. </listitem>
  659. </itemizedlist>
  660. </listitem>
  661. <listitem>
  662. <para>
  663. The third example shows three items of note:
  664. <itemizedlist>
  665. <listitem>
  666. <para>
  667. <function>getLineCount()</function> is a method in jEdit's
  668. <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> class. It returns an
  669. <classname>int</classname> representing the number of lines in the
  670. current text buffer. We call it on <varname>textArea</varname>, the
  671. pre-defined, current <ulink url="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html">JEditTextArea</ulink> object.
  672. </para>
  673. </listitem>
  674. <listitem>
  675. <para>
  676. The use of the <function>+</function> operator (which can be chained,
  677. as here) appends objects and string
  678. literals to return a single, concatenated <classname>String</classname>.
  679. </para>
  680. </listitem>
  681. </itemizedlist>
  682. </para>
  683. </listitem>
  684. </itemizedlist>
  685. </sect1>
  686. </chapter>