require 'clio/usage/command' require 'clio/usage/parser' module Clio # = Usage # # Uasge provides a verstile but easy to use system of describing # a commandline interface. # # == Underlying Fluent and Block Notation # # Underlying all usage is a fluent interface for decalaring # a commandline's structure. Here is an example of using # this DSL, albeit rather brutely. # # usage = Clio::Usage.new # usage.command(:document).help('generate documentation') # usage.command(:document).option(:output, :o).type('FILE') # usage.command(:document).option(:output).help('output directory') # usage.option(:verbose, :V).help('verbose output') # usage.option(:quiet, :q).help('run silently').xor(:V) # # The example defines a subcommand 'document' that can take an # 'output' option, and two mutually excluive universal options, # 'verbose' and 'quiet', with respective one-letter aliases. # # As you might expect the fluent notation can be broken down into # block notation which is easier to read. # # usage = Usage.new # usage do # option(:verbose, :v) do # help('verbose output') # end # option(:quiet, :q) do # help('run silently') # xor(:V) # end # command(:document) do # help('generate documentation') # option(:output, :o) do # type('FILE') # help('output directory') # end # argument('files') do # multiple # end # end # end # # Clearly block notation is DRY and more elegant the the previous fluent # version, but fluent notation is important because it allows the usage # object to be easily passed around and augmented as needed. # #-- # == Abbriviated Notation # # While comprehensble, the core Usage DSL can be a somewhat verbose. # So abbriviated forms of these methods are provided. These methods # go one step further as well, and allow for some additional arguments. # # cli.usage do # opt('verbose -v', 'verbose output') | # opt('quiet -q' , 'run silently') # cmd('document', 'generate documentation') do # opt('output=FILE -o', 'output directory') # arg('FILE*') # end # end # # Notice the use of '|'. This allows us to define mutual exclusion # without resorting to #xor as was done in the first example. #++ # # = Method Notation # # This notation is very elegant, but slightly more limited in scope. # For instance, subcommands that use non-letter characters, such as ':', # can not be described with this notation. # # usage.document('', '--output=FILE -o') # usage('--verbose -V','--quiet -q') # # usage.help( # 'document' , 'generate documentation', # 'validate' , 'run tests or specifications', # '--verbose' , 'verbose output', # '--quiet' , 'run siltently' # ) # # usage.document.help( # '--output', 'output directory' # 'file*', 'files to document' # ) # # This notation is slightly more limited in scope... so... # # usage.command(:document, '--output=FILE -o', '') # # == Bracket Shorthand Notation # # The core notation can be somewhat verbose. As a further convenience # commandline usage can be defined with a brief bracket shorthand. # This is especailly useful when the usage is simple and statically defined. # # usage['document']['--output=FILE -o']['FILE*'] # # Using a little creativity to improve readabilty we can convert the # whole example from above using this notation. # # usage['--verbose -V', 'verbose output' ] \ # ['--quiet -q', 'run silently' ] \ # ['document', 'generate documention' ] \ # [ '--output=FILE -o', 'output directory' ] \ # [ 'FILE*', 'files to document' ] # # Alternately the help information can be left out and defined in # a seprate set of usage calls. # # usage['--verbose -V']['--quiet -q'] \ # ['document']['--output=FILE -o']['FILE*'] # # usage.help( # 'document' , 'generate documentation', # 'validate' , 'run tests or specifications', # '--verbose' , 'verbose output', # '--quiet' , 'run siltently' # ) # # usage['document'].help( # '--output', 'output directory' # 'FILE', 'files to docment' # ) # # A little more verbose, but a bit more intutive. # # == "Alien" Notation # # As a side note, it is easy enough to alias #[] to #_, so alternatively # one code create a variant shorthand written as: # # usage do # _ '--verbose -V', 'verbose output' # _ '--quiet -q', 'run silently' # _ 'document', 'generate documentation' do # _ '--output=FILE -o', 'output directory' # _ 'FILE*', 'files to document' # end # end # # To demonsrtate it's equvalence to bracket shorthand, it can be chained as well. # # usage._('document')._('--output=FILE -o')._('FILE*') # # This notation is not supported by default, but if it is more your style # it is easy enough to implement by extending Clio::Usage::Command like this: # # class Clio::Usage::Command # alias_method :_, :[] # end # # == Combining Notations # # Since the various notations all translate to same underlying # structures, they can be mixed and matched as suites ones taste. # For example we could mix Method Notation and Bracket Notation. # # usage.document['--output=FILE -o']['file*'] # usage['--verbose -V']['--quiet -q'] # # The important thing to keep in mind when doing this is what is # returned by each type of usage call. # module Usage def self.new(name=nil, &block) Command.new(name, &block) end end#module Usage end#module Clio