-
-
Notifications
You must be signed in to change notification settings - Fork 2
Embedded Document Formatting
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.
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.
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.
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.
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...
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.
...
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.
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()
.
Within the same document, use #Name()
to refer to any API function, class action or method. Use #Name
for field references.
Use ~Module.Function()
to refer to the function of an external module.
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.
Embedded backticks are supported for writing text with a monotype font. This is suitable for declaring code, constants, numeric values and so forth.
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.
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.