oocdoc, Part 1 — NaturalDocs
May 22, 2013
4 minute read

Documentation in ooc land has sucked for quite some time. The standard response is pretty much: “use the code, Luke!” — which is fine when doing small projects that don’t matter much, but not so when you want to get serious.

So when a newcomer, beoran, asked how to generate documentation, and later told us he got NaturalDocs to work, naturally, I had to see for myself how well it worked.

The basic idea

In this series I’m talking about generated documentation, not hand-written manual. Reference docs are usually generated directly from the codebase, thanks to inline documentation like this:

/**
 * The star of the latest EA game. Can bark.
 *
 * @since 1.3
 * @author Amos Wenger
 */
Dog: class {

  /**
   * Make a barking sound. That's good, right?
   *
   * @param sound Something like "woof" or "glap", depending
   * on your country of choice.
   *
   * @return true on success
   */
  bark: func (sound: String) -> Bool {
      "%s, %s!" printfln(sound, sound)
      true
  }

}

Then, a tool is used to parse the code and generate documentation from there. For Java, there’s javadoc. For C/C++ and a few others, there’s Doxygen. For JavaScript, there’s a plethora of options, and so on.

However there’s no tool yet for ooc that does exactly that. I’m planning to write one and describe my adventure in this series of blog posts, but for now I’ll present another alternative that works a bit differently: NaturalDocs.

How NaturalDocs works

NaturalDocs with any language based on some symple syntactic hints. Since it has no knowledge of the structure of programs, modules, libraries, classes and functions, you have to annotate them by hand.

The example above, with NaturalDocs mark up, would look like:

/**
 * Class: Dog
 *
 * The star of the latest EA game. Can bark.
 *
 * Since: 1.3
 * Author: Amos Wenger
 */
Dog: class {

  /**
   * Function: numFrames
   *
   * Make a barking sound. That's good, right?
   *
   * Parameters:
   *
   *   sound - Something like "woof" or "glap", depending on your country of choice.
   *
   * Returns:
   *
   *   true on success
   */
  bark: func (sound: String) -> Bool {
      "%s, %s!" printfln(sound, sound)
      true
  }

}

As you can see, the problem with this syntax is that it is rather long - it would be a hassle to work on a codebase that has such comments in there. There’s almost no room for code!

NaturalDocs also handles Javadoc-like syntax (see previous section), but only for languages which have full support - at the time of this writing, only C# 1.1, Perl, and ActionScript.

NaturalDocs and ooc

Adding support for a language in NaturalDocs is not trivial, but it can be done. The most important step is to add a Languages.txt file in your NaturalDocs project directory.

Language: ooc

   Extensions: ooc use
   Shebang String: ooc
   Line Comments: // #
   Block Comment: /** */
   Package Separator: /
   Enum Values: Under type
   Function Prototype Enders: { \n
   Variable Prototype Enders: = \n
   Line Extender: \

In your example, our directory structure looks something like this:

- project
  - source
  - doc
    - html
    - nd-project
      - Languages.txt

And the command we need to run to build docs is the following:

NaturalDocs -i source -o HTML doc/html -p doc/nd-project

How it looks

Unfortunately, I have to say it looks pretty bad. Even Javadoc seems friendly in comparison. See for yourself:

Of course, that’s the default style. With a few CSS tricks, we can get something that looks almost acceptable:

But there’s still the markup problem: having such a volume of comments in the code is not acceptable in my opinion, and having to repeat type and function names is seriously not DRY.

Also, the command line to launch doc generation is quite long and not trivial to remember. I much prefer tools that have a single per-project config file, that is optional, and sane defaults.

What’s next?

So, even though NaturalDocs does the deed, I am not satisfied with it. Before attempting to write my own documentation generator, I’ll take a look at an alternative, Sphinx, which is currently being used to generate the SDK documentation.