EDoc is the Erlang program documentation generator. Inspired by the Javadoc(TM) tool for the Java(TM) programming language, EDoc is adapted to the conventions of the Erlang world, and has several features not found in Javadoc.
EDoc lets you write the documentation of an Erlang program as
comments in the source code itself, using tags on the form
"@Name ...
". A source file does not have to contain tags
for EDoc to generate its documentation, but without tags the result will
only contain the basic available information that can be extracted from
the module.
A tag must be the first thing on a comment line, except for leading
'%
' characters and whitespace. The comment must be between
program declarations, and not on the same line as any program text. All
the following text - including consecutive comment lines - up until the
end of the comment or the next tagged line, is taken as the
content of the tag.
Tags are associated with the nearest following program construct "of significance" (the module name declaration and function definitions). Other constructs are ignored; e.g., in:
%% @doc Prints the value X. -record(foo, {x, y, z}). print(X) -> ...
the @doc
tag is associated with the function print/1
.
Note that in a comment such as:
% % @doc ...
the tag is ignored, because only the first '%
' character is
considered "leading". This allows tags to be "commented out".
Some tags, such as @type
, do not need to be associated
with any program construct. These may be placed at the end of the file,
in the "footer".
The following are the main functions for running EDoc:
Note that the function edoc:file/2 belongs to the old, deprecated interface (from EDoc version 0.1), and should not be used.
When documentation is generated for an entire application, an overview
page, or "front page", is generated. (The page you are now reading is an
overview page.) This should contain the high-level description or user
manual for the application, leaving the finer details to the
documentation for individual modules. By default, the overview page is
generated from the file overview.edoc
in the target directory
(typically, this is the doc
subdirectory of the application
directory); see edoc_doclet for details.
The format of the overview file is the same as for EDoc documentation
comments (see Introduction), except that the lines do not
have leading '%
' characters. Furthermore, all lines before the first
tag line are ignored, and can be used as a comment. All tags in the
overview file, such as @doc
, @version
, etc., refer to the
application as a whole; see Overview tags for details.
Here is an example of the contents of an overview file:
** this is the overview.doc file for the application 'frob' ** @author R. J. Hacker <rjh@acme.com> @copyright 2007 R. J. Hacker @version 1.0.0 @title Welcome to the `frob' application! @doc `frob' is a highly advanced frobnicator with low latency, ...
The following tags can be used anywhere within a module:
@clear
@clear
tag itself. The text following the tag
is also ignored. This is typically only useful in code
containing conditional compilation, when preprocessing is turned
on. (Preprocessing is turned off by default.) E.g., in-ifdef(DEBUG). %% @doc ... foo(...) -> ... -endif. %% @clear %% @doc ... bar(...) -> ...the
@clear
tag makes sure that EDoc does not see
two @doc
tags before the function bar
,
even if the code for function foo
is removed by
preprocessing. (There is no way for EDoc to see what the first
@doc
tag "really" belongs to, since preprocessing
strips away all such information.)@docfile
@docfile
tag. The content is the name of the file to be
read; leading and trailing whitespace is ignored. See also @headerfile.@end
%% ---------------------------------- %% ... %% @doc ... %% ... %% @end %% ----------------------------------to avoid including the last "ruler" line in the
@doc
tag.@headerfile
.hrl
). If the file turns
out to contain one or more function definitions or a module
declaration, all tags that occur above the last such definition or
module declaration are ignored, and EDoc will print a
warning. This tag allows you to write documentation in a header
file and insert it at a specific place in the documentation, even
if the header file is used (i.e., included) by several
modules. The includes
option can be used to specify a search
path (see edoc:read_source/2).@todo
(or @TODO
)
%% @TODO Finish writing the documentation.or
%% @todo Implement <a href="http://www.ietf.org/rfc/rfc2549.txt">RFC 2549</a>.These tags can also be written as "
TODO:
", e.g.:%% TODO: call your mothersee Wiki notation for more information. To-Do notes are normally not shown unless the
todo
option is turned on (see
edoc:get_doc/2).@type
.
') separator and XHTML
text describing the type (i.e., its purpose, use, etc.). There
must be at least one whitespace character between the '.
' and
the text. See Type specifications for syntax and
examples.
All data type descriptions are placed in a separate section of
the documentation, regardless of where the tags occur.The following tags can be used in an overview file.
@author
@copyright
@doc
@reference
@see
@since
@title
@version
The following tags can be used before a module declaration:
@author
<...>
delimiters, and a URI within [...]
delimiters. Both e-mail and
URI are optional, and any surrounding whitespace is stripped from
all strings.<...>
or [...]
, and does not contain only whitespace. (In other words,
the name can come before, between, or after the e-mail and URI,
but cannot be split up; any sections after the first are ignored.)
If an e-mail address is given, but no name, the e-mail string will
be used also for the name. If no <...>
section is present, but
the name string contains an '@
' character, it is assumed to be
an e-mail address. Not both name and e-mail may be left out.%% @author Richard Carlsson
%% @author Richard Carlsson <richardc@it.uu.se> %% [http://user.it.uu.se/~richardc/]
%% @author <richardc@it.uu.se>
%% @author richardc@it.uu.se [http://user.it.uu.se/~richardc/]
@copyright
%% @copyright 2001-2003 Richard Carlsson
@deprecated
{@link}
reference to a
replacement; as in:%% @deprecated Please use the module {@link foo} instead.
@doc
%% @doc This is a <em>very</em> useful module. It is ...
@hidden
@private
@reference
%% @reference Pratchett, T., <em>Interesting Times</em>, %% Victor Gollancz Ltd, 1994.
%% @reference See <a href="www.google.com">Google</a> for %% more information.
@see
@since
@version
The following tags can be used before a function definition:
@deprecated
@doc
.
') or exclamation mark
('!
') that is followed by a whitespace character, a
line break, or the end of the tag text, and is not within XML
markup. (As an exception, the first sentence may be within an
initial paragraph element)@equiv
@doc
. @hidden
@private
spawn
. (Non-exported functions are
always "private".) The content can be used as a comment; it is
ignored by EDoc.@see
.
'), one or more whitespace characters, and
XHTML text to be used for the label; for example "@see edoc
" or
"@see edoc. <b>EDoc</b>
". If no label text is specified, the
reference itself is used as the label.@since
@spec
@throws
erlang:throw(Term)
. The content is a type expression (see Type specifications), and can be a union type.exit
(as caused by calls to
erlang:exit(Term)
) and error
(run-time errors such as badarg
or badarith
) are not viewed as part of the normal interface of
the function, and cannot be documented with the @throws
tag.
@type
@type
tag by a function
definition may be convenient, but does not affect where the
description is placed in the generated documentation.
In several contexts (@see
tags, @link
macros, etc.), EDoc lets
you refer to the generated documentation for modules, functions,
datatypes, and applications, using a simple and compact syntax. The
possible formats for references are:
Reference syntax | Example | Scope |
Module
|
edoc_run, erl.lang.list
|
Global |
Package.*
|
erl.lang.*
|
Global |
Function/Arity
|
file/2
|
Within module |
Module:Function/Arity
|
edoc:application/2 | Global |
Type()
|
filename()
|
Within module |
Module:Type()
|
edoc:edoc_module() | Global |
//Application
|
edoc | Global |
//Application/Module
|
edoc_doclet(3) | Global |
//Application/Module:Function/Arity
|
edoc_run:file/1 | Global |
//Application/Module:Type()
|
edoc:edoc_module() | Global |
EDoc will resolve references using the information it finds in
edoc-info
-files at the locations specified with the doc_path
option. EDoc will automatically (and somewhat intelligently) try to find
any local edoc-info
-files using the current code path, and add them to
the end of the doc_path
list. The target doc-directory is also
searched for an existing info file; this allows documentation to be
built incrementally. (Use the new
option to ignore any old info
file.)
Note that if the name of a module, function or datatype is explicitly
qualified with an application (as in "//edoc/edoc_run
"), this
overrides any other information about that name, and the reference will
be made relative to the location of the application (if it can be
found). This makes it possible to refer to e.g. a module "fred
" as
"//foo/fred
" without accidentally getting a reference to
"//bar/fred
". You should not use this form of explicit references for
names that are local to the application you are currently creating -
they will always be resolved correctly.
Note that module-local references such as file/2
only work properly
within a module. In an overview-page like this (i.e., the one you are
currently reading), no module context is available.
In several places, XHTML markup can be used in the documentation
text, in particular in @doc
tags. The main differences from
HTML are the following:
<li>
tag without also writing a corresponding </li>
tag in the right place. This could be an annoyance
at times, but has the great advantage that EDoc can report all
malformed XHTML in your source code, rather than propagate the
errors to the generated documentation.<a
name="top">
.To write an element like the HTML <br>
, which has no actual content,
you can write either the full <br></br>
, or better, use the XHTML
abbreviated form <br/>
.
Since the purpose of EDoc is to document programs, there is also a limited form of "wiki"-syntax available for making program code easier to write inline (and to make the doc-comments easier to read). See Wiki notation for details.
The HTML heading tags h1
and h2
are reserved for use by EDoc.
Headings in documentation source code should start at h3
. There is
however a special syntax for writing headings which avoids using
specific level numbers altogether; see Headings for details.
EDoc uses XMerL to parse and export XML markup.
When EDoc parses XHTML, it does additional pre- and post-processing of the text in order to expand certain notation specific to EDoc into proper XHTML markup. This "wiki" (http://en.wikipedia.org/wiki/Wiki) notation is intended to make it easier to write source code documentation.
Leaving an empty line in XHTML text (i.e., a line which except for
any leading start-of-comment '%
' characters contains only
whitespace), will make EDoc split the text before and
after the empty line into separate paragraphs. For example:
%% @doc This will all be part of the first paragraph. %% It can stretch over several lines and contain <em>any %% XHTML markup</em>. %% %% This is the second paragraph. The above line is %% regarded as "empty" by EDoc, even though it ends with %% a space.
will generate the following text:
This will all be part of the first paragraph. It can stretch over several lines and contain any XHTML markup.
This is the second paragraph. The above line is regarded as "empty" by EDoc, even though it ends with a space.
Paragraph splitting takes place after the actual XHTML parsing. It only
affects block-level text, and not e.g., text within <pre>
markup, or
text that is already within <p>
markup.
Section headings, sub-headings, and sub-sub-headings, can be written using the following notation:
== Heading == === Sub-heading === ==== Sub-sub-heading ====
Such a heading must be alone on a line, except for whitespace, and cannot be split over several lines. A link target is automatically created for the heading, by replacing any whitespace within the text by a single underscore character. E.g.,
== Concerning Hobbits ==
is equivalent to
<h3><a name="Concerning_Hobbits">Concerning Hobbits</a></h3>
Thus, headings using this notation should not contain characters that may not be part of URL labels, except for whitespace. If you need to create such headings, you have to use the explicit XHTML markup.
A hypertext link to a heading written this way can be created using the
@section
macro, which transforms the argument text into a label as
described above. E.g.,
{@section Concerning Hobbits}
is eqivalent to writing
<a href="#Concerning_Hobbits">Concerning Hobbits</a>
The above expansions take place before XML parsing.
Writing a URL within brackets, as in "[http://www.w3c.org/]
", will
generate a hyperlink such as http://www.w3c.org/, using the URL both
for the destination and the label of the reference, equivalent to writing
"<a href="http://www.w3c.org/"><tt>http://www.w3c.org/</tt></a>
". This
short-hand keeps external URL references short and readable. The
recognized protocols are http
, ftp
, and file
. This expansion takes
place before XML parsing.
Lines that begin with the text "TODO:
" (the colon is required) are
recognized as tags, as if they had been written as "@todo ...
" (see @todo tags for further details).
In XHTML text, the '`
' character (Unicode 000060
,
known as "grave accent" or "back-quote") can be used for verbatim
quoting. This expansion takes place before XML parsing.
`...'
" or
"``...''
" will be expanded to
"<code>...</code>
", where all occurrences of the special XML
characters '<
' and '&
' (and for completeness, also '>
') in
the quoted text have been escaped to "<
", "&
", and
">
", respectively.
All whitespace is stripped from the beginning and end of the
quoted text.``...''
" can be used
to quote text containing single ''
' characters. The automatic
stripping of any surrounding whitespace makes it possible to write
things like "`` 'foo@bar' ''
".''
" verbatim,
explicit <code>
markup or similar must be used.
```...'''
"
will be expanded to "<pre><![CDATA[...]]></pre>
", which disables
all XML markup within the quoted text, and displays the result in
fixed-font with preserved indentation. Whitespace is stripped from
the end of the quoted text, but not from the beginning, except for
whole leading lines of whitespace. This is
useful for multi-line code examples, or displayed
one-liners.`
'-character in XML
without beginning a new quote, you can write "`'
"
(no space between the '`
' and the ''
').
You can of course also use the XML character entity
"`
".Examples:
%% @doc ...where the variable `Foo' refers to...
%% @doc ...returns the atom `` 'foo@erlang.org' ''...
%% @doc ...use the command ```erl -name foo''' to...
%% @doc ...as in the following code: %% ```f(X) -> %% case X of %% ... %% end'''
%% @doc ...or in the following: %% ``` %% g(X) -> %% fun () -> ... end %% '''
Before the content of a tag is parsed, the text undergoes macro expansion. The syntax for macro calls is:
{@name}
or
{@name argument}
where name and argument are separated by one or more
whitespace characters. The argument can be any text, which may contain
other macro calls. The number of non-escaped "{@
" and
"}
" delimiters must be balanced.
The argument text is first expanded in the current environment, and
the result is bound to the macro parameter, written
{@?}
. (If no argument is given, {@?}
is
bound to the empty string.) The macro definition is then substituted
for the call, and expansion continues over the resulting text. Recursive
macro expansions are not allowed.
Users can define their own macros by using the def
EDoc
option; see edoc:file/2 and edoc:get_doc/2 for more
information. User-defined macros override predefined macros.
{@date}
Month Day Year
",
e.g. "Jun 12 2007".{@docRoot}
"../../.."
) from the current page to the root
directory of the generated documentation. This can be used to
create XHTML references such as <img
src="{@docRoot}/images/logo.jpeg">
that are independent of how
deep down in a package structure they occur. If packages are not
used (i.e., if all modules are in the "empty" package),
{@docRoot}
will always resolve to the empty
string.{@link reference.
description}
{@link edoc:file/2}
creates the
link edoc:file/2, and {@link edoc:file/2. <em>this link</em>}
creates this link.{@module}
{@package}
{@section
heading}
{@time}
Hr:Min:Sec
",
e.g. "11:58:07".{@type
type-expression}
<code>...</code>
markup and with hypertext links for data types. For example,
{@type {options, List::edoc:option_list()@}}
generates "{options, List::edoc:option_list()}
". (Cf.
Escape sequences.){@version}
{@date}
and {@time}
.
Typically, this macro is redefined by the user when an official
release of the application is generated.
To prevent certain characters from being interpreted as delimiters,
for example to produce the text "{@
" in the output, or use a
'}
' character in the argument text of a macro call, the
following escape sequences may be used:
@{
{
". Example:%% @doc A macro call starts with the sequence "@{@".
@}
}
". Example:%% @doc ...{@foo ...{Key, Value@}...}...
@@
@
". Example:%% @doc Contact us at support@@{@hostname}Will generate the text "Contact us at support@vaporware.acme.com" if the macro
hostname
is bound to
"vaporware.acme.com
". Also:%% @doc You might want to write something like %% @@foo that will expand to @foo and does not start %% a new tag even if it appears first in a line.
The following grammar describes the form of the specifications following
a @spec
tag. A '?
' suffix implies that the element is optional.
Function types have higher precedence than union types; e.g., "(atom())
-> atom() | integer()
" is parsed as ((atom()) -> atom()) | integer()
,
not as (atom()) -> (atom() | integer())
.
Spec
::=
FunType "where"? DefList?
| FunctionName FunType "where"? DefList?
FunctionName
::=
Atom
FunType
::=
"(" UnionTypes? ")" "->" UnionType
UnionTypes
::=
UnionType
| UnionType "," UnionTypes
UnionType
::=
UnionList
| Name "::" UnionList
Name
::=
Variable
UnionList
::=
Type
| Type "+" UnionList
| Type "|" UnionList
Type
::=
TypeVariable
| Atom
| Integer
| Float
| FunType
| "{" UnionTypes? "}"
| "[" "]"
| "[" UnionType "]"
| "(" UnionType ")"
| TypeName "(" UnionTypes? ")"
| ModuleName ":" TypeName "(" UnionTypes? ")"
| "//" AppName "/" ModuleName ":" TypeName "(" UnionTypes? ")"
TypeVariable
::=
Variable
TypeName
::=
Atom
ModuleName
::=
Atom
| ModuleName "." Atom
AppName
::=
Atom
DefList
::=
Def
| DefList Def
| DefList "," Def
Def
::=
TypeVariable "=" UnionType
| TypeName "(" TypeVariables? ")" "=" UnionType
TypeVariables
::=
TypeVariable
| TypeVariable "," TypeVariables
Examples:
%% @spec my_function(X::integer()) -> integer()
%% @spec (X::integer()) -> integer()
%% @spec sqrt(float()) -> float()
%% @spec pair(S, T) -> {S, T}
%% @spec append(List, List) -> List %% List = [term()]
%% @spec append(A::List, B::List) -> List %% List = [Item] %% Item = term()
%% @spec open(File::filename()) -> FileDescriptor %% where %% filename() = string() + atom(), %% FileDescriptor = term()
%% @spec close(graphics:window()) -> ok
In the above examples, X
, A
, B
,
and File
are parameter names, used for referring to the
parameters from the documentation text. The type variables
S
, T
and List
are used to
simplify the type specifications, and may be supplied with
definitions. It is also possible to give definitions for named types,
which means that the name is simply an alias. (Use the
@type
tag to document abstract data types.) If a named type
is defined in another module, it can be referred to as
Module:TypeName(...)
. Note that the keyword 'where
' is optional
before a list of definitions, and that the definitions in the list may
optionally be separated by ',
'.
Both the '|
' and the '+
' character may be
used to separate alternatives in union types; there is no semantic
difference. Note that the notation [Type]
means "proper
(nil-terminated) list whose elements all belong to Type
";
For example, [atom()|integer()]
means the same thing as
[atom()+integer()]
, i.e., a proper list of atoms and/or
integers.
If only a type variable is given for a parameter, as in
"pair(S, T) -> ...
", the same variable name may implicitly
be used as the parameter name; there is no need to write
"pair(S::S, T::T) -> ...
".
EDoc automatically extracts possible parameter names from the source
code, to be used if no parameter name is given in the specification (or
if the specification is missing altogether). If this fails, EDoc will
generate a dummy parameter name, such as X1
. This way, EDoc
can often produce helpful documentation even for code that does not
contain any annotations at all.
The following grammar (see above for auxiliary definitions) describes
the form of the definitions that may follow a @type
tag:
Typedef
::=
TypeName "(" TypeVariables? ")" DefList?
| TypeName "(" TypeVariables? ")" "=" UnionType DefList?
(For a truly abstract data type, no equivalence is specified.) The main definition may be followed by additional local definitions. Examples:
%% @type myList(X). A special kind of lists ...
%% @type filename() = string(). Atoms not allowed!
%% @type thing(A) = {thong, A} %% A = term(). %% A kind of wrapper type thingy.
The following data types are predefined by EDoc, and may not be redefined:
any() atom() binary() bool() char() cons() deep_string() float() function() integer() list() nil() none() number() pid() port() reference() string() term() tuple()
Details:
any()
means "any Erlang data type".
term()
is simply an alias for any()
.atom()
, binary()
,
float()
, function()
,
integer()
, pid()
, port()
and reference()
are primitive data types of
the Erlang programming language.bool()
is the subset of atom()
consisting
of the atoms true
and false
.char()
is a subset of
integer()
representing character codes.tuple()
is the set of all tuples {...}
.list(T)
is just an alias for [T]
.nil()
is an alias for the empty list []
.cons(H,T)
is the list constructor. This is usually not
used directly. It is possible to recursively define list(T)
:= nil()+cons(T,list(T))
.string()
is an alias for [char()]
.deep_string()
is recursively defined as
[char()+deep_string()]
.none()
means "no data type". E.g., a function
that never returns has type (...) -> none()
Since the first version of EDoc, several people have come up with suggestions (Luke Gorrie, Joe Armstrong, Erik Stenman, Sean Hinde, Ulf Wiger, ...), and some have even submitted code to demonstrate their ideas (Vlad Dumitrescu, Johan Blom, Vijay Hirani, ...). None of that code was actually included in the Great Rewriting that followed the initial public release (EDoc version 0.1), but most of the central points were addressed in the new system, such as better modularization and possibility to plug in different layout engines, and making EDoc understand the application directory layout.
It is now getting too hard to keep track of all the people who have made further suggestions or submitted bug reports, but your input is always appreciated. Thank you.