[getopt-sig] Ann: argexp - new option parsing library

Beni Cherniavsky cben@techunix.technion.ac.il
Wed, 11 Dec 2002 15:13:47 +0200 (IST)


Hi,

This is not mature enough yet for use in a real application (help printing
not implemented) so I'm only announcing it here for now (if you think
somebody does have use for it today, feel free to forward).  I withholded
releasing it since I felt "just a little bit and I will have a help system
and it will be ready for use" but I didn't advance on that part for some
time.  Also Greg Ward mentioned that the name change optik->optarg could
be a good oportunity to even introduce incompatibilities.  So I decided to
show what I have for possible cross-fertilization of ideas...

It's currently availiable at:

http://www.technion.ac.il/~cben/argexp/

``argexp.py`` is the library itself, in one file.  It's reasonably
documented (rST docstrings all over), in particular the top module
docstring gives an overview.  It takes quite a different approach from
optik in that it provides a full language for specifying the syntax and
associated semantics of the command line.  The building block is a Matcher
object that takes a list of arguments and an associated env dict and
returns some extracted information, a new argument list and a new env (or
fails with an exception).  The aim is to be able to directly handle *all*
command-line parsing needs, including positional arguemtns, even for
programs like cvs!  To this end it's very easily extensible.

To get a taste:

>>> arglist = ['--fo', '.5', '-d']
>>> Option('--foo').match(arglist, {})
(0, ['.5', '-d'], {})
>>> Function(float).match(*_[1:])
(0.5, ['-d'], {})
>>> Repeat(Switch({
        Option('--foo'): Set('foo', Function(float)),
        Or(Option('--debug'), Option('-d')): Set('debug', Quote(1))
     })).match(arglist, {})
([None, None], [], {'foo': 0.5, 'debug': 1})

A shorter way to describe the last matcher is by using "templates", that
give meanings to standalone Python objects (strings, functions, lists,
dicts, etc.): ``({'--foo': float, ('--debug', '-d'): 1},)`` :-).

For a "real" example see ``ripoff_argexp.py`` - an interface to ripoff
using in the context of:

http://www.python.org/sigs/getopt-sig/compare.html

With 127 lines, 84 of them code, it's smaller than all competitors except
optik but it does quite a bit more than optik -- it parses ``-t 1,5-7,2``
into the list [1, 5, 6, 7, 2] and manages all conflicts between dependent
options (-p/-f, -R => -k => -f) before they get to the application.

The example shows approximately where the help strings will go.  I'm still
not sure how this will work.  Basically the tree will be traversed in some
flexible way that will allow to control how much to print (usage, full
help, help limited to some part of the tree for big programs, etc.).  I
expect eventually to reach more help flexibility than possible with e.g.
optik -- but as I said I have none yet ;-)

-- 
Beni Cherniavsky <cben@tx.technion.ac.il>

What's lower level than machine code?  A spreadsheet: not only addresses
are numeric and hand-allocated but also all loops are hand-unrolled and
all calls hand-inlined... (and macros are unheard of, of course).