Documenting softcode (gasp)

Submitted by Cheetah on Tue, 2010-01-12 14:33

When I need something softcoded, especially a function, chances are I'll code it myself. Even if it exists. Even if it exists on the same MUSH. There are several reasons for that, but one's a fairly big one: Softcode is hard to read. Doubly so if you didn't code it. What's worse, since softcode doesn't have a function definition like you would in C or Python or whatnot, you don't have even the self-documentation that comes from variable names, and in fact you may have to dig deep to even see how many arguments a function takes, let alone determine which ones are optional. I've been wanting to do something about that for a while (read: at least 3 years), but this time I actually did come up with a partial solution.

Let's take a quick example. How many arguments does the following code take, and how many are optional? What do the arguments DO? What does the thing return anyway? (Please don't waste too much time on it.)

&FUN_DOCUMENT object=ifelse(hasattr(%0,1`cc),u(fun_parse_cc,lcstr(%1),xget(%0,%1`cc)),Function has no calling convention defined.)[if(%2,%r[if(hasattr(%0,%1`doc),u(fun_decorate,u(%0/%1`doc),first(xget(%0,%1`cc))),Function has no docstring.)])]

Still with me? Okay, now, how much easier is it to get the same info from this snippet of text, generated by my docf code:

Call: u(fun_document, <object>, <attr>, [full])
=> documentation (a string)

Let's see.. 2 args with an optional third. An object, an attr, and optionally something called 'full'. It returns some documentation, apparently. So 'full' might mean 'display full documentation' as opposed to a part of it?

How did I generate this snippet? Relatively easily:

&fun_document`cc object=object:attr:*:full r:string:documentation
docf object/fun_document

This says: I have arguments object and attr, the rest of the arguments are optional, the one optional argument is 'full'. It returns a string which represents documentation.

This is a nice start, but some things are still unclear. Let's change that.

&FUN_DOCUMENT`DOC object=Get the documentation of the ufun in OBJECT/ATTR. If FULL, output the docstring as well as the calling convention.
docff object/fun_document

That gets me:

Call: u(fun_document, <object>, <attr>, [full])
=> documentation (a string)
Get the documentation of the ufun in <object>/<attr>. If [full], output the docstring as well as the calling convention.

Note that it automatically transformed the uppercase arguments, marking them as mandatory or optional, as well as making them stand out. (And additionally it lets the docf code know those arguments are documented so it won't warn you about skipping them.)

With docf you have 2 times 2 options: docf with one f displays just the calling information (what's defined in the `cc attr). docff (with a second f for 'full') displays the docstring as well. On the argument side, you can specify obj/attr, or just an object to see the info for all documented functions. So you can go 'docf object' to get a quick reminder of what functions are available and roughly how they work, or 'docff object/attr' to get all the info for a specific function. Or even 'docff object' when you're learning how a new system works.

The system so far has a fair amount of features, but it does have two important limitations: First off, it's only meant for documenting ufuns, not commands or other things (though at least commands are clearer about their arguments). Second, it still requires someone to actually write the documentation, sadly ;) Though even just a `cc attr can make a world of difference.

I hope someone (preferably several someones) will find this useful. Questions, comments, suggestions and their ilk very welcome.