[getopt-sig] Suggestions for Optik

David Goodger goodger@users.sourceforge.net
Thu, 30 May 2002 21:14:32 -0400


(Perhaps this should be on optik-users, but this is where all the
action is -- and all the eyes are -- these days.)

I'm glad to see Optik moving forward into the standard library.  I've
just finished a first cut at applying Optik to the Docutils project
(http://docutils.sf.net/), and have some suggestions.  I don't mean
for this to impede Optik's stdlib adoption; the issues are not central
to its workings, and the timing is purely coincidental.  However, if
there are to be changes, earlier is better.

Here's a simplified description.  Docutils is a modular system, with
"Reader" components for input and "Writer" components for output.  A
front end will combine an arbitrary Reader and Writer together.  The
core system has a set of command-line options, and each component may
have its own set.  I've implemented an option specification data
structure, a list of ``('help text', [list of option strings], {dict
of keyword arguments})`` 3-tuples, which populate an Optik
OptionParser subclass.  The ``optik.option_parser.Values`` object
produced is used in both command-line script context (via a front-end)
and imported module context.  For details, see:

- http://docutils.sf.net/tools/html.py (a working front-end script)
- http://docutils.sf.net/docutils/frontend.py
- http://docutils.sf.net/docutils/core.py
- http://docutils.sf.net/docutils/writers/html4css1.py

Here are my suggestions.  I am willing and able to do the
implementation work, alone or with others.  Would anybody like to
help?  Feedback is welcome.

- Overhaul the help message code.  As has been mentioned on getopt-sig
  and/or optik-users before, the help message generating code ought to
  be extracted into a class of its own (call it "HelpMessenger" for
  now).

  - Make the parts of help messages (usage model, formatted list of
    options, etc. [see below]) individually accessible.  That would
    make Optik more flexible for auto-documentation and for extending
    the HelpMessenger class.

  - As with "options:", the "usage:" header should be supplied by
    Optik, even when a custom usage string is supplied.  In other
    words, an Optik client should supply::

        usage="%prog [options] [arg1 [arg2] ...]"

    Currently, you have to supply::

        usage="usage: %prog [options] [arg1 [arg2] ...]"

    It may seem a small point, but it makes the help system more
    consistent.  It's important when combined with the following
    ideas.

  - Allow more structure and flexibility in help messages.  I'd like
    to be able to generate help messages more like what you get from
    "grep --help" and other GNU tools.

    - Add titles for groups of options (which would require "option
      group" objects), and interspersed free explanatory text.  Option
      group titles should be short (a few words only, less than a line
      long, so they don't wrap).  This directly relates to Docutils'
      modular nature: one option group per component.

    - Add introductory descriptive text, examples, and closing
      statements as well.

    For example::

        "myscript" does XYZ to ABC              <- intro
        in a very cool way.

        Usage:
          myscript [options] [arg]              <- usage template

          If "arg" is not supplied, STDIN       <- usage elaboration
          is assumed.                              (free text)

        Example(s):
          myscript -v file1 file2               <- example (literal)

        Options:
          General options:                      <- option group title
            -h, --help     ...                  <- option group
            -v, --verbose  ...

          General options are available         <- free text
          for all formats.

          HTML-specific options:
            --stylesheet=file  ...
            ...

        Please report bugs to                   <- closing statements
        <bugs@example.org>.

    - Text in intro, examples, and closing, and text between option
      groups can be paragraphs (free-wrapping) or literal blocks
      (<pre>; linebreaks are significant and won't wrap).

    - Option groups could be nestable, but limited to one level may be
      better.  Perhaps either all option groups, or all single
      options, but not mixed?

    - Options are flattened internally into OptionParser's _short_opt
      & _long_opt dictionaries for lookup.

    OptionParser could grow new methods: add_intro_text(),
    add_example_text(), add_option_group(), add_option_text(),
    add_closing_text().  Corresponding classes might also need to be
    added: OptionGroup, etc.

  - Rework the structure of help messages to make them more
    reStructuredText-friendly?  It would be ideal if the help text
    produced by the standard Python option processor was parseable by
    the standard Python documentation utilities (positive thinking).

    Perhaps no changes are required, if the help message parts are
    made individually accessible.  The format as it is now, is valid
    reStructuredText.

  - Put long options first?  Short options are like a shortcut for
    long options.  Long options are more verbose and better identify
    the option; they're more of a "title".  I know that GNU tools
    always do "short, long", but they seem to be hand-crafted anyway.

  Some prior discussion on getopt-sig: "Documentation, functionality,
  options, syncing" thread began 2002-02-20:
  http://mail.python.org/pipermail/getopt-sig/2002-February/000064.html

- Standardize a Python API for extracting command-line help from
  script modules?  An auto-documentation program could import a script
  as a module, and extract the script's usage for inclusion in the
  generated documentation.  Or perhaps this is too complicated, and
  it'd be better and easier to simply call the script with "--help"
  and use *that*.

- Add something like a ``get_default_values`` method to OptionParser::

      def get_default_values(self):
          return Values(self.defaults)

  This is very useful when code can be used both as a command-line
  script and an importable module.  See the OptionParser subclass in
  http://docutils.sf.net/docutils/frontend.py; the "__init__" method
  accepts a dict of default overrides which affects the Values object
  returned.  This is used in import (as opposed to command-line)
  context.

-- 
David Goodger  <goodger@users.sourceforge.net>  Open-source projects:
  - Python Docutils: http://docutils.sourceforge.net/
    (includes reStructuredText: http://docutils.sf.net/rst.html)
  - The Go Tools Project: http://gotools.sourceforge.net/