Over the last few years, Perl's POD format has proven itself as a useful tool for documenting Perl's functionality and its library modules. POD is easy to learn, easy to read and easy to embed.
In 1992, I wanted to embed documentation in source code in order to make it easier to keep the documentation up to date. POD didn't exist, so I invented a similar system called SDF (Simple Document Format) and implemented it in Perl, the world's greatest programming language. SDF has grown rapidly over the years and is now a powerful general purpose documentation system. But like POD, SDF has remained simple in spirit: easy to learn, easy to read and easy to embed.
In June 1997, most of POD's syntax and functionality were merged into SDF, making it easier for people to migrate from POD to SDF. This document aims to answer the following questions for POD users:
If you have other questions, check out the documentation provided with SDF. If that doesn't help, you can always email your question to sdf-users@mincom.com.
By using the
pod2sdf perlrun.pod > perlrun.sdf
As SDF is essentially a superset of POD, the SDF output is almost the same as the POD input, except that verbatim lines are marked with a leading >. For example, the following POD:
=head1 NAME abc - output the alphabet =head1 DESCRIPTION This program displays the alphabet like this: ABCDEFGHIJ KLMNOPQRST UVWXYZ Pretty simple, eh? |
gets converted to:
=head1 NAME abc - output the alphabet =head1 DESCRIPTION This program displays the alphabet like this: > ABCDEFGHIJ > KLMNOPQRST > UVWXYZ Pretty simple, eh? |
Note that it isn't actually necessary to use
sdf -2html perlrun.pod
How does this work? Well, the sdf program can be configured to automatically prefilter files with certain extensions. The default configuration is to prefilter .pod, .pm and .PL files with the pod filter (which converts POD to SDF).
If you want to use the sdf program on POD files without one of these extensions, you can either edit the sdf.ini configuration file, or explicitly specify the prefiltering like this:
sdf -2html -ppod xyz.pd
By using the sdf program. Typical usage is:
sdf -2pod mydoc.sdf
This will create a file called mydoc.pod in the current directory.
The general usage of the sdf program is:
sdf [options] filename ...
A .sdf extension is assumed on each filename (unless a filename without the extension is found).
If you're generally happy with POD and only need SDF occasionally, SDF can be embedded in POD using POD's =for command or =begin/=end command pair. Some examples are:
Here's our new logo: =for sdf !import "mylogo.gif" And these are the documentation systems we use: =begin sdf !block table Name Meaning POD Plain Old Documentation SDF Simple Document Format !endblock =end sdf
If you want the rest of a POD file to be in SDF, simply put in an "=begin sdf" - the closing "=end sdf" isn't necessary.
By using the pod filter. Filters can be applied to blocks of text in a file, complete files or the output of programs. Some examples are:
# Insert some pod !block pod =head2 My B<heading> A normal POD paragraph. And some verbatim text. !endblock # Get pod from a file !include "perlre.pod"; pod # Get pod from standard output !execute "getpod 'hello.c'"; pod
So reusing existing POD documentation within an SDF document is easy.
No. 90% of SDF documents use a set of core features which can be summarised in a few pages. For POD users, the main things to know are these:
style":" text
style"["attributes"]" text
A normal paragraph with a few lines. Note: This is a paragraph tagged with the Note style. Note[label='Important'] This is an important note!
Tag | Meaning |
* | bulleted list item |
- | 2nd-level bulleted list item |
. | plain list item/paragraph |
^ | first item in an ordered list |
+ | next item in an ordered list |
& | enumerated list item |
* item 1 - item 1a - item 1b * item 2 * item3
To its fans, SDF is more readable than POD for the following reasons:
Of course, POD's fans argue that POD is more readable for equally valid reasons. Beauty is in the eye of the beholder - even Lisp has it's fans. :-)
The main reasons for using SDF over POD are:
These are briefly considered below.
SDF support tables via the table filter. Typically, tables are defined using the block and endblock macros like this:
!block table Name Meaning POD Plain Old Documentation SDF Simple Document Format !endblock
The result is:
Name | Meaning |
POD | Plain Old Documentation |
SDF | Simple Document Format |
The first line specifies the headings and the input format of the data:
For readability reasons, fixed-width format is preferred. Delimited format is useful for tables already in that format and for data exported by spreadsheets.
SDF supports a large number of features for tables including:
See the SDF User Guide for further details.
Figures are supported in SDF via the import macro. The usage is:
!import "filename" [parameters]
For example:
!import "mylogo"; align=Right
It is generally best not to specify an extension for the filename containing the figure, as SDF will then use the best format it can find. The search rules are:
When generating | The search order is |
PostScript | epsi, eps, wmf, mif, gif |
HTML | jpeg, jpg, png, gif |
Windows Help | bmp |
See the SDF User Guide for further details.
Variables can be defined using the define macro like this:
!define VERSION 1.34
The first argument is the variable name and the second argument is the value. You can use a Perl expression for the value if you wish. For example:
!define LOGO $ENV{'LOGO'} || "mylogo"
Having defined a variable, it can be used in paragraph text by enclosing it within [[ and ]]. For example:
WorldPeace [[VERSION]] is just what you need and is available for free download from ...
In fact, a Perl expression can be embedded in paragraph text the same way, e.g.
!define STARS 5 ... This movie gets [['*' x $var{'STARS'}]].
Within Perl expressions, SDF variables are available via the %var associative array.
From its beginning, one of SDF's primary goals has been to support the authoring of documents in a logical manner. Therefore, it is possible to define your own:
and to either alias these to existing styles/attributes or map them to target format entities.
Likewise, you can define your own macros and filters to do almost anything you want. See the SDF Guru Guide for further details.
Typically, a workgroup or project team will put their extensions in an SDF library, which is essentially a normal SDF file which is included at the start of each document. Alternatively, you can specify a configuration library on the sdf command line. This is useful if you want an SDF configuration library for a POD document, say.
For L (Link) phrases, SDF lets you customise:
This flexibility is important for non-English documentation and non-Perl documentation.
To change the text expansion rules, define one of more of the variables below:
Variable | Default Value |
FORMAT_LINK_PAGE | the $page manpage |
FORMAT_LINK_PAGE_ENTRY | the $entry entry in the $page manpage |
FORMAT_LINK_PAGE_SECTION | the section on "$sect" in the $page manpage |
FORMAT_LINK_SECTION | the section on "$sect" |
For example:
!define FORMAT_LINK_SECTION 'the "$sect" section'
To change the URL generation rule, override the BuildLinkUrl subroutine like this:
!block script sub BuildLinkUrl { my ($page, $sect, $entry) = @_; my $url = ... return $url; } !endblock
The default implementation of BuildLinkUrl is simplistic by design. This is considered a feature. If you want intelligent URL generation ala pod2html, use the perl configuration library and set the PERL_HTML_ROOT variable like this:
sdf -2html -cperl -DPERL_HTML_ROOT=/nmanual/perl perlrun.pod
The default value of PERL_HTML_ROOT is /perl.
The most common complaints about SDF are:
On the WYSIWYG issue, SDF is a tool for people who would rather use a text editor. It tries hard to be readable and an emacs mode is available. If that isn't good enough, then SDF isn't for you.
On the output format issue, I'm working on it. For developers with a good knowledge of Perl and the output format they need, writing an "SDF output driver" isn't hard, it just takes time. Like all of us, I only have so much free time, so any assistance anyone can offer in this regard is very welcome.
On the functionality issue, SDF is growing and will continue growing. If it doesn't have a feature you need, the Perl source code is provided, so you might be able to add it yourself.
If SDF is already too complex, then stick with POD. You can always mix in some SDF or migrate to SDF if you need to at a later date. Personally, I find the "I'm sticking with POD because SDF is too complex" argument a little short-sighted:
I prefer SDF to POD for the same reason that I prefer Perl to awk: the latter may be sufficent for a given task, but choosing it will cause me grief the moment the task grows. On the other hand, as the designer of SDF, I'm probably just a little biased. :-)
Thanks to the many people who have used and contributed to SDF over the years, particularly David Cox, Tim Hudson and Chris Moran. Likewise, thanks to Larry Wall for inventing Perl and to everyone who has contributed to Perl over the years. Without it, SDF wouldn't exist.
Finally, I'd like to thank the people who encouraged me to merge POD and SDF, including Kenneth Albanowski, Brad Appleton, Achim Bohnet, Jim Esten, Chaim Frenkel, Gerd Knops, Hugues Lafarge, Tuomas J. Lukka, Andy Wardley and Peter Wolfe. I hope the result is useful.