Skip to content

Embedded Document Formatting

Paul Manias edited this page Oct 3, 2024 · 2 revisions

This guide describes the formatting that we use to document Parasol's class and module functionality. By following the standard, it is possible to use our tools to not only produce documentation, but the header files that will allow languages to utilise your work.

A benefit of our approach is that you will be able to intersperse documentation throughout your code, targeting the areas where it is needed. It is not an issue if your code and documentation is split across multiple source files. The parsing tools can read everything from one folder if necessary.

Documentation can be written for a class-based API or a module-based API. The tools will not accept a mixture of both in one file, nor can two or more of either type be processed in one session.

The type of documentation that you are writing is determined by the first 'mark', which must be either a -MODULE- or -CLASS- mark. This is followed by the API's name and a short description. The full introduction to the API can then follow as a series of paragraphs.

Here's an example header for the Config class:

-CLASS-
Config: Manages the reading and writing of configuration files.

The Config class is provided for reading text based key-values in a simple structured format.

...

-END-

The documentation tools will consume as much recognisable paragraph content as possible until the next marker is reached, in this case -END-. Terminating the introduction with an -END- marker is recommended so that the parser doesn't consume unintended content.

Documenting Functions

Standard module interfaces will typically export one or more public functions. Documenting a function is achieved as follows:

-FUNCTION-
[name]:   A short description of the function's purpose.
Category: Optional category name
Status:   Can be set to 'Internal' if the function is not to appear in official documentation.

...Long description follows...

If a function accepts input, an -INPUT- marker is defined that is followed by each parameter in their correct order. The type of each parameter must be specified with the name. Here's an example:

-INPUT-
double XCoord: Defines horizontal placement.
double YCoord: Defines vertical placement.

Types

The following table lists the base types that are recognised for declaring input and results:

Type C Type Description
array(Type) Type [] An array of Type. Must be followed by arraysize.
arraysize LONG Specifies the size of the preceding array.
buf(Type) Type * Pointer to a buffer of Type. Must be followed by a bufsize or structsize in the next parameter.
bufsize LONG Parameter specifies the byte-size of the preceding buffer.
char char 8 bit value.
cid CLASSID Class UID.
cptr const void * Pointer to untyped const data.
cstr CSTRING Pointer to an immutable C-style character string.
double DOUBLE 64 bit floating point value.
eid EVENTID Event UID.
error ERROR Error value.
ext OBJECTPTR Pointer to an object.
fid FIELD Field UID
flags LONG 32 bit int representing bit flags.
float FLOAT 32 bit floating point value.
func FUNCTION Callback function.
fptr(Synopsis) APTR C function pointer. The Synopsis must start by declaring the result value (which can be void) followed by the input parameters, if any.
hhandle HANDLE A host-specific resource handle. Could be an int or pointer, and has meaning to the host operating system only.
int LONG 32 bit value.
int(Ref) LONG 32 bit value referring to a named type
large LARGE 64 bit value.
maxint LONG (32) / LARGE (64) 32 or 64 bit value depending on target CPU.
mem MEMORYID Memory UID.
obj OBJECTPTR Pointer to an object.
oid OBJECTID Object UID.
ptr APTR Pointer to an untyped data buffer.
ptr(Type) APTR Pointer to a typed resource, where Type is one of those in this table.
resource APTR Reference to a system resource.
short WORD 16 bit value.
str STRING Pointer to a C-style character string.
struct(Name) Name Reference to a struct identified by Name.
struct(*Name) Name * A pointer referring to a struct identified by Name.
structsize LONG Byte-size of the preceding struct reference.
uchar UBYTE Unsigned 8 bit value.
uint ULONG Unsigned 32 bit value.
ushort UWORD Unsigned 16 bit value.
void void Untyped

Further to the above, if a typed parameter is a pointer that receives a result, prefix the type with &. For instance, the C type LONG * can be represented as &int. If the result is an allocated resource pointer that can be terminated with FreeResource(), use ! instead of &. This will allow the resource to be terminated by Fluid so that it cannot be leaked.

Results

If the function returns an ERR code, you are expected to list the returnable codes in a -RESULT- section as in the following example:

-RESULT-
Okay:
AllocMemory:      Reason(s) for memory failure.
InvalidDimension: Reason(s) why dimension values can fail checks.

It is not an absolute requirement that a reason is given for each code. When no reason is specified, a default explanation for that error code will be provided.

In all other cases, the result can be specified in the form of this example with a declaration of the correct type:

-RESULT-
int: Description of what the int value represents.

Class Fields

When documenting a class, all fields declared in the class blueprint must be documented. The template for each field is as follows:

-FIELD-
[name]: A short description of the field's purpose.
Lookup: Can refer to a named const type declared in the API's FDL.
Private: If true, the field will not appear in generated documentation.

...Long description follows...

Class Methods and Actions

All methods and actions declared by a class will need to be documented. The template for both is largely similar, except that actions do not require an -INPUT- section:

-METHOD|ACTION-
[name]: A short description of the provided functionality.

...Long description follows...

-INPUT-
type Name: Description of input value.
...

-RESULT-
ErrorCode: Optional description of error code.
...

Markup Features

There are a number of markup features available when writing long descriptions, and these can be used to enhance the experience for the reader. This section documents these features in detail.

Links

Referencing Classes

Use @ClassName to refer to another class. For example, @VectorRectangle will generate the word VectorRectangle and provide a hyperlink that takes the user directly to the class document. Indexing is possible by appending a . suffix with the name of a supported field, action or method. For instance, @VectorRectangle.RX or @VectorRectangle.Init().

Internal References

Within the same document, use #Name() to refer to any API function, class action or method. Use #Name for field references.

External Function References

Use ~Module.Function() to refer to the function of an external module.

Constant References

Use &Name to link to constants and struct definitions declared in the module's FDL file.

There is a special usage in which &Name can be declared on a single line with no other content. This results in the entire definition being pulled into the document and represented in a table.

Backticks

Embedded backticks are supported for writing text with a monotype font. This is suitable for declaring code, constants, numeric values and so forth.

Code

To write multiple lines of preformatted code, use <pre> on one line, follow this with the code, then end with </pre> on its own line.


Document Processing Tools

The primary tool that we use to produce user documentation is bundled with Parasol as idl-doc.fluid and can be found in the scripts\dev\idl\ folder.

Despite it being written as a script, idl-doc is not a stand-alone tool and is instead implemented as an extension of idl-c.fluid. This is because the generation of fully accurate documentation requires inspection of the module's FDL file, as well as the compiled code.

For generating your documentation, please refer to both idl-c and the FDL Reference Manual.