# \[ANN\] main-4.0.0 (for avdi)

**URL:** <https://rubytalk.org/t/ann-main-4-0-0-for-avdi/55885>\
**Category:** ruby-talk\
**Created:** [21 October 2009 00:21 UTC](https://rubytalk.org/t/ann-main-4-0-0-for-avdi/55885 "2009-10-21T00:21:41Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![a11](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/a11/32/8169_2.png) [@a11](https://rubytalk.org/u/a11)\
**Post date:** [21 October 2009 00:21 UTC](https://rubytalk.org/t/ann-main-4-0-0-for-avdi/55885/1 "2009-10-21T00:21:41Z")

</div>

NAME  
&nbsp;&nbsp;main.rb

SYNOPSIS  
&nbsp;&nbsp;a class factory and dsl for generating command line programs real quick

URI  
&nbsp;&nbsp;[http://codeforpeople.com/lib/ruby/](http://codeforpeople.com/lib/ruby/)  
&nbsp;&nbsp;[http://rubyforge.org/projects/codeforpeople/](http://rubyforge.org/projects/codeforpeople/)  
&nbsp;&nbsp;[http://github.com/ahoward/main](http://github.com/ahoward/main)

INSTALL  
&nbsp;&nbsp;gem install main

DESCRIPTION  
&nbsp;&nbsp;main.rb features the following:

&nbsp;&nbsp;&nbsp;&nbsp;- unification of option, argument, keyword, and environment parameter  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parsing  
&nbsp;&nbsp;&nbsp;&nbsp;- auto generation of usage and help messages  
&nbsp;&nbsp;&nbsp;&nbsp;- support for mode/sub-commands  
&nbsp;&nbsp;&nbsp;&nbsp;- io redirection support  
&nbsp;&nbsp;&nbsp;&nbsp;- logging hooks using ruby's built-in logging mechanism  
&nbsp;&nbsp;&nbsp;&nbsp;- intelligent error handling and exit codes  
&nbsp;&nbsp;&nbsp;&nbsp;- use as dsl or library for building Main objects  
&nbsp;&nbsp;&nbsp;&nbsp;- parsing user defined ARGV and ENV  
&nbsp;&nbsp;&nbsp;&nbsp;- zero requirements for understanding the obtuse apis of \*any\* command  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line option parsers  
&nbsp;&nbsp;&nbsp;&nbsp;- leather pants

&nbsp;&nbsp;in short main.rb aims to drastically lower the barrier to writing uniform  
&nbsp;&nbsp;command line applications.

&nbsp;&nbsp;for instance, this program

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;Main {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument 'foo'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'bar'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p params['foo']  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p params['bar']  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit\_success!  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;sets up a program which requires one argument, 'bar', and which may accept one  
&nbsp;&nbsp;command line switch, '--foo' in addition to the single option/mode  
which is always  
&nbsp;&nbsp;accepted and handled appropriately: 'help', '--help', '-h'. for the most  
&nbsp;&nbsp;part main.rb stays out of your command line namespace but insists that your  
&nbsp;&nbsp;application has at least a help mode/option.

&nbsp;&nbsp;main.rb supports sub-commands in a very simple way

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;Main {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'install' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'installing...' end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'uninstall' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'uninstalling...' end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;which allows a program, called 'a.rb', to be invoked as

&nbsp;&nbsp;&nbsp;&nbsp;ruby a.rb install

&nbsp;&nbsp;and

&nbsp;&nbsp;&nbsp;&nbsp;ruby a.rb uninstall

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

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

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

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

&nbsp;&nbsp;when run with a command line of

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

&nbsp;&nbsp;will produce

&nbsp;&nbsp;&nbsp;&nbsp;42  
&nbsp;&nbsp;&nbsp;&nbsp;[40.0, 2.0]  
&nbsp;&nbsp;&nbsp;&nbsp;"a"  
&nbsp;&nbsp;&nbsp;&nbsp;[true, false, false]

&nbsp;&nbsp;while a command line of

&nbsp;&nbsp;&nbsp;&nbsp;ruby a.rb --help

&nbsp;&nbsp;will produce

&nbsp;&nbsp;&nbsp;&nbsp;NAME  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.rb

&nbsp;&nbsp;&nbsp;&nbsp;SYNOPSIS  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.rb foo [bar=bar] [options]+

&nbsp;&nbsp;&nbsp;&nbsp;PARAMETERS  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* foo [1 -\> int(foo)]

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* bar=bar [2 ~\> float(bar=0.0,1.0)]

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* --foobar=[foobar] [1 ~\> foobar]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the foobar option is very handy

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* --help, -h

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* export barfoo=value

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* foo [1 -\> int(foo)]

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'one argument will get processed via int(argument\_name)'

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* bar=bar [2 ~\> float(bar=0.0,1.0)]

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

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

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* --foobar=[foobar] [1 ~\> foobar]

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'one option with optional argument may be given directly'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* --help, -h

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;no synopsis, simple switch takes no args and is not required

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* export barfoo=value

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a user defined synopsis

SAMPLES

&nbsp;&nbsp;\<========\< samples/a.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/a.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;ARGV.replace %w( 42 ) if ARGV.empty?

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

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

&nbsp;&nbsp;~ \> ruby samples/a.rb

&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;42

&nbsp;&nbsp;\<========\< samples/b.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/b.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

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

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

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

&nbsp;&nbsp;~ \> ruby samples/b.rb

&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;[40, 1, 1]

&nbsp;&nbsp;\<========\< samples/c.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/c.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

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

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

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

&nbsp;&nbsp;~ \> ruby samples/c.rb

&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;[40.0, 2.0]  
&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;false

&nbsp;&nbsp;\<========\< samples/d.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/d.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

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

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

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

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

&nbsp;&nbsp;~ \> ruby samples/d.rb

&nbsp;&nbsp;&nbsp;&nbsp;true  
&nbsp;&nbsp;&nbsp;&nbsp;[40.0, 2.0]  
&nbsp;&nbsp;&nbsp;&nbsp;nil  
&nbsp;&nbsp;&nbsp;&nbsp;false

&nbsp;&nbsp;\<========\< samples/e.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/e.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;ARGV.replace %w( x y argument )

&nbsp;&nbsp;&nbsp;&nbsp;Main {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument 'argument'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'option'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'run' end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'a' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'a-option'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'a-run' end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'x' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'x-option'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'x-run' end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'y' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'y-option'

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run() puts 'y-run' end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;~ \> ruby samples/e.rb

&nbsp;&nbsp;&nbsp;&nbsp;y-run

&nbsp;&nbsp;\<========\< samples/f.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/f.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;ARGV.replace %W( compress /data )

&nbsp;&nbsp;&nbsp;&nbsp;Main {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument('directory'){ description 'the directory to operate on' }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option('force'){ description 'use a bigger hammer' }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this is how we run when no mode is specified'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'compress' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option('bzip'){ description 'use bzip compression' }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this is how we run in compress mode'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'uncompress' do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option('delete-after'){ description 'delete orginal file after  
uncompressing' }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this is how we run in un-compress mode'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;~ \> ruby samples/f.rb

&nbsp;&nbsp;&nbsp;&nbsp;this is how we run in compress mode

&nbsp;&nbsp;\<========\< samples/g.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/g.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;ARGV.replace %w( 42 ) if ARGV.empty?

&nbsp;&nbsp;&nbsp;&nbsp;Main {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument( 'foo' )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option( 'bar' )

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;run { puts "This is what to\_options produces:  
#{params.to\_options.inspect}" }  
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;~ \> ruby samples/g.rb

&nbsp;&nbsp;&nbsp;&nbsp;This is what to\_options produces: {"help"=\>nil, "foo"=\>"42", "bar"=\>nil}

&nbsp;&nbsp;\<========\< samples/h.rb \>========\>

&nbsp;&nbsp;~ \> cat samples/h.rb

&nbsp;&nbsp;&nbsp;&nbsp;require 'main'

&nbsp;&nbsp;&nbsp;&nbsp;# block-defaults are instance\_eval'd in the main instance and be  
combined with  
&nbsp;&nbsp;&nbsp;&nbsp;# mixins

> **···**
>
> #  
> &nbsp;&nbsp;&nbsp;&nbsp;# ./h.rb #=\> forty-two  
> &nbsp;&nbsp;&nbsp;&nbsp;# ./h.rb a #=\> 42  
> &nbsp;&nbsp;&nbsp;&nbsp;# ./h.rb b #=\> 42.0  
> &nbsp;&nbsp;&nbsp;&nbsp;#
> 
> &nbsp;&nbsp;&nbsp;&nbsp;Main {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fattr :default\_for\_foobar =\> 'forty-two'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option(:foobar) do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default{ default\_for\_foobar }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mixin :foo do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fattr :default\_for\_foobar =\> 42  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mixin :bar do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fattr :default\_for\_foobar =\> 42.0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;run{ p params[:foobar].value }
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode :a do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mixin :foo  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode :b do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mixin :bar  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;}
> 
> &nbsp;&nbsp;~ \> ruby samples/h.rb
> 
> &nbsp;&nbsp;&nbsp;&nbsp;"forty-two"
> 
> DOCS  
> &nbsp;&nbsp;test/main.rb  
> &nbsp;&nbsp;vim -p lib/main.rb lib/main/\*rb  
> &nbsp;&nbsp;API section below
> 
> HISTORY  
> &nbsp;&nbsp;4.0.0  
> &nbsp;&nbsp;&nbsp;&nbsp;- avoid duping ios. new methods Main.push\_ios! and Main.pop\_ios! are  
> &nbsp;&nbsp;&nbsp;&nbsp;utilized for testing. this was done to make it simple to wrap  
> &nbsp;&nbsp;&nbsp;&nbsp;daemon/servolux programs around main, althought not strictly required.  
> &nbsp;&nbsp;&nbsp;&nbsp;not the version bump - there is not reason to expect existing main  
> &nbsp;&nbsp;&nbsp;&nbsp;programs to break, but it \*is\* and interface change which requires a major  
> &nbsp;&nbsp;&nbsp;&nbsp;version bump.
> 
> API
> 
> &nbsp;&nbsp;Main {
> 
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;# CLASS LEVEL API #  
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# the name of the program, auto-set and used in usage  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;program 'foo.rb'  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# a short description of program functionality, auto-set and used in usage  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;synopsis "foo.rb arg [options]+"  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# long description of program functionality, used in usage iff set  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;description \<\<-hdoc  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this text will automatically be indented to the right level.
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it should describe how the program works in detail  
> &nbsp;&nbsp;&nbsp;&nbsp;hdoc  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# used in usage iff set  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;author 'ara.t.howard@gmail.com'  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# used in usage  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;version '0.0.42'  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# stdin/out/err can be anthing which responds to read/write or a string  
> &nbsp;&nbsp;# which will be opened as in the appropriate mode  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;stdin '/dev/null'  
> &nbsp;&nbsp;&nbsp;&nbsp;stdout '/dev/null'  
> &nbsp;&nbsp;&nbsp;&nbsp;stderr open('/dev/null', 'w')  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# the logger should be a Logger object, something 'write'-able, or a string  
> &nbsp;&nbsp;# which will be used to open the logger. the logger\_level specifies the  
> &nbsp;&nbsp;# initalize verbosity setting, the default is Logger::INFO  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;logger(( program + '.log' ))  
> &nbsp;&nbsp;&nbsp;&nbsp;logger\_level Logger::DEBUG  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# you can configure exit codes. the defaults are shown  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;exit\_success # 0  
> &nbsp;&nbsp;&nbsp;&nbsp;exit\_failure # 1  
> &nbsp;&nbsp;&nbsp;&nbsp;exit\_warn # 42  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# the usage object is rather complex. by default it's an object which can  
> &nbsp;&nbsp;# be built up in sections using the  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# usage["BUGS"] = "something about bugs'  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# syntax to append sections onto the already pre-built usage message which  
> &nbsp;&nbsp;# contains program, synopsis, parameter descriptions and the like  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# however, you always replace the usage object wholesale with one of your  
> &nbsp;&nbsp;# chosing like so  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;usage \<\<-txt  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my own usage message  
> &nbsp;&nbsp;&nbsp;&nbsp;txt
> 
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;# MODE API #  
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# modes are class factories that inherit from their parent class. they can  
> &nbsp;&nbsp;# be nested \*arbitrarily\* deep. usage messages are tailored for each mode.  
> &nbsp;&nbsp;# modes are, for the most part, independant classes but parameters are  
> &nbsp;&nbsp;# always a superset of the parent class - a mode accepts all of it's parents  
> &nbsp;&nbsp;# paramters \*plus\* and additional ones  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;option 'inherited-option'  
> &nbsp;&nbsp;&nbsp;&nbsp;argument 'inherited-argument'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;mode 'install' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'force' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description 'clobber existing installation'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inherited\_method()  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'installing...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode 'docs' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description 'installs the docs'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'installing docs...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;mode 'un-install' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option 'force' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description 'remove even if dependancies exist'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def run  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inherited\_method()  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'un-installing...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def run  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'no mode yo?'  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def inherited\_method  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'superclass\_method...'  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;# PARAMETER API #  
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# all the parameter types of argument|keyword|option|environment share this  
> &nbsp;&nbsp;# api. you must specify the type when the parameter method is used.  
> &nbsp;&nbsp;# alternatively used one of the shortcut methods  
> &nbsp;&nbsp;# argument|keyword|option|environment. in otherwords  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# parameter('foo'){ type :option }  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# is synonymous with  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# option('foo'){ }  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;option 'foo' {  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# required - whether this paramter must by supplied on the command line.  
> &nbsp;&nbsp;&nbsp;&nbsp;# note that you can create 'required' options with this keyword  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required # or required true  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# argument\_required - applies only to options.  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument\_required # argument :required  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# argument\_optional - applies only to options.  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argument\_optional # argument :optional  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# cast - should be either a lambda taking one argument, or a symbol  
> &nbsp;&nbsp;&nbsp;&nbsp;# designation one of the built in casts defined in Main::Cast. supported  
> &nbsp;&nbsp;&nbsp;&nbsp;# types are :boolean|:integer|:float|:numeric|:string|:uri. built-in  
> &nbsp;&nbsp;&nbsp;&nbsp;# casts can be abbreviated  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cast :int  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# validate - should be a lambda taking one argument and returning  
> &nbsp;&nbsp;&nbsp;&nbsp;# true|false  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;validate{|int| int == 42}  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# synopsis - should be a concise characterization of the paramter. a  
> &nbsp;&nbsp;&nbsp;&nbsp;# default synopsis is built automatically from the parameter. this  
> &nbsp;&nbsp;&nbsp;&nbsp;# information is displayed in the usage message  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;synopsis '--foo'  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# description - a longer description of the paramter. it appears in the  
> &nbsp;&nbsp;&nbsp;&nbsp;# usage also.  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description 'a long description of foo'  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# arity - indicates how many times the parameter should appear on the  
> &nbsp;&nbsp;&nbsp;&nbsp;# command line. the default is one. negative arities are supported and  
> &nbsp;&nbsp;&nbsp;&nbsp;# follow the same rules as ruby methods/procs.  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arity 2  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# default - you can provide a default value in case none is given. the  
> &nbsp;&nbsp;&nbsp;&nbsp;# alias 'defaults' reads a bit nicer when you are giving a list of  
> &nbsp;&nbsp;&nbsp;&nbsp;# defaults for paramters of \> 1 arity  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaults 40, 2  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;# you can add custom per-parameter error handlers using the following  
> &nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error :before do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this fires \*before\* normal error handling using #instance\_eval...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this fires \*instead of\* normal error handling using  
> #instance\_eval...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error :after do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts 'this fires \*after\* normal error handling using #instance\_eval...'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;}
> 
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;# INSTANCE LEVEL API #  
> &nbsp;&nbsp;###########################################################################  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;# you must define a run method. it is the only method you must define.  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;def run  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# all parameters are available in the 'params' hash and via the alias  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 'param'. it can be indexed via string or symbol. the values are all  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Main::Parameter objects  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo = params['foo']  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# the given? method indicates whether or not the parameter was given on  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# the commandline/environment, etc. in particular this will not be true  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# when a default value was specified but no parameter was given  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo.given?  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# the list of all values can be retrieved via 'values'. note that this  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# is always an array.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p foo.values  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# the \_\_first\_\_ value can be retrieved via 'value'. note that this  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# never an array.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p foo.value  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# the methods debug|info|warn|error|fatal are delegated to the logger  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# object  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info{ "this goes to the log" }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# you can set the exit\_status at anytime. this status is used when  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# exiting the program. exceptions cause this to be ext\_failure if, and  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# only if, the current value was exit\_success. in otherwords an  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# un-caught exception always results in a failing exit\_status  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit\_status exit\_failure  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# a few shortcuts both set the exit\_status and exit the program.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit\_success!  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit\_failure!  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit\_warn!  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;}
> 
> --  
> -a  
> --  
> be kind whenever possible... it is always possible - h.h. the 14th dalai lama
