Ridiculously easy git-style binaries.
This gem uses trollop
for option parsing
gem install jashmenn-git-style-binaries --source=http://gems.github.com
Checkout the new screencast!
cd `gem env gemdir`/gems/jashmenn-git-style-binaries-0.1.4/test/fixtures
./wordpress -h
./wordpress help post
Lets use the imaginary wordpress
gem. Let's say we have three different
actions we want to specify:
- categories
- list
- post
Each command has its own binary in a directory structure like this:
bin/
|-- wordpress
|-- wordpress-categories
|-- wordpress-list
`-- wordpress-post
The goal is to be able to call commands in this manner:
wordpress -h # gives help summary of all commands
wordpress-list -h # gives long help of wordpress-list
wordpress list -h # ditto
echo "about me" | wordpress-post --title="new post" # posts a new post with that title
Our bin/wordpress
binary is called the primary . Our primary only needs to contain the following line:
#!/usr/bin/env ruby
require 'git-style-binary/command'
git-style-binary
will automatically make this command the primary.
The bin/wordpress-post
binary could contain the following:
#!/usr/bin/env ruby
require 'git-style-binary/command'
GitStyleBinary.command do
short_desc "create a blog post"
banner <<-EOS
Usage: #{command.full_name} #{all_options_string} {content|STDIN}
Posts content to a wordpress blog
EOS
opt :blog, "short name of the blog to use", :default => 'default'
opt :category, "tag/category. specify multiple times for multiple categories", :type => String, :multi => true
opt :title, "title for the post", :required => true, :type => String
opt :type, "type of the content [html|xhtml|text]", :default => 'html', :type => String
run do |command|
command.die :type, "type must be one of [html|xhtml|text]" unless command.opts[:type] =~ /^(x?html|text)$/i
puts "Subcommand name: #{command.name.inspect}"
puts "Options: #{command.opts.inspect}"
puts "Remaining arguments: #{command.argv.inspect}"
end
end
And so on with the other binaries.
Now if we run wordpress -h
we get the following output:
NAME
wordpress
VERSION
0.0.1 (c) 2009 Nate Murray - local
SYNOPSIS
wordpress [--version] [--test-primary] [--help] [--verbose] COMMAND [ARGS]
SUBCOMMANDS
wordpress-categories
do something with categories
wordpress-help
get help for a specific command
wordpress-list
list blog postings
wordpress-post
create a blog post
See 'wordpress help COMMAND' for more information on a specific command.
OPTIONS
-v, --verbose
verbose
-t, --test-primary=<s>
test an option on the primary
-e, --version
Print version and exit
-h, --help
Show this message
Default options, version string, and usage banner are automatically selected for you. The subcommands and their short descriptions are loaded automatically!
You can pass the -h
flag to any one of the subcommands (with or without the
connecting -
) or use the built-in help
subcommand for the same effect. For instance:
$ wordpress help post
NAME
wordpress-post - create a blog post
VERSION
0.0.1 (c) 2009 Nate Murray - local
SYNOPSIS
wordpress-post [--type] [--version] [--test-primary] [--blog] [--help] [--verbose] [--category]
[--title] COMMAND [ARGS] {content|STDIN}
OPTIONS
-v, --verbose
verbose
-t, --test-primary=<s>
test an option on the primary
-b, --blog=<s>
short name of the blog to use (default: default)
-c, --category=<s>
tag/category. specify multiple times for multiple
categories
-i, --title=<s>
title for the post
-y, --type=<s>
type of the content [html|xhtml|text] (default: html)
-e, --version
Print version and exit
-h, --help
Show this message
For more examples, see the binaries in test/fixtures/
.
Often you may want the primary to have its own set of options. Simply call GitStyleBinary.primary
with a block like so:
#!/usr/bin/env ruby
require 'git-style-binary/command'
GitStyleBinary.primary do
version "#{command.full_name} 0.0.1 (c) 2009 Nate Murray - local"
opt :test_primary, "a primary string option", :type => String
run do |command|
puts "Primary Options: #{command.opts.inspect}"
end
end
Primary options are inherited by all subcommands. That means in this case
all subcommands will now get the --test-primary
option available to them as
well as this new version
string.
Option parsing is done by trollop.
git-style-binary
uses this more-or-less exactly. See the trollop
documentation for information on how to setup
the options and flags.
Callbacks are available on the primary and subcommands. Available callbacks currently are before/after_run. These execute before the run block of the command parser and take take one argument, which is the command itself
To get the 'introspection' on the individual binaries every binary is load
ed
on primary help
. We need a way to get that information while not running
every command when calling primary help
. To achieve that you need to put what
will be run in the run
block.
run
yields
a Command
object which contains a number of useful options
such as name
, full_name
, opts
, and argv
.
command.opts
is a hash of the options parsedcommand.argv
is an array of the remaining arguments
- automatic colorization
- automatic paging
Play with the examples in the test/fixtures
directory.
git-style-binary
was written by Nate Murray<nate@natemurray.com>
trollop
was written by William Morgan- Inspiration comes from Ari Lerner's git-style-binaries for PoolParty.rb
colorize.rb
by Michal Kalbarczyk- Automatic less paging by Nathan Weizenbaum
- Color inspiration from Brian Henderson teaching me how to get
man git
colors usingless
on MacOSX
- automagic tab completion - Automatic for subcommands and options for any library that uses this
- Young
- A few places of really ugly code
- A feeling that this could be done in 1/2 lines of code
By Nate Murray and Ari Lerner
The MIT License
Copyright (c) 2009 Nate Murray. See LICENSE for details.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.