NAME
   main.rb

SYNOPSIS
   a class factory and dsl for generating real main programs real quick

URI

   http://rubyforge.org/projects/codeforpeople/
   http://codeforpeople.com/lib/ruby/

INSTALL

   $sudo gem install main

DESCRIPTION
   main.rb is a library which simplifies and unifies the details of creating
   command line programs.  for instance, this program

     require 'main'

     Main {
       argument 'foo'
       option 'bar'

       def run
         p params['foo']
         p params['bar']
         exit_success!
       end
     }

   sets up a program which requires one argument, 'bar', and which may accept one
   command line switch, '--foo' in addition to the single option which is always
   accepted and handled appropriately: '--help', '-h'.

   for simple programs this is a real time saver but it's for more complex
   applications where main.rb's unification of parameter parsing, class
   configuration dsl, and auto-generation of usage messages can really streamline
   command line application development.  for example the following 'a.rb'
   program:

     require 'main'

     Main {
       argument('foo'){
         cast :int
       }
       keyword('bar'){
         arity 2
         cast :float
         defaults 0.0, 1.0
       }
       option('foobar'){
         argument :optional
         description 'the foobar option is very handy'
       }
       environment('BARFOO'){
         cast :list_of_bool
         synopsis 'export barfoo=value'
       }

       def run
         p params['foo'].value
         p params['bar'].values
         p params['foobar'].value
         p params['BARFOO'].value
       end
     }

   when run with a command line of

     BARFOO=true,false,false ruby a.rb 42 bar=40 bar=2 --foobar=a

   will produce

     42
     [40.0, 2.0]
     "a"
     [true, false, false]

   while a command line of

     ruby a.rb --help

   will produce

     NAME
       a.rb

     SYNOPSIS
       a.rb foo [bar=bar] [options]+

     PARAMETERS
       * foo [ 1 -> int(foo) ]

       * bar=bar [ 2 ~> float(bar=0.0,1.0) ]

       * --foobar=[foobar] [ 1 ~> foobar ]
           the foobar option is very handy

       * --help, -h

       * export barfoo=value

   and this shows how all of argument, keyword, option, and environment parsing
   can be declartively dealt with in a unified fashion - the dsl for all
   parameter types is the same - and how auto synopsis and usage generation saves
   keystrokes.  the parameter synopsis is compact and can be read as

       * foo [ 1 -> int(foo) ]

         'one argument will get processed via int(argument_name)'

           1        : one argument
           ->       : will get processed (the argument is required)
           int(foo) : the cast is int, the arg name is foo

       * bar=bar [ 2 ~> float(bar=0.0,1.0) ]

         'two keyword arguments might be processed via float(bar=0.0,1.0)'

           2                  : two arguments
           ~>                 : might be processed (the argument is optional)
           float(bar=0.0,1.0) : the cast will be float, the default values are
                                0.0 and 1.0

       * --foobar=[foobar] [ 1 ~> foobar ]

         'one option with optional argument may be given directly'

       * --help, -h

         no synopsis, simple switch takes no args and is not required

       * export barfoo=value

         a user defined synopsis

SAMPLES

   <========< samples/a.rb >========>

   ~ > cat samples/a.rb

     require 'main'

     ARGV.replace %w( 42 ) if ARGV.empty?

     Main {
       argument('foo'){
         required                    # this is the default
         cast :int                   # value cast to Fixnum
         validate{|foo| foo == 42}   # raises error in failure case
         description 'the foo param' # shown in --help
       }

       def run
         p params['foo'].given?
         p params['foo'].value
       end
     }

   ~ > ruby samples/a.rb

     true
     42

   ~ > ruby samples/a.rb --help

     NAME
       a.rb

     SYNOPSIS
       a.rb foo [options]+

     PARAMETERS
       * foo [ 1 -> int(foo) ]
           the foo param

       * --help, -h



   <========< samples/b.rb >========>

   ~ > cat samples/b.rb

     require 'main'

     ARGV.replace %w( 40 1 1 ) if ARGV.empty?

     Main {
       argument('foo'){
         arity 3                             # foo will given three times
         cast :int                           # value cast to Fixnum
         validate{|foo| [40,1].include? foo} # raises error in failure case
         description 'the foo param'         # shown in --help
       }

       def run
         p params['foo'].given?
         p params['foo'].values
       end
     }

   ~ > ruby samples/b.rb

     true
     [40, 1, 1]

   ~ > ruby samples/b.rb --help

     NAME
       b.rb

     SYNOPSIS
       b.rb foo [options]+

     PARAMETERS
       * foo [ 3 -> int(foo) ]
           the foo param

       * --help, -h



   <========< samples/c.rb >========>

   ~ > cat samples/c.rb

     require 'main'

     ARGV.replace %w( foo=40 foo=2 bar=false ) if ARGV.empty?

     Main {
       keyword('foo'){
         required  # by default keywords are not required
         arity 2
         cast :float
       }
       keyword('bar'){
         cast :bool
       }

       def run
         p params['foo'].given?
         p params['foo'].values
         p params['bar'].given?
         p params['bar'].value
       end
     }

   ~ > ruby samples/c.rb

     true
     [40.0, 2.0]
     true
     false

   ~ > ruby samples/c.rb --help

     NAME
       c.rb

     SYNOPSIS
       c.rb foo=foo [bar=bar] [options]+

     PARAMETERS
       * foo=foo [ 2 -> float(foo) ]

       * bar=bar [ 1 ~> bool(bar) ]

       * --help, -h



   <========< samples/d.rb >========>

   ~ > cat samples/d.rb

     require 'main'

     ARGV.replace %w( --foo=40 -f2 ) if ARGV.empty?

     Main {
       option('foo', 'f'){
         required  # by default options are not required, we could use 'foo=foo'
                   # above as a shortcut
         argument_required
         arity 2
         cast :float
       }

       option('bar=[bar]', 'b'){  # note shortcut syntax for optional args
         # argument_optional      # we could also use this method
         cast :bool
         default false
       }

       def run
         p params['foo'].given?
         p params['foo'].values
         p params['bar'].given?
         p params['bar'].value
       end
     }

   ~ > ruby samples/d.rb

     true
     [40.0, 2.0]
     true
     false

   ~ > ruby samples/d.rb --help

     NAME
       d.rb

     SYNOPSIS
       d.rb --foo=foo [options]+

     PARAMETERS
       * --foo=foo, -f [ 2 -> float(foo) ]

       * --bar=[bar], -b [ 1 ~> bool(bar=false) ]

       * --help, -h



DOCS
   test/main.rb
   find lib|xargs -n1 vi -R

HISTORY
   0.0.1

     initial version.  this version extracts much of the functionality of alib's
     (gen install alib) Alib.script main program generator and also some of jim's
     freeze's excellent CommandLine::Aplication into what i hope is a simpler and
     more unified interface

-a
-- 
be kind whenever possible... it is always possible.
- the dalai lama