Documenting Plugins
After writing a plugin, you need to make sure other plugin writers can know about the functionality it provides, both to use it or to create alternative plugins which can be used in place of yours. This means documenting the plugin API.
This documentation is written as normal source code documentation, formatted for YARD and using the extensions included by Ruber (in the yard subdirectory of the gem).
The API documentation for a plugin is made of two main parts: the API documentation for the the feature the plugin provides and the API documentation for specific parts of the plugin (the plugin object, extensions objects and tool widgets). Most of the times, a plugin API only contains the feature API and the API for the plugin objects, since extensions and tool widgets are usually implementation details which other plugins don’t need to know.
The API documentation for the feature, together with a description of what the plugin does, should be written as documentation for the module or class which acts as namespace for the plugin (if the plugin doesn’t use a namespace, any class or module can be used for this, the use of a namespace is strongly suggested). Documentation for tool widgets and extensions should be written as normal source code documentation for the class which implements the tool widget or extension.
Although conceptually different, the feature API documentation and the documentation for the individual parts of the plugin are in practice quite similar. They all make use of the following YARD tags (the feature API documentation also uses the the plugin’s specification file to retrieve some information about the plugin).
Tags to document a plugin’s API
api
Tells YARD to write an API feature in the documentation. It takes two
or three parameters. The first two parameters are the kind of object the API is
for (feature
, extension
, tool_widget
) and the name Ruber uses to refer to
it (the internal name for features, the name for extension and the name or caption
for tool widgets, as in the PSF). The third parameter (which is everything after
the second one) is additional text to display.
If the first parameter is feature
, the presence of this tag also causes the PSF
to be read to look for information to be used with other tags. The PSF must be in
the same directory as the file where this tag is and be called plugin.yaml
.
Examples:
@api feature xxx
@api tool_widget abc extra description for tool widget abc
plugin
A description of the API for the plugin object. If no parameter is given, the class of the plugin object is read from the PSF and a line saying “See API for clsname” is inserted. If the tag contains some text, that text is used instead.
Usully, you don’t need to specify a parameter here, as any documentation should most likely go into the documentation of the plugin class itself. In special situations, however, it may be useful to write custom text here (note that no automatic text is inserted if the parameter is specified, so you should mention the plugin class by yourself)
Examples:
@plugin
@plugin some description
extension
An extension which plugins providing this feature must also provide. It can take
one or two argument. The first is the name of the extension, as in the PSF. The
second (not required) can be either a description of what the extension does
or a YAML hash (in the short form {key: value…\})which can contain the same
entries allowed for an extension entry
in the PSF plus an api
entry and a description
entry.
If the second argument is a hash, its contents will be merged with those contained in the corresponding entr in the PSF (with the hash in the documentation having the precedence on the one in the PSF).
The description
entry in the hash contains a general description of the extension
(just as if the second parameter hadn’t been a hash).
If the hash doesn’t contain an api
entry, then a line specifying the class to
look for for the extension API is inserted automatically (the class is read from
the class
entry of the hash or from the PSF). If the api
entry exists, then
its contents are used for the api
section.
The scope
, file_extension
and mimetype
entries, either in the hash or the
PSF are used to format messages saying to which kind of projects the extension
is applied.
If the entry corresponding to the extension in the PSF is an array, the text contains sections for the various cases. However, if the second parameter to the tag is a hash, then the PSF entry for the extension is completely ignored.
Examples
@extension xyz
@extension xyz a description of the extension
@extension xyz {api: some strange api, scope: global}
tool_widget
A tool widget which plugins providing this feature must also provide. Its syntax
is exactly that for the extension
tag.
Examples
@tool_widget xyz
@tool_widget xyz a description of the tool widget
@tool_widget xyz {api: some strange api, scope: global}
config_option
A global option which is part of the public API. It takes three arguments: the first two are the group and name of the option. The third is the type of its value (using the YARD syntax to specify types).
Examples
@config_option grp opt [String]
@config_option grp opt [String, nil]
@config_option grp opt [<Qt::Color>]
project_option
A project or document option which is part of the public API. It takes three or four
arguments: the first three are equal to the arguments of the config_option
tag,
while the last is as the last parameter of the extension
tag, except that the
api
and class
entries of the hash aren’t used
Examples
@project_option grp opt [String, nil] {scope: global}
@project_option grp opt [String, nil] {scope: document, file_extension: '*.rb'}
api_method
, api_signal
, api_slot
, api_class
, api_constant
Tags which specify that a given method, signal, slot, class or constant is part of the API. They all take a single argument, which is the name of the item. A link will be created (if the target is found) to that item.
These tags are the most common part of the API of plugin objects, extensions or tool widget, but should rarely appear in the API of the feature itself.
Note that, since you can’t create a class or constant which is part of the API in
the usual way but only using const_set
, the content of the @api_class
and
@api_constant
tags should specify both the internal constant and the name which
users of the api should use.
Examples
@api_method SomeClass#some_method
@api_signal SomeClass#some_signal
@api_slot SomeClass#some_slot
@api_constant SomeClass::InternalName SomeClass::SomeConstant