Optitron

Sensible options parsing

You can specify lots of different commands with options

@parser = Optitron.new {
  help
  opt 'verbose', "Be very loud"
  cmd "install", "This installs things" do
    arg "file", "The file to install"
  end
  cmd "show", "This shows things" do
    arg "first", "The first thing to show"
    arg "second", "The second optional thing to show", :required => false
  end
  cmd "kill", "This kills things" do
    opt "pids", "A list of pids to kill", :type => :array
    opt "pid", "A pid to kill", :type => :numeric
    opt "names", "Some sort of hash", :type => :hash
  end
  cmd "join", "This joins things" do
    arg "thing", "Stuff to join", :type => :greedy
  end
}

Want to see the help?

@parser.help

Will output:

Commands

show [first] <second>          # This shows things
install [file]                 # This installs things
kill                           # This kills things
  -p/--pids=[ARRAY]            # A list of pids to kill
  -P/--pid=[NUMERIC]           # A pid to kill
  -n/--names=[HASH]            # Some sort of hash
join [thing1 thing2 ...]       # This joins things

Global options

-v/--verbose                   # Be very loud

And @parser.parse(%w(-v install file)) gives back:

response = @parser.parse(%w(-v install file))
response.command
=> "install"
response.args
=> ["file"]
response.params
=> {"verbose" => true}

If you try parsing invalid parameters, get back friendly error messages

@parser.parse(%w()).error_messages
=> ["Unknown command"]
@parser.parse(%w(something)).error_messages
=> ["Something is an unknown command"]
@parser.parse(%w(install)).error_messages
=> ["File is required"]
@parser.parse(%w(kill --pid=something)).error_messages
=> ["Pid is invalid"]

Usage in a binary

To use this in a file, create a parser, and tell it to dispatch to your favourite object. For instance, save this down to test.rb

class Runner
  def install(file, opts)
    puts "installing #{file} with #{opts}!"
  end
end

Optitron.dispatch(Runner.new) {
  opt 'verbose', "Be very loud"
  cmd "install", "This installs things" do
    arg "file", "The file to install"
  end
  cmd "show", "This shows things" do
    arg "first", "The first thing to show"
    arg "second", "The second optional thing to show", :required => false
  end
  cmd "kill", "This kills things" do
    opt "pids", "A list of pids to kill", :type => :array
    opt "pid", "A pid to kill", :type => :numeric
    opt "names", "Some sort of hash", :type => :hash
  end
  cmd "join", "This joins things" do
    arg "thing", "Stuff to join", :type => :greedy
  end
}

Now, try running it.

crapbook-pro:optitron joshua$ ruby test.rb 
Unknown command

crapbook-pro:optitron joshua$ ruby test.rb install
File is required

crapbook-pro:optitron joshua$ ruby test.rb install file
installing file with {"verbose"=>false}!

crapbook-pro:optitron joshua$ ruby test.rb install file --verbose
installing file with {"verbose"=>true}!

Usage in a class

require 'optitron'

class Runner < Optitron::CLI

  class_opt 'verbose'
  use_help

  desc "Install stuff"
  opt 'force'
  def install(file, source)
    puts "install some things #{file} from #{source.inspect} #{params.inspect}"
  end
end

Runner.dispatch

Running this gives you

crapbook-pro:optitron joshua$ ruby ideal.rb --help
Commands

install [file] <source>       # Install stuff
  -f/--force                  

Global options

-v/--verbose                  
-?/--help                     # Print help message

crapbook-pro:optitron joshua$ ruby ideal.rb install
File is required

crapbook-pro:optitron joshua$ ruby ideal.rb install file
installing file from yourmom with params: {"help"=>false, "force"=>false, "verbose"=>false}

crapbook-pro:optitron joshua$ ruby ideal.rb install file yourdad
installing file from yourdad with params: {"help"=>false, "force"=>false, "verbose"=>false}

crapbook-pro:optitron joshua$ ruby ideal.rb install file yourdad -v
installing file from yourdad with params: {"help"=>false, "force"=>false, "verbose"=>true}