Converted odf_odt for compatibility with both Python 2 and Python3
[docutils.git] / prest / doc / src / prest_extend.rst
blobb1d6b51ab39d5cdfbf423ea36e72ea23687a1b6c
1 ======================
2 How to Extend Prest
3 ======================
4 :Author: Mark Nodine
5 :Contact: mnodine@alum.mit.edu
6 :Revision: $Revision: 762 $
7 :Date: $Date: 2006-01-27 11:47:47 -0600 (Fri, 27 Jan 2006) $
8 :Copyright: This document has been placed in the public domain.
10 .. perl::
11    # Make path safe for -T
12    my $perl_dir = $1 if $^X =~ m|^(.*)/|;
13    $ENV{PATH} = "$perl_dir:/bin";
15 .. contents::
17 This document explains how to write new modules to extend prest.  There
18 are two principal mechanisms by which prest can be extended: adding new
19 plug-in directives/roles and adding new writers.  For either of these tasks,
20 the programmer should be familiar with the DOM_ data structure and the
21 `DOM.pm`_ subroutines.
23 .. _`DOM`: `Text::Restructured::DOM`_
24 .. _`DOM.pm`: prest_internals.html#dom-pm
26 Adding New Directives
27 ---------------------
29 To add a plug-in directive, the programmer should be familiar with the
30 Text::Restructured::Directive:: routines.  The `parser`_ objects are
31 those of type `Text::Restructured`_.  Important routines are
32 `Text::Restructured::Directive::arg_check`_, as well as the
33 Text::Restructured:: routines `Text::Restructured::system_message`_
34 and `Text::Restructured::Paragraphs`_.
36 A plug-in directive can be added by creating a Perl module with the
37 same name as the directive (with a ".pm" extension, of course).  The
38 Perl module should have an ``init`` routine which registers the
39 routine to call to process the directive using
40 `Text::Restructured::Directive::handle_directive`_ (though this call
41 can also be in a BEGIN block).  The ``init`` routine is called with
42 the arguments ``($parser, $source, $lineno)``, where
43 ``$parser`` is the ``Text::Restructured`` object, ``$source`` is the
44 name of the file containing the directive,, and ``$lineno`` is the
45 line number within ``$source``.
47 As an example from the ``if`` plug-in directive,
49 .. system:: perl -ne 'print if /^BEGIN/ .. /^\}/' .\./.\./blib/lib/Text/Restructured/Directive/if.pm
50    :literal:
52 Whatever routine you designate will get called with the following
53 arguments:
55   *``$parser``*:
56     The `Text::Restructured`_ object holding the state of the current
57     parser.
58   *``$name``*:
59     The directive name.  This argument is useful if you use the same
60     routine to process more than one directive with different names.
61   *``$parent``*:
62     Pointer to the parent DOM object.  It is needed to add new DOM objects
63     to the parent's contents.
64   *``$source``*:
65     A string indicating the source for the directive.  If you call
66     `Text::Restructured::Paragraphs`_ to parse reStructuredText
67     recursively, you should supply it a source like "$name directive
68     at $source, line $lineno".
69   *``$lineno``*:
70     The line number indicating where in the source this directive
71     appears. 
72   *``$dtext``*:
73     The directive text in a format suitable for parsing by
74     `Text::Restructured::Directive::parse_directive`_.  It consists of
75     only the arguments, options, and content sections.
76   *``$lit``*:
77     The complete literal text of the explicit markup containing the
78     directive.  Used for generating error messages.
80 The directive's routine will return any DOM objects representing system
81 messages.  It will also likely produce side-effects by appending new
82 DOM objects to the parent object's contents, at least if there were no
83 errors detected by the directive.
85 The first thing the directive's routine will usually do is to call
86 `Text::Restructured::Directive::parse_directive`_ as follows:
88 .. system:: grep parse_directive .\./.\./blib/lib/Text/Restructured/Directive/if.pm
89    :literal:
91 It is recommended that if the directive encounters any parse errors
92 (wrong number of arguments, does/does not contain content, etc.), that
93 it return a ``system_message`` DOM object formatted with
94 `Text::Restructured::Directive::system_msg`_ to label the message as
95 having come from the specific directive.
97 It is also up to the package to provide the documentation that appears
98 when the user runs ``prest -h``.  Any comment in the perl module within
99 a ``=begin Description`` .. ``=end Description`` section of a Perl POD
100 section is printed for the module's help.  For example, here is the
101 help documentation from the ``if`` directive:
103 .. system:: perl -ne 'print if /^=pod/ .. /^=cut/' .\./.\./blib/lib/Text/Restructured/Directive/if.pm
104    :literal:
106 .. note::
108    The help text should parse correctly as reStructuredText, since it
109    is passed through prest to create the web documentation.
111 Adding New Roles
112 ---------------------
114 A plug-in role can be added by creating a Perl module with the same
115 name as the role (with a ".pm" extension, of course).  The Perl module
116 should have an ``init`` routine which registers the role using the
117 parser's `Text::Restructured::DefineRole`_ method.  The ``init``
118 routine is called with the arguments ``($parser, $source, $lineno)``,
119 where ``$parser`` is the ``Text::Restructured`` object, ``$source`` is
120 the name of the file containing the directive,, and ``$lineno`` is the
121 line number within ``$source``.
123 Adding New Writers
124 ------------------
126 The output from a writer is generated by traversing the DOM_ tree
127 recursively.  There can be multiple phases of traversal, and the value
128 produced by the top-level DOM object in the final phase is what
129 actually gets written to the output.
131 Each writer exists in a file that is the writer's name with the
132 extension ``.wrt``.  A ``.wrt`` file has a special write schema
133 format specifically designed to make development of writers easy.
134 Here is a BNF for the _`write schema` file format::
136   parser := phase_list
137   phase_list := phase_desc | phase_list phase_desc
138   phase_desc := phase id eq '{' NL sub_list NL '}' NL
139   phase := 'phase' |
140   eq := '=' |
141   sub_list := sub_desc | sub_list sub_desc
142   sub_desc := sub id eq '{' NL perl_code NL '}' NL
143   sub := 'sub' |
145 An ``id`` is any sequence of non-space characters.  ``NL`` is a newline.
146 ``perl_code`` is the perl code for a subroutine.  Note that the words
147 "phase" and "sub" are optional, as is the equal sign ("=") between the
148 ``id`` and the open brace. 
150 The id's associated with phases are arbitrary.  The phases are
151 executed in the order they appear in the file. [#]_ The names of the
152 subroutines are regular expressions to match the ``tag`` field in the
153 DOM_ structure.  The first subroutine in the phase whose regular
154 expression matches the ``tag`` field of the DOM object to be processed
155 is the one that is called, and is referred to as the handler for that
156 tag.  The handlers are called doing a post-order traversal of the
157 tree; in other words, once all of the children (members of the
158 ``content`` field) of a DOM object have had their handler called,
159 the DOM's own handler is called.  The arguments of the subroutine are:
161   ``$dom``:
162     A reference to the DOM object being processed.
163   ``$str``:
164     The concatenation of the strings returned by the handlers of all
165     the children of the DOM object being processed.
167 The subroutine needs to return a string that is the combined result of
168 processing all the layers from the DOM on down (assisted, of course,
169 by the ``$str`` argument).  The result returned by the subroutine gets
170 cached in the ``val`` field of the DOM object for future use, as well
171 as being propagated as part of the ``$str`` argument of the parent's
172 handler routine.
174 Options to the writer can be specified using a ``-W`` define, which has
175 the format ::
177   -W var[=val]
179 If no value is supplied, then the value defaults to 1.  Any such
180 defines become available to the writer directly in a variable ``$var``
181 which should be declared in a ``use vars qw($var)`` statement.
183 As an example, here is the code for the dom writer:
185 .. system:: perl -ne 'print if /^phase/ .. 0' .\./.\./blib/lib/Text/Restructured/Writer/dom.wrt
186    :literal:
188 This example is not typical, since it needs to call the internal
189 `Text::Restructured::Writer::ProcessDOMPhase`_ (via the writer object)
190 routine in order to process the DOM objects in the internal
191 ``.details`` field of the DOM; most writers should have no need to do
194 It is also up to the writer to provide the documentation that appears
195 when the user runs ``prest -h``.  Any comment in the writer appearing
196 in a POD (Perl's Plain-Old-Documentation) Description section is
197 printed for the writer's help.  For example, here is the help
198 documentation from the ``dom`` writer:
200 .. system:: perl -ne 'print if /^=pod/ .. /^=cut/' .\./.\./blib/lib/Text/Restructured/Writer/dom.wrt
201    :literal:
203 .. note::
205    The help text should parse correctly as reStructuredText, since it
206    is passed through prest to create the web documentation.
208 Footnotes
209 ---------
211 .. [#] If the same phase name is repeated later in the file, its
212    subroutine definitions are appended to those of the phase and
213    run at the earlier position.
215 .. include:: prest_internals.xref
219    Local Variables:
220    mode: indented-text
221    indent-tabs-mode: nil
222    sentence-end-double-space: t
223    fill-column: 70
224    End: