Friday, June 21, 2013

A simple documentation generator

No, I don't want to create yet-another documentation-generator like Doxygen, there are lots of them, each with their specific purpose, and strengths. But mostly (at least AFAIK), all of them are intended to be embedded in the host language, and to document the APIs of the same language. I.e, if one is writing some C code, and wants to document the APIs of the same C code - all is well!. But I wanted something different (ah! as usual!).
I am embedding Lua into our application, and I am writing libraries to be used by Lua, in C. And, I want to document those APIs [of Lua], which I am building, by adding the usual doxygen-like comments in the source files.
I have 2 choices at this point, either I define some comment format/tags (like @something \something-else) and then extract them out of the source, then parse and generate the docs), Or ... use something which is well suited for data-description. Aha!, I'm anyway learning/using Lua, which has its roots in data-description, why not embed Lua code into my C comments?
Of course!
All I need is, a brief description of what the function does, its arguments and return types, at the
minimum, I can capture it, in Lua, like:
   mydoc {
       name = "str_len", -- function name
       args =  { string = 's' }, -- input arg and its type
       ret = { len = 'i' }, -- return val and its type
       brief = "return the length of input string",

And a way to quickly fetch it from the source - make the comment begin with '*!' (or something similar)
 *!   mydoc {
 *!       name = "str_len", -- function name
 *!       args =  { string = 's' }, -- input arg and its type
 *!       ret = { len = 'i' }, -- return val and its type
 *!       brief = "return the length of input string",
 *!   }
And how to convert this to doc ?  simple!, just grep out these comments from the C source, and then define the mydoc function in Lua:
  function mydoc (t) -- excluding err handling and formatting
    if then
        print (libname .. ":" .. , "\n") -- libname also from source
    if t.brief then
        print (" -- ", t.brief, "\n")
    if t.args then
        print ("\tTakes " .. tablelength(t.args)  .. " arguments")
        describeargs(t.args) -- writes the values and their types
        print "\tTakes no arguments\n"
    if t.ret then
        print ("\tReturns " .. tablelength(t.ret)  .. " values")

Run all of this (the mydoc function, and the extracted blocks) together in Lua, and there you go! Now, generating text doc was so easy, how difficult is it to generate Markdown?  I added both, as options (to the bash wrapper, which extracts the comments and runs Lua on it) :-)