• Stars
    star
    109
  • Rank 308,488 (Top 7 %)
  • Language
    Ruby
  • Created over 13 years ago
  • Updated about 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Sensible, minimal simple options parsing and dispatching for Ruby. Build a CLI with no fuss.

Optitron

Sensible options parsing for Ruby!

Optitron strives to be simple, minimal and to do the “right thing” most of the time. The structure is easy: you have global options, a list of commands, and each of those commands takes a number of arguments and options.

Usage

To create an Optitron command line interface (CLI), start with a class you want to wire up as a CLI. In our example, we’ll use the class Runner, which we want to work as a CLI.

class Runner
  def start
    # ... starts
  end

  def stop
    # ... stops
  end

  def status
    # ... reports status
  end
end

To make this class suitable for use as a CLI, either extend Optitron::CLI or include Optitron::ClassDsl. Then, describe each argument as follows:

class Runner < Optitron::CLI
  desc "Starts the process"
  def start
    # ... starts
  end

  desc "Stops the process"
  def stop
    # ... stops
  end

  desc "Report the status"
  def status
    # ... reports status
  end
end

Help command

Help is added by default, but, if you don’t want to use this, include the command dont_use_help in your class. Help is available from either --help or -?.

Arguments

Only methods described will be available to the CLI. If you have a method that needs arguments, simply include them as method arguments. It will respect splats and defaults. For instance

desc "Starts the process"
def start(mode)
  # ... starts
end

Will generate

start [mode]       # Starts the process

In your help file.

desc "Starts the process"
def start(mode = 'production')
  # ... starts
end

Will generate

start <mode="production">       # Starts the process

And

desc "Starts the process"
def start(*modes)
  # ... starts
end

Will generate

start <modes1 modes2 ...>       # Starts the process

As well, you can provide type hints to the args:

desc "Does something awesome"
arg_types :numeric, :string, :boolean
def start(number, string, truth)
  # ... does something
end

Will generate

start [number] [string] [truth]       # Does something awesome

And those arguments have to conform to the types given. For instance, calling this with

start 123 something flase

Will produce the error Truth is invalid. Calling with

start 123 something true

however, will correctly invoke the method.

These same arg type hints can be provided by ending your arguments in _type. The accepted types are: float, string, int, numeric, array, hash. For example

desc "Does something awesome"
def start(number_int, something_string, opt_boolean)
  # ... does something
end

Options

Options are specified with the opt method in your class, as follows:

class Runner < Optitron::CLI
  desc "Starts the process"
  opt "verbose"
  opt "environment", :in => ['development', 'production', 'staging', 'test']
  def start
    # ... starts
  end

  # .. more methods

end

If you need an option available for all methods, use class_opt to specify it.

class Runner < Optitron::CLI
  class_opt "verbose", "Be loud"

  # ... your methods
end

The last line in your runner has to be the class name and dispatch. This will parse ARGV and execute normal dispatching on it.

class Runner < Optitron::CLI
  # ... your methods
end
Runner.dispatch

Options can have defaults, types and inclusion checks. Here are all the options available on an opt:

:default

This allows you to specify a default value. The type of value is used to infer the type required for this option. This can be over-ridden with :type.

:short_name

This allows you to set a short name for the option, though, one will be assigned automatically from the short names available.

:run

This allows you to run an arbitrary block for an option. The proc will be called with the value, and the response object.

:in

This allows you to test for inclusion in a range or array (or anything that responds to #include? and #first). The first item in the object will be used to infer the type. This can be over-ridden with :type.

:required

This allows you to force an option to be required. False by default.

:type

This allows you to specify the type. Acceptable options are :numeric, :array, :hash, :string or :boolean.

With boolean type, you can additionally supply :use_no => true to be able to use –no-option style options.

Stand alone usage

You can create parsers and parse using them.

@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
}

To generate help, use the #help method.

@parser.help

Which returns,

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

The parse method can parse a list of arguments. For example, @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, you can get back friendly error messages using #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"]

The response from #parse can also be used to dispatch. All that’s required is the target object be able to respond to params=.

For example

class Runner
  attr_accessor :params
  def install(file)
    puts "I'm installing #{file} with #{params.inspect}"
  end
end

parser = Optitron.new {
  help
  opt 'verbose', "Be very loud"
  cmd "install", "This installs things" do
    arg "file", "The file to install"
  end
}

parser.parse(%w(install this_file -v)).dispatch(Runner.new)

Will output

I'm installing this_file with {"help"=>false, "verbose"=>true}

More Repositories

1

spoiler-alert

SPOILER ALERT! A happy little bit of javascript to hide spoilers on your site.
JavaScript
472
star
2

jsonpath

Ruby implementation of http://goessner.net/articles/JsonPath/
Ruby
433
star
3

ghostbuster

Integration testing ftw
CoffeeScript
276
star
4

http_router

A kick-ass HTTP router for use in Rack
Ruby
199
star
5

usher

Pure ruby general purpose router with interfaces for rails, rack, email or choose your own adventure
Ruby
122
star
6

noexec

NO MORE BUNDLE EXEC
Ruby
109
star
7

apiary

Convert your existing class into an EM-based API
Ruby
98
star
8

swearjar

Put another nickel in the swearjar. Simple profanity detection with content analysis.
Ruby
68
star
9

sherpa

Simple URI routing and generation in Javascript
JavaScript
60
star
10

tcplock

Throttle TCP connections to anything!
JavaScript
57
star
11

tokyo_cache_cow

Memcache server with substring deleting and aggregate functions
Ruby
47
star
12

ak47

Reload anything
Ruby
40
star
13

exif-be-gone

Remove exif data using a node.js transform stream
JavaScript
32
star
14

chirpstream

An EventMachine-based client for http://chirpstream.twitter.com.
Ruby
31
star
15

callsite

Caller/backtrace parser with some useful utilities for manipulating the load path, and doing other relative things.
Ruby
23
star
16

tumbler

Let's make gem development fun! Tumbler provides common gem management tasks using a common set of 'best practices' out of the box.
Ruby
22
star
17

rack-rewrite

Rack middleware for request rewriting
Ruby
19
star
18

rack-cache-while-revalidate

Works with Rack::Cache to serve up stale data while silently revalidating
Ruby
18
star
19

spanner

Natural language time span parsing
Ruby
18
star
20

em-ventually

Eventually, your tests should pass in EventMachine
Ruby
16
star
21

fuzzyhash

A fuzzy weird hash that can store string or ... regexs?
Ruby
16
star
22

load_path_find

Useful tools for looking for files on the $LOAD_PATH
Ruby
15
star
23

has_many_versions

Versioning for has_many relationships
Ruby
14
star
24

meddler

Hey, someone meddled with my middleware!
Ruby
14
star
25

pitcrew

AsyncIO-powered python DSL for running commands locally, on docker, or over ssh.
Python
13
star
26

spackle

Sensible DSL for ESI definition within Rails
Ruby
13
star
27

anybase

Arbitrary number bases
Ruby
13
star
28

hintable_levenshtein

levenshtein with the ability to inject hints into the ruleset for possibly cheaper rules
Ruby
12
star
29

rack-console

Rack Console that lets us take a look at a running rack app
Ruby
12
star
30

jsont

ruby implementation of http://goessner.net/articles/jsont/
Ruby
12
star
31

data_bindings

Schemas for schemaless data
Ruby
9
star
32

esi-for-rack

ESI implementation for Rack
Ruby
9
star
33

respond_to

Easy way to make respond_to? matchers for case statements.
Ruby
9
star
34

sms

Add an sms method to Kernel, because sms is the new puts. Or, sms from the command line, sms is also the new echo.
Ruby
9
star
35

em-http-monitor

Monitor, request recording and playback for em-http-request
Ruby
9
star
36

rack-tamperproof

Rack middleware that provides tamper-proof cookies
Ruby
8
star
37

dirge

Relative require, relative autoload and __DIR__
Ruby
8
star
38

messed

Framework around short message paradigms (read: twitter, irc, sms)
Ruby
8
star
39

kik

kik off a process if no listener exists on a port
Ruby
7
star
40

parameters_extra

Get back more detailed information about the arguments for a method
Ruby
7
star
41

gradients

Generate gradients because colors are fun.
Ruby
7
star
42

slick-chrome

Transfer files in chrome
JavaScript
7
star
43

http_router_sinatra

Kick ass router for Sinatra based on http_router
Ruby
7
star
44

emjay

Kickass Javascript templating for node.js and others.
JavaScript
7
star
45

padrino-presentation

Padrino Presentation for LSRC
7
star
46

decaying_bloomfilter

Time Decaying Bloom Filter - Much like a bloom-filter except keys inserted decay over-time.
Ruby
6
star
47

gameplan

Plan your game yo.
JavaScript
6
star
48

sabbath

REST for your work (queues)
Ruby
6
star
49

liposuction

Maybe us other protocols want middleware too. (And proxy servers)
Ruby
5
star
50

rack-capabilities

Discover just what rack can do (rather, what middleware you have installed)
Ruby
5
star
51

hashify

Simple to/from hash creation for your favorite classes
Ruby
5
star
52

esi_attribute_language

ESI Attribute Language
Ruby
5
star
53

shell_tools

Some common shell utilities
Ruby
5
star
54

dressmaker

Application templating in ruby. Define beautiful patterns and cut them out.
Ruby
5
star
55

q

Fast, fun, east HTML generation from Ruby
Ruby
4
star
56

tokyodystopia-ruby

TokyoDystopia Ruby bindings
C
4
star
57

queueing_proxy

Queueing HTTP proxy
Ruby
4
star
58

tumbler2

Ruby
4
star
59

arduino-examples

3
star
60

duck_duck_twilio

DuckDuckGo + Twilio SMS = WTF
Ruby
3
star
61

smatrix

(sparse/streaming)matrix
Ruby
3
star
62

dreamerq

That queue I've been dreaming about
JavaScript
3
star
63

passenger_reaper

Gemification of https://gist.github.com/596401/db750535df61e679aad69e8d9c9750f8640a234f
Ruby
3
star
64

plaza

An open modular web framework for the hacker in us all
Ruby
3
star
65

rack-regenerate

Rack middleware for periodic cache regeneration
Ruby
3
star
66

testable_examples

Test your examples!
Ruby
3
star
67

jacket

Beanstalkd monitoring, reporting and graphs!
JavaScript
3
star
68

code_stats

Brief code stats from your rakefile
Ruby
3
star
69

bundler_push_host

Set the bundler push host for the rake tasks
Ruby
3
star
70

yippee

Easily manage your requirements.txt files!
Python
2
star
71

sonjas-demo-app

Ruby
2
star
72

em-memcache-client

async Memcache client for Ruby EventMachine
Ruby
2
star
73

assetpack

Pack your assets before you leave home
JavaScript
2
star
74

skiplist

C
2
star
75

tryleapjs

Tryleapjs.com
JavaScript
2
star
76

jpake

J-pake implementation using ECC
Go
2
star
77

squeezy

Asset compression service
Ruby
2
star
78

futures

Reading values that aren't quite set yet.
Ruby
2
star
79

led-display

Display emulator for that weird thing in the HackLab
Ruby
2
star
80

escaping_params

Crazy idea for autoescaping params
Ruby
2
star
81

castle-attachmentstein

Ze attachments! Zee!
2
star
82

gravitypong

Gravity experiement
2
star
83

dsl_helper

Helpers for creating internal DSLs
Ruby
2
star
84

barbu

JavaScript
2
star
85

bridge-analysis

Some lin files with a simple parser
Ruby
2
star
86

envs

Sync your .env and .env.default files
Ruby
1
star
87

ReadEase

Unicode text normalizer browser extension
JavaScript
1
star
88

update_via_dnssec

Publish and update git repo over DNSSEC
Ruby
1
star
89

joshbuddy.github.com

Mah pages
1
star
90

changes

Make changes in multiple documents easy to see!
JavaScript
1
star