Now it's time to start documenting your code. Natural Docs tries to make this very straightforward and painless so let's just dive right in:
// Function: Multiply
// Multiplies two integers and returns the result.
int Multiply (int x, int y)
{ return x * y; }
That's all you need. Run Natural Docs and this is what will appear in the output:
You can make each comment as simple or as detailed as you want. Here's a more elaborate one. This is obviously overkill for this function but it's just a demonstration:
/* Function: Multiply
Multiplies two integers.
Parameters:
x - The first integer.
y - The second integer.
Returns:
The two integers multiplied together.
See Also:
<Divide>
*/
int Multiply (int x, int y)
{ return x * y; }
int Multiply ( |
| ) |
Multiplies two integers.
x int | The first integer. |
y int | The second integer. |
The two integers multiplied together.
Still not too scary, right? The comments are just as readable as the output. No tags littered about, and the structure is very natural. You probably get it just by looking at it, but let's go through each piece anyway.
Function: Multiply
Every one of these comments you write are going to start with a line in the format "keyword: title". There are a lot of keywords, but they're exactly what you'd expect: Function, Class, Variable, etc. There are also a lot of synonyms and abbreviations so instead of Function you could use Func, Procedure, Method, etc. It's designed so you can just use whatever it is you're describing without memorizing anything. You can look over the keyword list but you shouldn't have to consult it very often.
The other part of the line is the title. It should match whatever it is you're documenting, in this case the function name Multiply. Natural Docs is case sensitive even if your programming language isn't, so make sure you match it exactly or you might not get the prototype in your output, which is the little gray box that shows the function declaration. You don't need to include the parameters in the title. In fact, it's better if you don't.
You don't have to use any special comment symbols like /**. The only important thing is that it starts with a "keyword: title" line.
Parameters:
Returns:
See Also:
You can also define headings by skipping a line and ending the text with a colon. If you're used to other documentation systems you may think there's only a handful of headings to choose from, but any text formatted this way will become one. If you want a heading called Dependencies you can go right ahead and add it. Just note that it needs to be in title-case, meaning most words are capitalized like the title of a book.
x - The first integer.
y - The second integer.
This is what's called a definition list. You can use more than one line to finish the definition, as it won't stop until you skip a line.
x - The first integer.
y - The second integer with a long description.
This is still part of the description.
This is a new paragraph because we skipped a line
and didn't indent.
The second line doesn't have to be indented all the way to match the first, but it should be indented at least two spaces.
<Divide>
This is how we link in Natural Docs, with angle brackets. There will be more to say about this later, but for now I'll just show you something cool. Hold the mouse over it in the output below:
You get that everywhere in your generated documentation.
So that's good for our one function of questionable usefulness, but what if we have a whole class of questionable usefulness? We can document the class and its members the same way we documented the individual function, with a Natural Docs comment right above each element. We'll go back to short descriptions to keep the example manageable.
// Class: Counter
// A class that manages an incrementing counter.
public class Counter
{
// Constructor: Counter
// Initializes the object.
public Counter ()
{ value = 0; }
// Function: Increment
// Adds one to the counter.
public void Increment ()
{ value++; }
// Property: Value
// Returns the value of the counter.
public int Value
{
get
{ return value; }
}
// Variable: value
// The value of the counter.
private int value;
}
Everything's the same, we just substituted Class, Property, and Variable for the Function keyword when it was appropriate. We also used Constructor, but we could have just as easily used Function there too. They're both keywords for the same thing so it doesn't matter.
Like the source code itself, Natural Docs comments have scope. Value and Increment are seen as part of class Counter, just like they are in the code. Why is this important? Linking. Linking from one comment to another has similar rules to how one function can call another. Since Value is in the same class as Increment, its comment can link to it with just <Increment>. However, linking to Increment from a different class would require <Counter.Increment> instead. You can actually use any of the three most common class/member notations: <Counter.Increment>, <Counter::Increment>, and <Counter->Increment>.
If your programming language has full language support, the scope is determined by the code and applied automatically. However, if you only have basic language support it follows these rules:
Any comment that appears after a Class comment (or anything that says Starts Scope) is part of that class.
Any comment that appears after a Section comment (or anything that says Ends Scope) is global again.
Any File comment (or anything that says Always Global) is global no matter what and doesn't affect any other comments.
Chances are you would have written the same thing even if you didn't know about this and it would have just worked. You usually won't need to think about it at all. However, it's still good to be aware of these rules in case something doesn't behave the way you expected it to. The full reference goes into more detail.
You actually know enough to go start documenting now. There's more you can learn, but those are the essentials.
The syntax for these is pretty straightforward:
*Bold text*
_Underlined text_
Paragraphs are broken by skipping lines. So the two
lines above each have their own paragraph, but these
three lines are all part of the same one.
Bold text
Underlined text
Paragraphs are broken by skipping lines. So the two lines above each have their own paragraph, but these three lines are all part of the same one.
When underlining multiple words you can use an underscore for each space or only put them at the edges like we did above. Both ways will work.
You can add bullet lists by starting a line with a dash or an asterisk. The content can span multiple lines so to end it you have to skip a line.
- Bullet one.
- Bullet two.
Bullet two continued.
- Bullet three.
Some text after the bullet list.
Bullet one.
Bullet two. Bullet two continued.
Bullet three.
Some text after the bullet list.
You can have multiple levels as long as each one is indented at least two spaces more than the previous one. You can also have multiple paragraphs in a single bullet as long as they're indented at least two spaces from it.
* Level one.
* Level two, first paragraph.
Level two, first paragraph continued.
Level two, second paragraph.
* Level three.
Level one.
Level two, first paragraph. Level two, first paragraph continued.
Level two, second paragraph.
Level three.
Definition lists are lines in the format "item - definition". Like bullet lists they continue until you skip a line and you can have multiple paragraphs in the definition if they're indented.
Item 1 - The first paragraph.
The first paragraph continued.
The second paragraph
Item 2 - The first paragraph.
The first paragraph continued.
The second paragraph.
Some text after the definition list.
Item 1 | The first paragraph. The first paragraph continued. The second paragraph |
Item 2 | The first paragraph. The first paragraph continued. The second paragraph. |
Some text after the definition list.
If you're documenting a function and put a definition list under a heading called Parameters (or Params, Arguments, etc.) Natural Docs will automatically look up each one in the prototype and include their types in the list.
/* Function: MyFunction
*
* Parameters:
*
* x - Description of x.
* y - Description of y.
* z - Description of z.
*/
void MyFunction (int x, string y, Counter z)
{ ... }
x int | Description of x. |
y string | Description of y. |
z | Description of z. |
If the type is something documented like Counter it will also serve as a link to its definition and have a pop-up summary when you hold the mouse over it.
To add a section of code, start a line with at least three dashes, equals signs, or underscores followed by "Code". It will continue until there's another line of at least three of the same symbols.
This is a normal paragraph.
--- Code
int x = 12;
int y = 0;
---
This is a normal paragraph.
This is a normal paragraph.
int x = 12;
int y = 0;
This is a normal paragraph.
You can use more than three characters if you want, and also follow the keyword with more if it makes it more visually distinct for you.
Another thing you can do is put a language name instead of Code so it uses the correct syntax highlighting. You can also use Text to have no highlighting at all, and you can switch from one mode to another without closing each block individually.
This is a normal paragraph.
======= C# =======
int x = 12;
int y = 0;
====== Perl ======
my $x = 12;
my $y = 0;
====== Text ======
This is plain text
==================
This is a normal paragraph.
This is a normal paragraph.
int x = 12;
int y = 0;
my $x = 12;
my $y = 0;
This is plain text
This is a normal paragraph.
If you just want a quick line here or there you can start each one with >, |, or :. It won't be highlighted though.
This is a normal paragraph.
> int x = 12;
> int y = 0;
This is a normal paragraph.
This is a normal paragraph.
int x = 12;
int y = 0;
This is a normal paragraph.
There's more to linking. You can link to URLs and e-mail addresses, but in this case the angle brackets are optional.
Visit <http://www.website.com> or send messages to email@address.com.
Visit http://www.website.com or send messages to em@addre ss.com. ail
You can create named links by putting the text, "at", and then the address in the angle brackets. This format lets it read naturally in a sentence. You can also use a colon instead of "at" if you prefer.
Visit <the website: http://www.website.com> or <e-mail me at email@address.com>.
Visit the website or e-mail me.
E-mail addresses look and act like regular links but the HTML is obfuscated to help protect them from spam crawlers.
As for regular links, to help them fit into sentences easily you can actually include plurals and possessives inside the angle brackets. In other words, you don't have to use awkward syntax like <Object>s, although that's supported as well. You can simply write <Objects> and it will link to the symbol Object just fine. It can handle any plural and/or possessive form you can throw at it. I'm not kidding: Foxes, Fox's, Foxes', Children, Mice, Alumni, Indices, Amoebae, Teeth, just try to trip it up.
Sometimes you want to include documentation that doesn't correspond directly to a code element. Maybe you want to include license information or architecture notes. There are two ways to do this.
Just because most of the comments you write will directly correspond to an element of your source code doesn't mean they have to. You can pick any of the available keywords and create a standalone comment with it. For example:
/* Class: Counter
* A class that manages an incrementing counter.
*/
public class Counter
{
/* About: Thread Safety
* This class is not designed to be thread safe.
*/
/* Constructor: Counter
* Initializes the object.
*/
public Counter ()
{ value = 0; }
...
The extra comment will be added to the output just like the functions.
This class is not designed to be thread safe.
Remember that because of scope the comment will actually be considered part of Counter the way it's listed above. You'd link to it from outside Counter with <Counter.Thread Safety>. That idea may take some getting used to, but if the extra comment only applies to one class that's actually the most appropriate way to do it. If it were something like a license that applies to the entire project you would put it above the class to make it global, just like moving a function there would.
You can also add additional documentation with text files. If you put a file with a .txt extension in your source folders and start it with a "keyword: title" line its contents will be treated the same as if it were in a comment in your source code. That means you can define multiple things in it by using multiple "keyword: title" lines, you can link between them and comments in your source code, and you can use all available formatting options.
Title: License
This file is licensed under the GPL.
I can link to <Counter> and <Counter.Increment>, and the
documentation in that class can even link back with <License>.
About: Second Topic
I can create a *second* topic in here too, complete with
formatting.
You must remember to start it with a "keyword: title" line, like "Title: License" above. This is how Natural Docs tells it apart from regular text files.
Here's another useful thing you may want to know about. Suppose you have a lot of little things to document, like constants. Writing a separate comment for each one can be very tedious, no matter how much you compress it:
// Constant: COUNTER_NORMAL
// Causes the counter to increment normally.
const int COUNTER_NORMAL = 0;
// Constant: COUNTER_ODD
// Causes the counter to only increment in odd numbers.
const int COUNTER_ODD = 1;
// Constant: COUNTER_EVEN
// Causes the counter to only increment in even numbers.
const int COUNTER_EVEN = 2;
If you looked at the keyword list you may have noticed that they almost all have plural forms. These are used to create what are called list comments. You define a comment using a plural keyword, and then anything appearing in a definition list within it becomes linkable as if they each had their own comment. For example:
/* Constants: Counter Modes
COUNTER_NORMAL - Causes the counter to increment normally.
COUNTER_ODD - Causes the counter to only increment in odd numbers.
COUNTER_EVEN - Causes the counter to only increment in even numbers.
*/
const int COUNTER_NORMAL = 0;
const int COUNTER_ODD = 1;
const int COUNTER_EVEN = 2;
I would now be able to write <COUNTER_ODD> and have it work the same as it would with the first example.
Using the enum keyword is special because it automatically behaves in a similar manner. This allows both the enum and its values to be documented in the same place.
/* Enum: CounterMode
Normal - Causes the counter to increment normally.
Odd - Causes the counter to only increment in odd numbers.
Even - Causes the counter to only increment in even numbers.
*/
enum CounterMode { Normal, Odd, Even };
You can now link not only to CounterMode but to CounterMode.Odd.