It is often the case that you need to comment on lines of code to explain it. There are three mechanisms you can use for that purpose.
You can mix lineannotation
elements in with your code to explain something directly in the text. For example:
<programlisting># constructor sub new { my ($file, $output) = @_; <lineannotation>Store args</lineannotation> my $dir = basename $file; <lineannotation>Get dir name</lineannotation> } </programlisting>
Lineannotations in the stock stylesheet print as italic, but they inherit the monospace font family of the programlisting
. You may want them to appear in the italic version of the body font to make them stand out more. The following is such a customization for a print customization layer:
FO template customization:
<xsl:template match="lineannotation">
<fo:inline font-family="{$body.font.family}"
font-style="italic">
<xsl:call-template name="inline.charseq"/>
</fo:inline>
</xsl:template>
For HTML output, you can let the CSS stylesheet handle the formatting:
HTML CSS stylesheet:
span.lineannotation {
font-family: serif;
font-style: italic;
}
Line annotations cannot be added in files inserted using textobject
or <xi:include parse="text">
because the "<" character that starts the element will be escaped as <
when it is brought in. You can use lineannotations in files brought in with <xi:include parse="xml">
, but then you have to be careful to escape other XML characters in your program file. Line annotations also cannot be used with examples marked as CDATA, because any lineannotation
element won't be recognized as an XML element.
You can add line numbers to the listing, and then your paragraphs can refer to the line numbers. Currently line numbering is only available with the Java processors Saxon and Xalan, not xsltproc, because it is done with an extension function.
Line numbers are turned on by a linenumbering
attribute on each programlisting
element that needs line numbering. By default, the numbering starts at 1, but you can assign your own starting number with the optional startinglinenumber
attribute. You can also continue the numbering from the most recent programlisting
that had line numbering by adding a continuation="continues"
attribute to the current element. The following is an example with startinglinenumber
:
<programlisting linenumbering="numbered" startinglinenumber="12">
...
You have to enable the line numbering feature by setting a couple of stylesheet parameters. The parameters are use.extensions=1
and linenumbering.extension=1
. Both must be set for it to work.
Once your lines are numbered, you can refer to the line numbers in the paragraphs. The problem with line numbers, though, is you cannot see them until the text is formatted at least once. Also, if you edit the code, the line numbers may change and you will need to adjust your number references. It is useful for stable code examples, though.
The formatting of line numbers can be controlled using a set of line numbering parameters for all program listings (and screen
and cmdsynopsis
elements). You can also override the formatting for a single program listing using special processing instructions. The line numbering parameters are:
linenumbering.everyNth
By default, every 5th line of the programlisting displays its number, so the visible numbers are 5, 10, 15, etc. If you set this parameter to 3
, for example, then every third line shows its number. Setting it to 1
numbers all lines.
linenumbering.width
This is the number of spaces at the beginning of each line reserved for the line numbers. The default value is three, so numbers up to 999 will fit. You can set this parameter to a different integer to save fewer or more spaces for the line numbers. The numbers are right-aligned within this space so the digits line up properly.
linenumbering.separator
The literal content of this parameter is printed after the line number and before the program listing text. The default value is a single space, but it could be changed to any text.
To control the line number formatting for an individual program listing, you can use equivalent processing instructions. The processing instructions begin with <?dbhtml
for HTML output, or <?dbfo
for print output. The following is an example.
<programlisting linenumbering="numbered" ><?dbhtml linenumbering.everyNth="2" linenumbering.separator=" >" linenumbering.width="2" ?><?dbfo linenumbering.everyNth="2" linenumbering.separator=" >" linenumbering.width="2" ?><textobject><textdata fileref="mycode.c" /></textobject> </programlisting>
When processed, this particular program listing will have a number appearing on every other line, with two spaces allocated for the numbers, and with a literal >
character (>
) separating the number from the line of code.
You can use callouts to mark specific locations in a program listing and link explanatory text to the marks. To see how callouts look in output, see the example below. In DocBook, the callout
element contains the explanatory text. The mark, which is called a callout bug, is most easily placed using the co
element. Those two elements can be linked to each other to allow the reader to move back and forth between them.
The callout bug is usually rendered as a white number in a black circle. To see other options for rendering the callout bugs, see the section “Callout icons”.
The following is an annotated example of how callouts are written, using actual callouts to identify the important points.
<programlisting> #ifndef _My_Parser_h_ <co id="condition-co" linkends="condition" /> #define _My_Parser_h_ #include "MyFetch.h" <co id="headerfile-co" linkends="headerfile" /> class My_Parser <co id="classdef-co" linkends="classdef" /> { public: // // Construction/Destruction // My_Parser(); <coref linkend="classdef-co"/> virtual ~My_Parser() = 0; virtual int parse(MyFetch &fetcher) = 0; }; #endif </programlisting> <calloutlist> <callout arearefs="condition-co" id="condition" > <para>Make this conditional.</para> </callout> <callout arearefs="headerfile-co" id="headerfile"> <para>Load necessary constants.</para> </callout> <callout arearefs="classdef-co" id="classdef"> <para>Define new class</para> </callout> </calloutlist>
It helps to establish a naming scheme for the ids to track the two-ended links. This example uses the same name on both ends except the one on the co
element adds a -co
suffix. If you have to edit the code sample and move lines around, be sure to move any co
elements with them. Also, remember when cutting and pasting to not duplicate any id values, which will produce a validation error.
Can you put callouts on code imported from an external file? Yes, but it isn't easy, since you have to place the callout bugs by coordinates rather than literally in the code. This feature lets you use unmodified code files, though. Just don't try it with code samples that change with any frequency, because you will have to remap the coordinates.
You have to wrap your programlisting
and calloutlist
in a programlistingco
element, because it supports the use of an areaspec
to provide the coordinates. You also must use either Saxon or Xalan to process the files, because placing the callouts at the coordinates takes an XSLT extension function that is not available in xsltproc. To enable this function in Saxon or Xalan, you must set the stylesheet parameters use.extensions=1
and callouts.extension=1
. Both must be set for it to work. Don't forget
to
include the appropriate DocBook XSL extensions jar file in your CLASSPATH as well.
To place a callout bug, you use an area
element inside of a separate areaspec
element, instead of a co
element inside the code sample. Placing the bugs is the tedious part, because you must count lines and columns for each one.
You specify where the bug goes in the area
element's coords
attribute. Although the DTD allows you to specify a variety of units to use as coordinates, the DocBook XSL extension functions only support linecolumn
and linerange
unit types. The units
attribute can be specified in the areaspec
for all included area
s, or in each individual area
. If no units are specified, then linecolumn
is assumed. With linecolumn
, the coords
attribute specifies a line number and column number, separated by a space. If the second number is absent, then the value of the stylesheet parameter callout.defaultcolumn
is used, which is 60 by default. With linerange
, the two numbers specify beginning and ending line
numbers.
Here is an example that produces results like the previous one, but using an external file to hold the code sample. Note that the textobject
does not have a line break before it, which would throw off the line counting coordinates.
Example 26.2. programlistingco with areaspec
<programlistingco>
<areaspec units="linecolumn">
<area id="condition-co" linkends="condition" coords="1 23"/>
<area id="headerfile-co" linkends="headerfile" coords="3 23"/>
<area id="classdef-co" linkends="classdef" coords="4 18"/>
</areaspec>
<programlisting><textobject>
<textdata fileref="mycode.c" />
</textobject>
</programlisting>
<calloutlist>
<callout arearefs="condition-co" id="condition" >
<para>Make this conditional.</para>
</callout>
<callout arearefs="headerfile-co" id="headerfile">
<para>Load necessary constants.</para>
</callout>
<callout arearefs="classdef-co" id="classdef">
<para>Define new class</para>
</callout>
</calloutlist>
</programlistingco>
Here is an example command to process this file with Saxon:
CLASSPATH=../saxon653/saxon.jar:../docbook-xsl/extensions/saxon653.jar \ java com.icl.saxon.StyleSheet \ -o outputfile.html \ myfile.xml \ ../docbook-xsl/html/docbook.xsl \ use.extensions=1 \ callouts.extension=1 \ textinsert.extension=1
DocBook XSL: The Complete Guide - 3rd Edition | PDF version available | Copyright © 2002-2005 Sagehill Enterprises |