This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Docstring question


On  7-Dec-1999, Daschbach, John L <John.Daschbach@pnl.gov> wrote:

| In my experience the best manuals are
| structured around usage and provided with alphabetical indexes of
| functions and variables.  Two quite good manuals I think are Octave
| and Emacs Lisp.

Thanks!  :-)  The Octave manual owes a lot to the organization of the
Emacs Lisp manual, as well as the Gawk and Emacs manuals.  I think
I've seen RMS write that a good manual must be more than just a
laundry list of functions.  I tried hard to follow that advice by
writing a description of a topic with reference-manual information
mixed in.  I think I've partially succeeded, but there is still much
work to be done.

| To
| automatically collect docstring information into relevant manual
| sections requires some sort of metadata to be included in the
| docstring format.

Perhaps this is not really necessary.  Here is what I'm currently using
in the Octave sources (interpreter code and manual).  In the
interpreter sources, I declare functions like this:

  DEFUN (fprintf, args, ,
    "-*- texinfo -*-\n\
  @deftypefn {Built-in Function} {} fprintf (@var{fid}, @var{template}, @dots{})\n\
  This function is just like @code{printf}, except that the output is\n\
  written to the stream @var{fid} instead of @code{stdout}.\n\
  @end deftypefn")
  {
    ... function body stuff ...
  }

This is similar to what I've seen proposed on this list.  I stole the
idea from GNU Emacs, which is where I first saw it.  FWIW, I didn't
find it all that hard to follow, nor do I think it makes the sources
much harder to read.  I think it is worth using this approach just to
avoid duplicating information.  Note that Octave does not require a
separate interpreter function name because all function names in
Octave are also valid identifiers in C++.  As is the Emacs convention,
function names are prefixed with an `F', so the C++ identifier for the
above function is actually `Ffprintf' (automatically generated by the
macro, so this convention is enforced), though perhaps it should really
use namespaces and be something like Octave::Ffprintf.  In any case,
this would be an easy change to make globally just by changing the
definition of DEFUN.

When compiling the sources, DEFUN expands to the function declaration.
When creating a DOCSTRINGS file, it expands to the doc string plus
some marker information so that it is easy to extract the doc string
from the preprocessor output.  Again, I don't think this is a terrible
thing, and I find that its usefulness far outweighs any potential
confusion (I really dislike having to maintain the same information in
more than one place).  If someday I find a system where preprocessor
abuse like this is not possible, I suppose I'll have to include a
standalone C++ preprocessor with Octave, or write a special-purpose
mini-preprocessor to handle the task.

Originally, the doc strings in the Octave sources did not contain
Texinfo markup commands (it is still optional).  Instead, I had
separate documentation strings in the manual sources.  The duplication
always bothered me, but I didn't see a good solution for quite a
while.  Recently, I realized that it would be possible to use Texinfo
markup commands in the doc strings and to use makeinfo to format them
before displaying them, so I began switching to the current scheme in
which the interpreter sources contain the only copy of the doc
strings, and they are automatically inserted in the manual sources.
Now when someone types `help FUNCTION' at the command prompt, Octave
checks to see if the doc string for FUNCTION begins with the magic
`-*- texinfo -*-' header, and if it does, passes the remainder of the
string through makeinfo (along with appropriate flags) before
displaying it.  Doing things this way also helps to give the on-line
help a more uniform appearance.

To manage the insertion of the doc strings in the manual, I have
things like this in the ultimate manual sources:

  @node Formatted Output
  @subsection Formatted Output

  This section describes how to call @code{printf} and related functions.

  The following functions are available for formatted output.  They are
  modelled after the C language functions of the same name, but they
  interpret the format template differently in order to improve the
  performance of printing vector and matrix values.

  @DOCSTRING(printf)

  @DOCSTRING(fprintf)

  @DOCSTRING(sprintf)

  The @code{printf} function can be used to print any number of arguments.
  The template string argument you supply in a call provides
  information not only about the number of additional arguments, but also
  about their types and what style should be used for printing them.

  ...

Then I create the manual by

  1. Processing the sources to extract doc strings, storing them in a
     separate file.

  2. Processing the manual sources and replacing @DOCSTRING(foo) with
     the actual doc string for the function foo, which is found in the
     file generated in step 1.

I find that this methods works reasonably well.  The filters I wrote
to extract the doc strings from the interpreter sources and insert it
in the manual sources are a mixture of shell scripts and C++, but it
would probably be quite easy to write them entirely in guile.

My solution does require that someone add information to the manual
for new functions, but that should probably be done anyway or you will
end up with a manual that is just a list of function descriptions with
no unifying text.

jwe

-- 
In the beginning, Ken Thompson | Octave: http://www.che.wisc.edu/octave
wrote the searching tool grep. |     Me: http://www.che.wisc.edu/~jwe
       -- A. Hume, SP&E (1988) |

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]