diff --git a/bin/yadr/default_libs.rb b/bin/yadr/default_libs.rb
new file mode 100755
index 00000000..900e095d
--- /dev/null
+++ b/bin/yadr/default_libs.rb
@@ -0,0 +1,2 @@
+Dir[File.join(File.dirname(__FILE__),"lib/**/lib")].each {|dir| $LOAD_PATH << dir}
+require 'git-style-binary/command'
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/README.markdown b/bin/yadr/lib/git-style-binaries-0.1.11/README.markdown
new file mode 100644
index 00000000..b63fa39a
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/README.markdown
@@ -0,0 +1,280 @@
+git-style-binaries
+==================
+
+Ridiculously easy git-style binaries.
+
+This gem uses [`trollop`](http://trollop.rubyforge.org/) for option parsing
+
+## Installation
+
+ gem install jashmenn-git-style-binaries --source=http://gems.github.com
+
+## Screencast
+
+Checkout the new screencast!
+
+
+
+## Try it out
+
+ cd `gem env gemdir`/gems/jashmenn-git-style-binaries-0.1.4/test/fixtures
+ ./wordpress -h
+ ./wordpress help post
+
+## Goal
+
+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
+
+## Example code
+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.
+
+## Running the 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=
+ 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=
+ test an option on the primary
+
+
+ -b, --blog=
+ short name of the blog to use (default: default)
+
+
+ -c, --category=
+ tag/category. specify multiple times for multiple
+ categories
+
+
+ -i, --title=
+ title for the post
+
+
+ -y, --type=
+ 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/`.
+
+## Primary options
+
+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
+
+Option parsing is done by [trollop](http://trollop.rubyforge.org/).
+`git-style-binary` uses this more-or-less exactly. See the [trollop
+documentation](http://trollop.rubyforge.org/) for information on how to setup
+the options and flags.
+
+## Callbacks
+
+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
+
+## The `run` block
+
+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 parsed
+* `command.argv` is an array of the remaining arguments
+
+## Features
+* automatic colorization
+* automatic paging
+
+## To Learn more
+
+Play with the examples in the `test/fixtures` directory.
+
+## Credits
+* `git-style-binary` was written by Nate Murray ``
+* `trollop` was written by [William Morgan](http://trollop.rubyforge.org/)
+* Inspiration comes from Ari Lerner's [git-style-binaries](http://blog.xnot.org/2008/12/16/git-style-binaries/) for [PoolParty.rb](http://poolpartyrb.com)
+* [`colorize.rb`](http://colorize.rubyforge.org) by Michal Kalbarczyk
+* Automatic less paging by [Nathan Weizenbaum](http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby)
+* Color inspiration from [Brian Henderson](http://xcombinator.com) teaching me how to get `man git` colors using `less` on MacOSX
+
+## TODO
+* automagic tab completion - Automatic for subcommands and options for any library that uses this
+
+## Known Bugs/Problems
+* Young
+* A few places of really ugly code
+* A feeling that this could be done in 1/2 lines of code
+
+## Authors
+By Nate Murray and Ari Lerner
+
+## Copyright
+
+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.
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/Rakefile b/bin/yadr/lib/git-style-binaries-0.1.11/Rakefile
new file mode 100644
index 00000000..2d0d50bb
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/Rakefile
@@ -0,0 +1,65 @@
+require 'rubygems'
+require 'rake'
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "git-style-binaries"
+ gem.description = %Q{Ridiculously easy git-style binaries}
+ gem.summary =<<-EOF
+ Add git-style binaries to your project easily.
+ EOF
+ gem.email = "nate@natemurray.com"
+ gem.homepage = "http://github.com/jashmenn/git-style-binaries"
+ gem.authors = ["Nate Murray"]
+ gem.add_dependency 'trollop'
+ gem.add_dependency 'shoulda' # for running the tests
+
+ excludes = /(README\.html)/
+ gem.files = (FileList["[A-Z]*.*", "{bin,examples,generators,lib,rails,spec,test,vendor}/**/*", 'Rakefile', 'LICENSE*']).delete_if{|f| f =~ excludes}
+ gem.extra_rdoc_files = FileList["README*", "ChangeLog*", "LICENSE*"].delete_if{|f| f =~ excludes}
+ end
+rescue LoadError
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
+end
+
+require 'rake/testtask'
+Rake::TestTask.new(:test) do |test|
+ test.libs << 'lib' << 'test'
+ test.pattern = 'test/**/*_test.rb'
+ test.verbose = true
+end
+
+begin
+ require 'rcov/rcovtask'
+ Rcov::RcovTask.new do |test|
+ test.libs << 'test'
+ test.pattern = 'test/**/*_test.rb'
+ test.verbose = true
+ end
+rescue LoadError
+ task :rcov do
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
+ end
+end
+
+
+task :default => :test
+
+require 'rake/rdoctask'
+require 'yaml'
+Rake::RDocTask.new do |rdoc|
+ if File.exist?('VERSION.yml')
+ config = YAML.load(File.read('VERSION.yml'))
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
+ else
+ version = ""
+ end
+
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "git-style-binaries #{version}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+task :bump => ['version:bump:patch', 'gemspec', 'build']
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/VERSION.yml b/bin/yadr/lib/git-style-binaries-0.1.11/VERSION.yml
new file mode 100644
index 00000000..43ec5478
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/VERSION.yml
@@ -0,0 +1,4 @@
+---
+:patch: 10
+:major: 0
+:minor: 1
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/colorize.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/colorize.rb
new file mode 100644
index 00000000..c4d695ab
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/colorize.rb
@@ -0,0 +1,198 @@
+#
+# Colorize String class extension.
+#
+class String
+
+ #
+ # Version string
+ #
+ COLORIZE_VERSION = '0.5.6'
+
+ #
+ # Colors Hash
+ #
+ COLORS = {
+ :black => 0,
+ :red => 1,
+ :green => 2,
+ :yellow => 3,
+ :blue => 4,
+ :magenta => 5,
+ :cyan => 6,
+ :white => 7,
+ :default => 9,
+
+ :light_black => 10,
+ :light_red => 11,
+ :light_green => 12,
+ :light_yellow => 13,
+ :light_blue => 14,
+ :light_magenta => 15,
+ :light_cyan => 16,
+ :light_white => 17
+ }
+
+ #
+ # Modes Hash
+ #
+ MODES = {
+ :default => 0, # Turn off all attributes
+ #:bright => 1, # Set bright mode
+ :underline => 4, # Set underline mode
+ :blink => 5, # Set blink mode
+ :swap => 7, # Exchange foreground and background colors
+ :hide => 8 # Hide text (foreground color would be the same as background)
+ }
+
+ protected
+
+ #
+ # Set color values in new string intance
+ #
+ def set_color_parameters( params )
+ if (params.instance_of?(Hash))
+ @color = params[:color]
+ @background = params[:background]
+ @mode = params[:mode]
+ @uncolorized = params[:uncolorized]
+ self
+ else
+ nil
+ end
+ end
+
+ public
+
+ #
+ # Change color of string
+ #
+ # Examples:
+ #
+ # puts "This is blue".colorize( :blue )
+ # puts "This is light blue".colorize( :light_blue )
+ # puts "This is also blue".colorize( :color => :blue )
+ # puts "This is blue with red background".colorize( :color => :light_blue, :background => :red )
+ # puts "This is blue with red background".colorize( :light_blue ).colorize( :background => :red )
+ # puts "This is blue text on red".blue.on_red
+ # puts "This is red on blue".colorize( :red ).on_blue
+ # puts "This is red on blue and underline".colorize( :red ).on_blue.underline
+ # puts "This is blue text on red".blue.on_red.blink
+ #
+ def colorize( params )
+
+ unless STDOUT.use_color
+ return self unless STDOUT.isatty
+ end
+ return self if ENV['NO_COLOR']
+
+ begin
+ require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
+ rescue LoadError
+ raise 'You must gem install win32console to use color on Windows'
+ end
+
+ color_parameters = {}
+
+ if (params.instance_of?(Hash))
+ color_parameters[:color] = COLORS[params[:color]]
+ color_parameters[:background] = COLORS[params[:background]]
+ color_parameters[:mode] = MODES[params[:mode]]
+ elsif (params.instance_of?(Symbol))
+ color_parameters[:color] = COLORS[params]
+ end
+
+ color_parameters[:color] ||= @color || 9
+ color_parameters[:background] ||= @background || 9
+ color_parameters[:mode] ||= @mode || 0
+
+ color_parameters[:uncolorized] ||= @uncolorized || self.dup
+
+ # calculate bright mode
+ color_parameters[:color] += 50 if color_parameters[:color] > 10
+
+ color_parameters[:background] += 50 if color_parameters[:background] > 10
+
+ return "\033[#{color_parameters[:mode]};#{color_parameters[:color]+30};#{color_parameters[:background]+40}m#{color_parameters[:uncolorized]}\033[0m".set_color_parameters( color_parameters )
+ end
+
+
+ #
+ # Return uncolorized string
+ #
+ def uncolorize
+ return @uncolorized || self
+ end
+
+ #
+ # Return true if sting is colorized
+ #
+ def colorized?
+ return !@uncolorized.nil?
+ end
+
+ #
+ # Make some color and on_color methods
+ #
+ COLORS.each_key do | key |
+ eval <<-"end_eval"
+ def #{key.to_s}
+ return self.colorize( :color => :#{key.to_s} )
+ end
+ def on_#{key.to_s}
+ return self.colorize( :background => :#{key.to_s} )
+ end
+ end_eval
+ end
+
+ #
+ # Methods for modes
+ #
+ MODES.each_key do | key |
+ eval <<-"end_eval"
+ def #{key.to_s}
+ return self.colorize( :mode => :#{key.to_s} )
+ end
+ end_eval
+ end
+
+ class << self
+
+ #
+ # Return array of available modes used by colorize method
+ #
+ def modes
+ keys = []
+ MODES.each_key do | key |
+ keys << key
+ end
+ keys
+ end
+
+ #
+ # Return array of available colors used by colorize method
+ #
+ def colors
+ keys = []
+ COLORS.each_key do | key |
+ keys << key
+ end
+ keys
+ end
+
+ #
+ # Display color matrix with color names.
+ #
+ def color_matrix( txt = "[X]" )
+ size = String.colors.length
+ String.colors.each do | color |
+ String.colors.each do | back |
+ print txt.colorize( :color => color, :background => back )
+ end
+ puts " < #{color}"
+ end
+ String.colors.reverse.each_with_index do | back, index |
+ puts "#{"|".rjust(txt.length)*(size-index)} < #{back}"
+ end
+ end
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/core.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/core.rb
new file mode 100644
index 00000000..70bbf3d4
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/ext/core.rb
@@ -0,0 +1,16 @@
+class Object
+ def returning(value)
+ yield(value)
+ value
+ end unless Object.respond_to?(:returning)
+end
+
+class Symbol
+ def to_proc
+ Proc.new { |*args| args.shift.__send__(self, *args) }
+ end
+end
+
+class IO
+ attr_accessor :use_color
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary.rb
new file mode 100644
index 00000000..fa853c9d
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary.rb
@@ -0,0 +1,88 @@
+$:.unshift(File.dirname(__FILE__))
+require 'rubygems'
+
+# Load the vendor gems
+$:.unshift(File.dirname(__FILE__) + "/../vendor/gems")
+%w(trollop).each do |library|
+ begin
+ require "#{library}/lib/#{library}"
+ rescue LoadError
+ begin
+ require 'trollop'
+ rescue LoadError
+ puts "There was an error loading #{library}. Try running 'gem install #{library}' to correct the problem"
+ end
+ end
+end
+
+require 'ext/core'
+require 'ext/colorize'
+require 'git-style-binary/autorunner'
+Dir[File.dirname(__FILE__) + "/git-style-binary/helpers/*.rb"].each {|f| require f}
+
+module GitStyleBinary
+
+ class << self
+ include Helpers::NameResolver
+ attr_accessor :current_command
+ attr_accessor :primary_command
+ attr_writer :known_commands
+
+ # If set to false GitStyleBinary will not automatically run at exit.
+ attr_writer :run
+
+ # Automatically run at exit?
+ def run?
+ @run ||= false
+ end
+
+ def parser
+ @p ||= Parser.new
+ end
+
+ def known_commands
+ @known_commands ||= {}
+ end
+
+ def load_primary
+ unless @loaded_primary
+ @loaded_primary = true
+ primary_file = File.join(binary_directory, basename)
+ load primary_file
+
+ if !GitStyleBinary.primary_command # you still dont have a primary load a default
+ GitStyleBinary.primary do
+ run do |command|
+ educate
+ end
+ end
+ end
+ end
+ end
+
+ def load_subcommand
+ unless @loaded_subcommand
+ @loaded_subcommand = true
+ cmd_file = GitStyleBinary.binary_filename_for(GitStyleBinary.current_command_name)
+ load cmd_file
+ end
+ end
+
+ def load_command_file(name, file)
+ self.name_of_command_being_loaded = name
+ load file
+ self.name_of_command_being_loaded = nil
+ end
+
+ # UGLY eek
+ attr_accessor :name_of_command_being_loaded
+
+ end
+end
+
+at_exit do
+ unless $! || GitStyleBinary.run?
+ command = GitStyleBinary::AutoRunner.run
+ exit 0
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/autorunner.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/autorunner.rb
new file mode 100644
index 00000000..be769c99
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/autorunner.rb
@@ -0,0 +1,21 @@
+require 'git-style-binary/parser'
+
+module GitStyleBinary
+class AutoRunner
+
+ def self.run(argv=ARGV)
+ r = new
+ r.run
+ end
+
+ def run
+ unless GitStyleBinary.run?
+ if !GitStyleBinary.current_command
+ GitStyleBinary.load_primary
+ end
+ GitStyleBinary.current_command.run
+ end
+ end
+
+end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/command.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/command.rb
new file mode 100644
index 00000000..296588f7
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/command.rb
@@ -0,0 +1,204 @@
+require 'git-style-binary'
+
+module GitStyleBinary
+ def self.command(&block)
+ returning Command.new(:constraints => [block]) do |c|
+ c.name ||= (GitStyleBinary.name_of_command_being_loaded || GitStyleBinary.current_command_name)
+ GitStyleBinary.known_commands[c.name] = c
+
+ if !GitStyleBinary.current_command || GitStyleBinary.current_command.is_primary?
+ GitStyleBinary.current_command = c
+ end
+ end
+ end
+
+ def self.primary(&block)
+ returning Primary.new(:constraints => [block]) do |c|
+ c.name ||= (GitStyleBinary.name_of_command_being_loaded || GitStyleBinary.current_command_name)
+ GitStyleBinary.known_commands[c.name] = c
+
+ GitStyleBinary.primary_command = c unless GitStyleBinary.primary_command
+ GitStyleBinary.current_command = c unless GitStyleBinary.current_command
+ end
+ end
+
+ class Command
+ class << self
+ def defaults
+ lambda do
+ name_desc "#{command.full_name}\#{command.short_desc ? ' - ' + command.short_desc : ''}" # eval jit
+ version_string = defined?(VERSION) ? VERSION : "0.0.1"
+ version "#{version_string} (c) #{Time.now.year}"
+ banner <<-EOS
+#{"SYNOPSIS".colorize(:red)}
+ #{command.full_name.colorize(:light_blue)} #{all_options_string}
+
+#{"SUBCOMMANDS".colorize(:red)}
+ \#{GitStyleBinary.pretty_known_subcommands.join("\n ")}
+
+ See '#{command.full_name} help COMMAND' for more information on a specific command.
+ EOS
+
+ opt :verbose, "verbose", :default => false
+ end
+ end
+ end
+
+ attr_reader :constraints
+ attr_reader :opts
+ attr_accessor :name
+
+ def initialize(o={})
+ o.each do |k,v|
+ eval "@#{k.to_s}= v"
+ end
+ end
+
+ def parser
+ @parser ||= begin
+ p = Parser.new
+ p.command = self
+ p
+ end
+ end
+
+ def constraints
+ @constraints ||= []
+ end
+
+ def run
+ GitStyleBinary.load_primary unless is_primary?
+ GitStyleBinary.load_subcommand if is_primary? && running_subcommand?
+ load_all_parser_constraints
+ @opts = process_args_with_subcmd
+ call_parser_run_block
+ self
+ end
+
+ def running_subcommand?
+ GitStyleBinary.valid_subcommand?(GitStyleBinary.current_command_name)
+ end
+
+ def load_all_parser_constraints
+ @loaded_all_parser_constraints ||= begin
+ load_parser_default_constraints
+ load_parser_primary_constraints
+ load_parser_local_constraints
+ true
+ end
+ end
+
+ def load_parser_default_constraints
+ parser.consume_all([self.class.defaults])
+ end
+
+ def load_parser_primary_constraints
+ parser.consume_all(GitStyleBinary.primary_command.constraints)
+ end
+
+ def load_parser_local_constraints
+ cur = GitStyleBinary.current_command # see, why isn't 'this' current_command?
+
+ unless self.is_primary? && cur == self
+ # TODO TODO - the key lies in this function. figure out when you hav emore engergy
+ # soo UGLY. see #process_parser! unify with that method
+ # parser.consume_all(constraints) rescue ArgumentError
+ parser.consume_all(cur.constraints)
+ end
+ end
+
+ def call_parser_run_block
+ runs = GitStyleBinary.current_command.parser.runs
+
+ parser.run_callbacks(:before_run, self)
+ parser.runs.last.call(self) # ... not too happy with this
+ parser.run_callbacks(:after_run, self)
+ end
+
+ def process_args_with_subcmd(args = ARGV, *a, &b)
+ cmd = GitStyleBinary.current_command_name
+ vals = process_args(args, *a, &b)
+ parser.leftovers.shift if parser.leftovers[0] == cmd
+ vals
+ end
+
+ # TOOooootally ugly! why? bc load_parser_local_constraints doesn't work
+ # when loading the indivdual commands because it depends on
+ # #current_command. This really sucks and is UGLY.
+ # the todo is to put in 'load_all_parser_constraints' and this works
+ def process_parser!
+ # load_all_parser_constraints
+
+ load_parser_default_constraints
+ load_parser_primary_constraints
+ # load_parser_local_constraints
+ parser.consume_all(constraints)
+
+ # hack
+ parser.consume {
+ opt :version, "Print version and exit" if @version unless @specs[:version] || @long["version"]
+ opt :help, "Show this message" unless @specs[:help] || @long["help"]
+ resolve_default_short_options
+ } # hack
+ end
+
+ def process_args(args = ARGV, *a, &b)
+ p = parser
+ begin
+ vals = p.parse args
+ args.clear
+ p.leftovers.each { |l| args << l }
+ vals # ugly todo
+ rescue Trollop::CommandlineError => e
+ $stderr.puts "Error: #{e.message}."
+ $stderr.puts "Try --help for help."
+ exit(-1)
+ rescue Trollop::HelpNeeded
+ p.educate
+ exit
+ rescue Trollop::VersionNeeded
+ puts p.version
+ exit
+ end
+ end
+
+ def is_primary?
+ false
+ end
+
+ def argv
+ parser.leftovers
+ end
+
+ def short_desc
+ parser.short_desc
+ end
+
+ def full_name
+ # ugly, should be is_primary?
+ GitStyleBinary.primary_name == name ? GitStyleBinary.primary_name : GitStyleBinary.primary_name + "-" + name
+ end
+
+ def die arg, msg=nil
+ p = parser # create local copy
+ Trollop.instance_eval { @p = p }
+ Trollop::die(arg, msg)
+ end
+
+ # Helper to return the option
+ def [](k)
+ opts[k]
+ end
+
+ end
+
+ class Primary < Command
+ def is_primary?
+ true
+ end
+ def primary
+ self
+ end
+ end
+
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/commands/help.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/commands/help.rb
new file mode 100644
index 00000000..5c1f70b7
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/commands/help.rb
@@ -0,0 +1,32 @@
+module GitStyleBinary
+ module Commands
+ class Help
+ # not loving this syntax, but works for now
+ GitStyleBinary.command do
+ short_desc "get help for a specific command"
+ run do |command|
+
+ # this is slightly ugly b/c it has to muck around in the internals to
+ # get information about commands other than itself. This isn't a
+ # typical case
+ self.class.send :define_method, :educate_about_command do |name|
+ load_all_commands
+ if GitStyleBinary.known_commands.has_key?(name)
+ cmd = GitStyleBinary.known_commands[name]
+ cmd.process_parser!
+ cmd.parser.educate
+ else
+ puts "Unknown command '#{name}'"
+ end
+ end
+
+ if command.argv.size > 0
+ command.argv.first == "help" ? educate : educate_about_command(command.argv.first)
+ else
+ educate
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/name_resolver.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/name_resolver.rb
new file mode 100644
index 00000000..e6edbd69
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/name_resolver.rb
@@ -0,0 +1,78 @@
+module GitStyleBinary
+module Helpers
+ module NameResolver
+
+ def basename(filename=zero)
+ File.basename(filename).match(/(.*?)(\-|$)/).captures.first
+ end
+ alias_method :primary_name, :basename
+
+ # checks the bin directory for all files starting with +basename+ and
+ # returns an array of strings specifying the subcommands
+ def subcommand_names(filename=zero)
+ subfiles = Dir[File.join(binary_directory, basename + "-*")]
+ cmds = subfiles.collect{|file| File.basename(file).sub(/^#{basename}-/, '')}.sort
+ cmds += built_in_command_names
+ cmds.uniq
+ end
+
+ def binary_directory(filename=zero)
+ File.dirname(filename)
+ end
+
+ def built_in_commands_directory
+ File.dirname(__FILE__) + "/../commands"
+ end
+
+ def built_in_command_names
+ Dir[built_in_commands_directory + "/*.rb"].collect{|f| File.basename(f.sub(/\.rb$/,''))}
+ end
+
+ def list_subcommands(filename=zero)
+ subcommand_names(filename).join(", ")
+ end
+
+ # load first from users binary directory. then load built-in commands if
+ # available
+ def binary_filename_for(name)
+ user_file = File.join(binary_directory, "#{basename}-#{name}")
+ return user_file if File.exists?(user_file)
+ built_in = File.join(built_in_commands_directory, "#{name}.rb")
+ return built_in if File.exists?(built_in)
+ user_file
+ end
+
+ def current_command_name(filename=zero,argv=ARGV)
+ current = File.basename(zero)
+ first_arg = ARGV[0]
+ return first_arg if valid_subcommand?(first_arg)
+ return basename if basename == current
+ current.sub(/^#{basename}-/, '')
+ end
+
+ # returns the command name with the prefix if needed
+ def full_current_command_name(filename=zero,argv=ARGV)
+ cur = current_command_name(filename, argv)
+ subcmd = cur == basename(filename) ? false : true # is this a subcmd?
+ "%s%s%s" % [basename(filename), subcmd ? "-" : "", subcmd ? current_command_name(filename, argv) : ""]
+ end
+
+ def valid_subcommand?(name)
+ subcommand_names.include?(name)
+ end
+
+ def zero
+ $0
+ end
+
+ def pretty_known_subcommands(theme=:long)
+ GitStyleBinary.known_commands.collect do |k,cmd|
+ next if k == basename
+ cmd.process_parser!
+ ("%-s%s%-10s" % [basename, '-', k]).colorize(:light_blue) + ("%s " % [theme == :long ? "\n" : ""]) + ("%s" % [cmd.short_desc]) + "\n"
+ end.compact.sort
+ end
+
+ end
+end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/pager.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/pager.rb
new file mode 100644
index 00000000..1fa1cff0
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/helpers/pager.rb
@@ -0,0 +1,37 @@
+module GitStyleBinary
+ module Helpers
+ module Pager
+
+ # by Nathan Weizenbaum - http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
+ def run_pager
+ return if RUBY_PLATFORM =~ /win32/
+ return unless STDOUT.tty?
+ STDOUT.use_color = true
+
+ read, write = IO.pipe
+
+ unless Kernel.fork # Child process
+ STDOUT.reopen(write)
+ STDERR.reopen(write) if STDERR.tty?
+ read.close
+ write.close
+ return
+ end
+
+ # Parent process, become pager
+ STDIN.reopen(read)
+ read.close
+ write.close
+
+ ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
+
+ Kernel.select [STDIN] # Wait until we have input before we start the pager
+ pager = ENV['PAGER'] || 'less -erXF'
+ exec pager rescue exec "/bin/sh", "-c", pager
+ end
+
+ module_function :run_pager
+
+ end
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/parser.rb b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/parser.rb
new file mode 100644
index 00000000..4e03d5c8
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/lib/git-style-binary/parser.rb
@@ -0,0 +1,223 @@
+module GitStyleBinary
+class Parser < Trollop::Parser
+ attr_reader :runs, :callbacks
+ attr_reader :short_desc
+ attr_accessor :command
+
+ def initialize *a, &b
+ super
+ @runs = []
+ setup_callbacks
+ end
+
+ def setup_callbacks
+ @callbacks = {}
+ %w(run).each do |event|
+ %w(before after).each do |time|
+ @callbacks["#{time}_#{event}".to_sym] = []
+ instance_eval "def #{time}_#{event}(&block);@callbacks[:#{time}_#{event}] << block;end"
+ end
+ end
+ end
+
+ def run_callbacks(at, from)
+ @callbacks[at].each {|c| c.call(from) }
+ end
+
+ def banner s=nil; @banner = s if s; @banner end
+ def short_desc s=nil; @short_desc = s if s; @short_desc end
+ def name_desc s=nil; @name_desc = s if s; @name_desc end
+
+ # Set the theme. Valid values are +:short+ or +:long+. Default +:long+
+ attr_writer :theme
+
+ def theme
+ @theme ||= :long
+ end
+
+ ## Adds text to the help display.
+ def text s; @order << [:text, s] end
+
+ def spec_names
+ @specs.collect{|name, spec| spec[:long]}
+ end
+
+ # should probably be somewhere else
+ def load_all_commands
+ GitStyleBinary.subcommand_names.each do |name|
+ cmd_file = GitStyleBinary.binary_filename_for(name)
+ GitStyleBinary.load_command_file(name, cmd_file)
+ end
+ end
+
+ ## Print the help message to 'stream'.
+ def educate(stream=$stdout)
+ load_all_commands
+ width # just calculate it now; otherwise we have to be careful not to
+ # call this unless the cursor's at the beginning of a line.
+ GitStyleBinary::Helpers::Pager.run_pager
+ self.send("educate_#{theme}", stream)
+ end
+
+ def educate_long(stream=$stdout)
+ left = {}
+
+ @specs.each do |name, spec|
+ left[name] =
+ ((spec[:short] ? "-#{spec[:short]}, " : "") +
+ "--#{spec[:long]}" +
+ case spec[:type]
+ when :flag; ""
+ when :int; "="
+ when :ints; "="
+ when :string; "="
+ when :strings; "="
+ when :float; "="
+ when :floats; "="
+ end).colorize(:red)
+ end
+
+ leftcol_width = left.values.map { |s| s.length }.max || 0
+ rightcol_start = leftcol_width + 6 # spaces
+ leftcol_start = 6
+ leftcol_spaces = " " * leftcol_start
+
+ unless @order.size > 0 && @order.first.first == :text
+
+ if @name_desc
+ stream.puts "NAME".colorize(:red)
+ stream.puts "#{leftcol_spaces}"+ colorize_known_words(eval(%Q["#{@name_desc}"])) + "\n"
+ stream.puts
+ end
+
+ if @version
+ stream.puts "VERSION".colorize(:red)
+ stream.puts "#{leftcol_spaces}#@version\n"
+ end
+
+ stream.puts
+
+ banner = colorize_known_words_array(wrap(eval(%Q["#{@banner}"]) + "\n", :prefix => leftcol_start)) if @banner # lazy banner
+ stream.puts banner
+
+ stream.puts
+ stream.puts "OPTIONS".colorize(:red)
+ else
+ stream.puts "#@banner\n" if @banner
+ end
+
+ @order.each do |what, opt|
+ if what == :text
+ stream.puts wrap(opt)
+ next
+ end
+
+ spec = @specs[opt]
+ stream.printf " %-#{leftcol_width}s\n", left[opt]
+ desc = spec[:desc] +
+ if spec[:default]
+ if spec[:desc] =~ /\.$/
+ " (Default: #{spec[:default]})"
+ else
+ " (default: #{spec[:default]})"
+ end
+ else
+ ""
+ end
+ stream.puts wrap(" %s" % [desc], :prefix => leftcol_start, :width => width - rightcol_start - 1 )
+ stream.puts
+ stream.puts
+ end
+
+ end
+
+ def educate_short(stream=$stdout)
+ left = {}
+
+ @specs.each do |name, spec|
+ left[name] = "--#{spec[:long]}" +
+ (spec[:short] ? ", -#{spec[:short]}" : "") +
+ case spec[:type]
+ when :flag; ""
+ when :int; " "
+ when :ints; " "
+ when :string; " "
+ when :strings; " "
+ when :float; " "
+ when :floats; " "
+ end
+ end
+
+ leftcol_width = left.values.map { |s| s.length }.max || 0
+ rightcol_start = leftcol_width + 6 # spaces
+ leftcol_start = 0
+
+ unless @order.size > 0 && @order.first.first == :text
+ stream.puts "#@version\n" if @version
+ stream.puts colorize_known_words_array(wrap(eval(%Q["#{@banner}"]) + "\n", :prefix => leftcol_start)) if @banner # jit banner
+ stream.puts "Options:"
+ else
+ stream.puts "#@banner\n" if @banner
+ end
+
+ @order.each do |what, opt|
+ if what == :text
+ stream.puts wrap(opt)
+ next
+ end
+
+ spec = @specs[opt]
+ stream.printf " %#{leftcol_width}s: ", left[opt]
+ desc = spec[:desc] +
+ if spec[:default]
+ if spec[:desc] =~ /\.$/
+ " (Default: #{spec[:default]})"
+ else
+ " (default: #{spec[:default]})"
+ end
+ else
+ ""
+ end
+ stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
+ end
+
+ end
+
+
+ def colorize_known_words_array(txts)
+ txts.collect{|txt| colorize_known_words(txt)}
+ end
+
+ def colorize_known_words(txt)
+ txt = txt.gsub(/^([A-Z]+\s*)$/, '\1'.colorize(:red)) # all caps words on their own line
+ txt = txt.gsub(/\b(#{bin_name})\b/, '\1'.colorize(:light_blue)) # the current command name
+ txt = txt.gsub(/\[([^\s]+)\]/, "[".colorize(:magenta) + '\1'.colorize(:green) + "]".colorize(:magenta)) # synopsis options
+ end
+
+ def consume(&block)
+ cloaker(&block).bind(self).call
+ end
+
+ def consume_all(blocks)
+ blocks.each {|b| consume(&b)}
+ end
+
+ def bin_name
+ GitStyleBinary.full_current_command_name
+ end
+
+ def all_options_string
+ # '#{spec_names.collect(&:to_s).collect{|name| "[".colorize(:magenta) + "--" + name + "]".colorize(:magenta)}.join(" ")} COMMAND [ARGS]'
+ '#{spec_names.collect(&:to_s).collect{|name| "[" + "--" + name + "]"}.join(" ")} COMMAND [ARGS]'
+ end
+
+ def run(&block)
+ @runs << block
+ end
+
+ def action(name = :action, &block)
+ block.call(self) if block
+ end
+
+end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr
new file mode 100755
index 00000000..8eca1b9b
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+VERSION="0.0.2" # just to test it
+require 'git-style-binary/command'
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr-download b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr-download
new file mode 100755
index 00000000..aff41282
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/flickr-download
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+require 'git-style-binary/command'
+
+GitStyleBinary.command do
+ short_desc "download a flickr image"
+ banner <<-EOS
+SYNOPSIS
+ #{command.full_name} #{all_options_string} url
+
+Downloads an image from flickr
+
+EOS
+ run do |command|
+ puts "would download: #{command.argv.inspect}"
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress
new file mode 100755
index 00000000..90a1cd69
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress
@@ -0,0 +1,42 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+
+require 'git-style-binary/command'
+GitStyleBinary.primary do
+ version "0.0.1 (c) 2009 Nate Murray - local"
+ opt :test_primary, "test an option on the primary", :type => String
+
+ action do
+ @categories = ["sports", "news"]
+ end
+
+ before_run do |cmd|
+ puts "before_run command #{cmd}"
+ end
+
+ after_run do |cmd|
+ puts "after_run command #{cmd}"
+ end
+
+ run do |command|
+ puts "Primary Options: #{command.opts.inspect}"
+ end
+end
+
+# OR
+
+# require 'git-style-binary/primary'
+# command = GitStyleBinary::primary("wordpress") do
+# version "#{$0} 0.0.1 (c) 2009 Nate Murray"
+# banner <<-EOS
+# usage: #{$0} #{all_options.collect(:&to_s).join(" ")} COMMAND [ARGS]
+#
+# The wordpress subcommands commands are:
+# {subcommand_names.pretty_print}
+#
+# See 'wordpress help COMMAND' for more information on a specific command.
+# EOS
+# opt :verbose, "verbose", :default => false
+# opt :dry, "dry run", :default => false
+# opt :test_global, "a basic global string option", :type => String
+# end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-categories b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-categories
new file mode 100755
index 00000000..66c44a41
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-categories
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+require 'git-style-binary/command'
+
+GitStyleBinary.command do
+ short_desc "do something with categories"
+ banner <<-EOS
+SYNOPSIS
+ #{command.full_name} #{all_options_string}
+
+Does something with categories
+
+EOS
+ run do |command|
+ puts "does something with categories"
+ puts @categories.join(" ")
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-list b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-list
new file mode 100755
index 00000000..dbe82a72
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-list
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+require 'git-style-binary/command'
+
+GitStyleBinary.command do
+ short_desc "list blog postings"
+ banner <<-EOS
+SYNOPSIS
+ #{command.full_name} #{all_options_string}
+
+Lists the posts on the blog
+
+EOS
+ run do |command|
+ puts "listing blog posts"
+ end
+end
+
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-post b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-post
new file mode 100755
index 00000000..61f08f4d
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/fixtures/wordpress-post
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+$:.unshift(File.dirname(__FILE__) + "/../../lib")
+require 'git-style-binary/command'
+
+GitStyleBinary.command do
+ short_desc "create a blog post"
+ banner <<-EOS
+SYNOPSIS
+ #{command.full_name} #{all_options_string} {content|STDIN}
+
+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
+
+
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/git-style-binary/command_test.rb b/bin/yadr/lib/git-style-binaries-0.1.11/test/git-style-binary/command_test.rb
new file mode 100644
index 00000000..0b35c98a
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/git-style-binary/command_test.rb
@@ -0,0 +1,17 @@
+require File.dirname(__FILE__) + "/../test_helper.rb"
+require 'git-style-binary/command'
+
+class CommandTest < Test::Unit::TestCase
+ context "cmd" do
+ setup do
+ @c = GitStyleBinary::Command.new
+ end
+
+ should "be able to easily work with constraints" do
+ assert_equal @c.constraints, []
+ @c.constraints << "foo"
+ assert_equal @c.constraints, ["foo"]
+ end
+
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/git_style_binary_test.rb b/bin/yadr/lib/git-style-binaries-0.1.11/test/git_style_binary_test.rb
new file mode 100644
index 00000000..aa715d8b
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/git_style_binary_test.rb
@@ -0,0 +1,21 @@
+require File.dirname(__FILE__) + "/test_helper.rb"
+
+class GitStyleBinariesTest < Test::Unit::TestCase
+ context "parsing basenames" do
+ should "accurately parse basenames" do
+ assert_equal "wordpress", GitStyleBinary.basename("bin/wordpress")
+ assert_equal "wordpress", GitStyleBinary.basename("bin/wordpress-post")
+ assert_equal "wordpress", GitStyleBinary.basename("wordpress-post")
+ end
+
+ should "get the current command name" do
+ # doesn't really apply any more b/c it calls 'current' which is never the
+ # current when your running rake_test_loader.rb
+ #
+ # assert_equal "wordpress", GitStyleBinary.current_command_name("bin/wordpress", ["--help"])
+ # assert_equal "post", GitStyleBinary.current_command_name("bin/wordpress-post", ["--help"])
+ # assert_equal "post", GitStyleBinary.current_command_name("bin/wordpress post", ["--help"])
+ #assert_equal "post", GitStyleBinary.current_command_name("bin/wordpress post", [])
+ end
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/running_binaries_test.rb b/bin/yadr/lib/git-style-binaries-0.1.11/test/running_binaries_test.rb
new file mode 100644
index 00000000..887b651a
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/running_binaries_test.rb
@@ -0,0 +1,224 @@
+require File.dirname(__FILE__) + "/test_helper.rb"
+
+THIS_YEAR=Time.now.year # todo
+
+class RunningBinariesTest < Test::Unit::TestCase
+ include RunsBinaryFixtures
+
+ context "when running primary" do
+ ["wordpress -h", "wordpress help"].each do |format|
+ context "and getting help as a '#{format}'" do
+ setup { @stdout, @stderr = bin(format) }
+
+ should "have the command name and short description" do
+ unless format == "wordpress -h" # doesn't apply to wordpress -h
+ output_matches /NAME\n\s*wordpress\-help \- get help for a specific command/m
+ end
+ end
+
+ should "have a local (not default) version string" do
+ output_matches /0\.0\.1 \(c\) 2009 Nate Murray - local/
+ end
+
+ should "get a list of subcommands" do
+ output_matches /subcommands/mi
+ end
+
+ should "have subcommand short descriptions" do
+ output_matches /post\s*create a blog post/
+ output_matches /categories\s*do something with categories/
+ output_matches /help\s*get help for a specific command/
+ output_matches /list\s*list blog postings/
+ end
+
+ should "have a usage" do
+ output_matches /SYNOPSIS/i
+ output_matches /wordpress(\-help)? \[/
+ end
+
+ should "be able to ask for help about help"
+ end
+ end
+
+ context "and getting help as subcommand" do
+ # ["wordpress -h", "wordpress help"].each do |format|
+ ["wordpress help"].each do |format|
+ context "'#{format}'" do
+ should "get help on subcommand post"
+ end
+ end
+ end
+
+ context "with no options" do
+ setup { @stdout, @stderr = bin("wordpress") }
+
+ should "output the options" do
+ output_matches /Primary Options:/
+ end
+
+ should "have the test_primary option" do
+ output_matches /test_primary=>nil/
+ end
+ end
+ should "be able to require 'primary' and run just fine"
+ end
+
+ context "when running with an action" do
+ # should be the same for both formats
+ ["wordpress-categories", "wordpress categories"].each do |bin_format|
+ context "#{bin_format}" do
+
+ context "with action block" do
+ setup { @stdout, @stderr = bin("#{bin_format}") }
+ should "have the parsed action items in the help output" do
+ output_matches /sports news/m
+ end
+ end
+ end
+ end
+ end
+
+ context "callbacks" do
+ context "on a binary" do
+ setup { @stdout, @stderr = bin("wordpress") }
+
+ %w(before after).each do |time|
+ should "run the callback #{time}_run}" do
+ assert @stdout.match(/#{time}_run command/)
+ end
+ end
+ end
+
+ context "on help" do
+ setup { @stdout, @stderr = bin("wordpress -h") }
+
+ %w(before after).each do |time|
+ should "not run the callback #{time}_run" do
+ assert_nil @stdout.match(/#{time}_run command/)
+ end
+ end
+ end
+
+ end
+
+
+ context "when running the subcommand" do
+ # should be the same for both formats
+ ["wordpress-post", "wordpress post"].each do |bin_format|
+ context "#{bin_format}" do
+
+ context "with no options" do
+ setup { @stdout, @stderr = bin("#{bin_format}") }
+ should "fail because title is required" do
+ output_matches /Error: option 'title' must be specified.\s*Try --help for help/m
+ end
+ end
+
+ context "with options" do
+ setup { @stdout, @stderr = bin("#{bin_format} --title='glendale'") }
+ should "be running the subcommand's run block" do
+ output_matches /Subcommand name/
+ end
+ should "have some default options" do
+ output_matches /version=>false/
+ output_matches /help=>false/
+ end
+ should "have some primary options" do
+ output_matches /test_primary=>nil/
+ end
+ should "have some local options" do
+ output_matches /title=>"glendale"/
+ output_matches /type=>"html"/
+ end
+ end
+
+ context "testing die statements" do
+ setup { @stdout, @stderr = bin("#{bin_format} --title='glendale' --type=yaml") }
+
+ should "die on invalid options" do
+ output_matches /argument \-\-type type must be one of \[html\|xhtml\|text\]/
+ end
+ end
+
+ end # end bin_format
+ end # end #each
+ end
+
+ ["wordpress help post", "wordpress post -h"].each do |format|
+ context "when calling '#{format}'" do
+
+ setup { @stdout, @stderr = bin(format) }
+ should "have a description" do
+ output_matches /create a blog post/
+ end
+
+ should "have the proper usage line" do
+ output_matches /SYNOPSIS\n\s*wordpress\-post/m
+ output_matches /\[--title\]/
+ end
+
+ should "have option flags" do
+ output_matches /\-\-title(.*)/
+ end
+
+ should "have primary option flags" do
+ output_matches /\-\-test-primary(.*)/
+ end
+
+ should "have default option flags" do
+ output_matches /\-\-verbose/
+ end
+
+ should "have trollop default option flags" do
+ output_matches /\-e, \-\-version/
+ end
+
+ should "have the correct binary name and short description" do
+ output_matches /NAME\n\s*wordpress\-post \- create a blog post/m
+ end
+
+ should "have a the primaries version string" do
+ output_matches /0\.0\.1 \(c\) 2009 Nate Murray - local/
+ end
+
+ should "have options" do
+ output_matches /Options/i
+
+ output_matches /\-b, \-\-blog=/
+ output_matches /short name of the blog to use/
+
+ output_matches /-i, \-\-title=/
+ output_matches /title for the post/
+ end
+
+ end
+ end
+
+ context "when running a bare primary" do
+ ["flickr -h", "flickr help"].each do |format|
+ context format do
+ setup { @stdout, @stderr = bin(format) }
+
+ should "have the name and short description" do
+ unless format == "flickr -h" # hmm
+ output_matches /NAME\n\s*flickr\-help \- get help for a specific command/m
+ end
+ end
+
+ should "have a local (not default) version string" do
+ output_matches /0\.0\.2 \(c\) #{Time.now.year}/
+ end
+ end
+ end
+ ["flickr-download -h", "flickr download -h"].each do |format|
+ context format do
+ setup { @stdout, @stderr = bin(format) }
+
+ should "match on usage" do
+ output_matches /SYNOPSIS\n\s*flickr\-download/m
+ end
+ end
+ end
+ end
+
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/shoulda_macros/matching_stdio.rb b/bin/yadr/lib/git-style-binaries-0.1.11/test/shoulda_macros/matching_stdio.rb
new file mode 100644
index 00000000..e8e90e5f
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/shoulda_macros/matching_stdio.rb
@@ -0,0 +1,13 @@
+class Test::Unit::TestCase
+ def output_should_match(regexp)
+ assert_match regexp, @stdout + @stderr
+ end
+ alias_method :output_matches, :output_should_match
+
+ def stdout_should_match(regexp)
+ assert_match regexp, @stdout
+ end
+ def stderr_should_match(regexp)
+ assert_match regexp, @stderr
+ end
+end
diff --git a/bin/yadr/lib/git-style-binaries-0.1.11/test/test_helper.rb b/bin/yadr/lib/git-style-binaries-0.1.11/test/test_helper.rb
new file mode 100644
index 00000000..7fcb576b
--- /dev/null
+++ b/bin/yadr/lib/git-style-binaries-0.1.11/test/test_helper.rb
@@ -0,0 +1,28 @@
+require 'rubygems'
+require 'test/unit'
+require 'shoulda'
+begin require 'redgreen'; rescue LoadError; end
+require 'open3'
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+Dir[File.join(File.dirname(__FILE__), "shoulda_macros", "*.rb")].each {|f| require f}
+ENV['NO_COLOR'] = "true"
+
+require 'git-style-binary'
+GitStyleBinary.run = true
+
+class Test::Unit::TestCase
+ def fixtures_dir
+ File.join(File.dirname(__FILE__), "fixtures")
+ end
+end
+
+module RunsBinaryFixtures
+ # run the specified cmd returning the string values of [stdout,stderr]
+ def bin(cmd)
+ stdin, stdout, stderr = Open3.popen3("#{fixtures_dir}/#{cmd}")
+ [stdout.read, stderr.read]
+ end
+end
+
diff --git a/bin/yadr/lib/trollop-1.16.2/FAQ.txt b/bin/yadr/lib/trollop-1.16.2/FAQ.txt
new file mode 100644
index 00000000..809b35d2
--- /dev/null
+++ b/bin/yadr/lib/trollop-1.16.2/FAQ.txt
@@ -0,0 +1,84 @@
+Trollop FAQ
+-----------
+
+Q: Why is it called "Trollop"?
+A: No reason.
+
+Q: Why should I use Trollop?
+A: Because it will take you FEWER LINES OF CODE to do reasonable option parsing
+ than any other option parser out there.
+
+ Look at this:
+
+ opts = Trollop::options do
+ opt :monkey, "Use monkey mode"
+ opt :goat, "Use goat mode", :default => true
+ opt :num_limbs, "Set number of limbs", :default => 4
+ end
+
+ That's it. And opts is a hash and you do whatever you want with it.
+ Trivial. You don't have to mix option processing code blocks with the
+ declarations. You don't have to make a class for every option (what is this,
+ Java?). You don't have to write more than 1 line of code per option.
+
+ Plus, you get a beautiful help screen that detects your terminal width and
+ wraps appropriately. C'mon, that's hot.
+
+Q: What is the philosophy behind Trollop?
+A: Must a commandline option processor have a philosophy?
+
+Q: Seriously now. What is it?
+A: Ok, it's this: Trollop *just* does the parsing and gives you a hash table
+ of the result. So whatever fancy logic or constraints you need, you can
+ implement by operating on that hash table. Options that disable other
+ options, fancy constraints involving multiple sets of values across multiple
+ sets of options, etc. are all left for you to do manually.
+
+ (Trollop does support limited constraint setting (see #conflicts and
+ #depends), but any non-trivial program will need to get fancier.)
+
+ The result is that using Trollop is pretty simple, and whatever bizarre
+ logic you want, you can write yourself. And don't forget, you can call
+ Trollop::die to abort the program and give a fancy options-related error
+ message.
+
+Q: What happens to the other stuff on the commandline?
+A: Anything Trollop doesn't recognize as an option or as an option parameter is
+ left in ARGV for you to process.
+
+Q: Does Trollop support multiple-value arguments?
+A: Yes. If you set the :type of an option to something plural, like ":ints",
+ ":strings", ":doubles", ":floats", ":ios", it will accept multiple arguments
+ on the commandline and the value will be an array of these.
+
+Q: Does Trollop support arguments that can be given multiple times?
+A: Yes. If you set :multi to true, then the argument can appear multiple times
+ on the commandline, and the value will be an array of the parameters.
+
+Q: Does Trollop support subcommands?
+A: Yes. You get subcommand support by adding a call #stop_on within the options
+ block, and passing the names of the subcommands to it. (See the third
+ example on the webpage.) When Trollop encounters one of these subcommands on
+ the commandline, it stops processing and returns.
+
+ ARGV at that point will contain the subcommand followed by any subcommand
+ options, since Trollop has contained the rest. So you can consume the
+ subcommand and call Trollop.options again with the particular options set
+ for that subcommand.
+
+ If you don't know the subcommands ahead of time, you can call
+ #stop_on_unknown, which will cause Trollop to stop when it encounters any
+ unknown token. This might be more trouble than its worth if you're also
+ passing filenames on the commandline.
+
+ It's probably easier to see the example on the webpage than to read all
+ that.
+
+Q: Why does Trollop disallow numeric short argument names, like '-1' and '-9'?
+A: Because it's ambiguous whether these are arguments or negative integer or
+ floating-point parameters to arguments. E.g., what about "-f -3". Is that a
+ negative three parameter to -f, or two separate parameters?
+
+ I could be very clever and detect when there are no arguments that require
+ floating-point parameters, and allow such short option names in those cases,
+ but opted for simplicity and consistency.
diff --git a/bin/yadr/lib/trollop-1.16.2/History.txt b/bin/yadr/lib/trollop-1.16.2/History.txt
new file mode 100644
index 00000000..bb2c8df3
--- /dev/null
+++ b/bin/yadr/lib/trollop-1.16.2/History.txt
@@ -0,0 +1,116 @@
+== 1.16.2 / 2010-04-06
+* Bugfix in Trollop::options. Thanks to Brian C. Thomas for pointing it out.
+
+== 1.16.1 / 2010-04-05
+* Bugfix in Trollop::die method introduced in last release.
+
+== 1.16 / 2010-04-01
+* Add Trollop::with_standard_exception_handling method for easing the use of Parser directly.
+* Handle scientific notation in float arguments, thanks to Will Fitzgerald.
+* Drop hoe dependency.
+
+== 1.15 / 2009-09-30
+* Don't raise an exception when out of short arguments (thanks to Rafael
+ Sevilla for pointing out how dumb this behavior was).
+
+== 1.14 / 2009-06-19
+* Make :multi arguments default to [], not nil, when not set on the commandline.
+* Minor commenting and error message improvements
+
+== 1.13 / 2009-03-16
+* Fix parsing of "--longarg=".
+
+== 1.12 / 2009-01-30
+* Fix some unit test failures in the last release. Should be more careful.
+* Make default short options only be assigned *after* all user-specified
+ short options. Now there's a little less juggling to do when you just
+ want to specify a few short options.
+
+== 1.11 / 2009-01-29
+* Set _given keys in the results hash for options that were specified
+ on the commandline.
+
+== 1.10.2 / 2008-10-23
+* No longer try `stty size` for screen size detection. Just use curses, and
+ screen users will have to deal with the screen clearing.
+
+== 1.10.1 / 2008-10-22
+* Options hash now responds to method calls as well as standard hash lookup.
+* Default values for multi-occurrence parameters now autoboxed.
+* The relationship between multi-value, multi-occurrence, and default values
+ improved and explained.
+* Documentation improvements.
+
+== 1.10 / 2008-10-21
+* Added :io type for parameters that point to IO streams (filenames, URIs, etc).
+* For screen size detection, first try `stty size` before loading Curses.
+* Improved documentation.
+
+== 1.9 / 2008-08-20
+* Added 'stop_on_unknown' command to stop parsing on any unknown argument.
+ This is useful for handling sub-commands when you don't know the entire
+ set of commands up front. (E.g. if the initial arguments can change it.)
+* Added a :multi option for parameters, signifying that they can be specified
+ multiple times.
+* Added :ints, :strings, :doubles, and :floats option types, which can take
+ multiple arguments.
+
+== 1.8.2 / 2008-06-25
+* Bugfix for #conflicts and #depends error messages
+
+== 1.8.1 / 2008-06-24
+* Bugfix for short option autocreation
+* More aggressive documentation
+
+== 1.8 / 2008-06-16
+* Sub-command support via Parser#stop_on
+
+== 1.7.2 / 2008-01-16
+* Ruby 1.9-ify. Apparently this means replacing :'s with ;'s.
+
+== 1.7.1 / 2008-01-07
+* Documentation improvements
+
+== 1.7 / 2007-06-17
+* Fix incorrect error message for multiple missing required arguments
+ (thanks to Neill Zero)
+
+== 1.6 / 2007-04-01
+* Don't attempt curses screen-width magic unless running on a terminal.
+
+== 1.5 / 2007-03-31
+* --help and --version do the right thing even if the rest of the
+ command line is incorrect.
+* Added #conflicts and #depends to model dependencies and exclusivity
+ between arguments.
+* Minor bugfixes.
+
+== 1.4 / 2007-03-26
+* Disable short options with :short => :none.
+* Minor bugfixes and error message improvements.
+
+== 1.3 / 2007-01-31
+* Wrap at (screen width - 1) instead of screen width.
+* User can override --help and --version.
+* Bugfix in handling of -v and -h.
+* More tests to confirm the above.
+
+== 1.2 / 2007-01-31
+* Minor documentation tweaks.
+* Removed hoe dependency.
+
+== 1.1 / 2007-01-30
+* Trollop::options now passes any arguments as block arguments. Since
+ instance variables are not properly captured by the block, this
+ makes it slightly less noisy to pass them in as local variables.
+ (A real-life use for _why's cloaker!)
+* Help display now preserves original argument order.
+* Trollop::die now also has a single string form in case death is not
+ due to a single argument.
+* Parser#text now an alias for Parser#banner, and can be called
+ multiple times, with the output being placed in the right position
+ in the help text.
+* Slightly more indicative formatting for parameterized arguments.
+
+== 1.0 / 2007-01-29
+* Initial release.
diff --git a/bin/yadr/lib/trollop-1.16.2/README.txt b/bin/yadr/lib/trollop-1.16.2/README.txt
new file mode 100644
index 00000000..72580085
--- /dev/null
+++ b/bin/yadr/lib/trollop-1.16.2/README.txt
@@ -0,0 +1,52 @@
+== trollop
+
+by William Morgan (http://masanjin.net/)
+
+Main page: http://trollop.rubyforge.org
+
+Release announcements and comments: http://all-thing.net/label/trollop
+
+Documentation quickstart: See Trollop.options and then Trollop::Parser#opt.
+Also see the examples at http://trollop.rubyforge.org/.
+
+== DESCRIPTION
+
+Trollop is a commandline option parser for Ruby that just gets out of your
+way. One line of code per option is all you need to write. For that, you get a
+nice automatically-generated help page, robust option parsing, command
+subcompletion, and sensible defaults for everything you don't specify.
+
+== FEATURES/PROBLEMS
+
+- Dirt-simple usage.
+- Sensible defaults. No tweaking necessary, much tweaking possible.
+- Support for long options, short options, short option bundling, and
+ automatic type validation and conversion.
+- Support for subcommands.
+- Automatic help message generation, wrapped to current screen width.
+- Lots of unit tests.
+
+== REQUIREMENTS
+
+* A burning desire to write less code.
+
+== INSTALL
+
+* gem install trollop
+
+== SYNOPSIS
+
+ require 'trollop'
+ opts = Trollop::options do
+ opt :monkey, "Use monkey mode" # flag --monkey, default false
+ opt :goat, "Use goat mode", :default => true # flag --goat, default true
+ opt :num_limbs, "Number of limbs", :default => 4 # integer --num-limbs , default to 4
+ opt :num_thumbs, "Number of thumbs", :type => :int # integer --num-thumbs , default nil
+ end
+
+ p opts # a hash: { :monkey => false, :goat => true, :num_limbs => 4, :num_thumbs => nil }
+
+== LICENSE
+
+Copyright (c) 2008--2009 William Morgan. Trollop is distributed under the same
+terms as Ruby.
diff --git a/bin/yadr/lib/trollop-1.16.2/lib/trollop.rb b/bin/yadr/lib/trollop-1.16.2/lib/trollop.rb
new file mode 100644
index 00000000..06ee2af0
--- /dev/null
+++ b/bin/yadr/lib/trollop-1.16.2/lib/trollop.rb
@@ -0,0 +1,781 @@
+## lib/trollop.rb -- trollop command-line processing library
+## Author:: William Morgan (mailto: wmorgan-trollop@masanjin.net)
+## Copyright:: Copyright 2007 William Morgan
+## License:: the same terms as ruby itself
+
+require 'date'
+
+module Trollop
+
+VERSION = "1.16.2"
+
+## Thrown by Parser in the event of a commandline error. Not needed if
+## you're using the Trollop::options entry.
+class CommandlineError < StandardError; end
+
+## Thrown by Parser if the user passes in '-h' or '--help'. Handled
+## automatically by Trollop#options.
+class HelpNeeded < StandardError; end
+
+## Thrown by Parser if the user passes in '-h' or '--version'. Handled
+## automatically by Trollop#options.
+class VersionNeeded < StandardError; end
+
+## Regex for floating point numbers
+FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))([eE][-+]?[\d]+)?$/
+
+## Regex for parameters
+PARAM_RE = /^-(-|\.$|[^\d\.])/
+
+## The commandline parser. In typical usage, the methods in this class
+## will be handled internally by Trollop::options. In this case, only the
+## #opt, #banner and #version, #depends, and #conflicts methods will
+## typically be called.
+##
+## If you want to instantiate this class yourself (for more complicated
+## argument-parsing logic), call #parse to actually produce the output hash,
+## and consider calling it from within
+## Trollop::with_standard_exception_handling.
+class Parser
+
+ ## The set of values that indicate a flag option when passed as the
+ ## +:type+ parameter of #opt.
+ FLAG_TYPES = [:flag, :bool, :boolean]
+
+ ## The set of values that indicate a single-parameter (normal) option when
+ ## passed as the +:type+ parameter of #opt.
+ ##
+ ## A value of +io+ corresponds to a readable IO resource, including
+ ## a filename, URI, or the strings 'stdin' or '-'.
+ SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float, :io, :date]
+
+ ## The set of values that indicate a multiple-parameter option (i.e., that
+ ## takes multiple space-separated values on the commandline) when passed as
+ ## the +:type+ parameter of #opt.
+ MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats, :ios, :dates]
+
+ ## The complete set of legal values for the +:type+ parameter of #opt.
+ TYPES = FLAG_TYPES + SINGLE_ARG_TYPES + MULTI_ARG_TYPES
+
+ INVALID_SHORT_ARG_REGEX = /[\d-]/ #:nodoc:
+
+ ## The values from the commandline that were not interpreted by #parse.
+ attr_reader :leftovers
+
+ ## The complete configuration hashes for each option. (Mainly useful
+ ## for testing.)
+ attr_reader :specs
+
+ ## Initializes the parser, and instance-evaluates any block given.
+ def initialize *a, &b
+ @version = nil
+ @leftovers = []
+ @specs = {}
+ @long = {}
+ @short = {}
+ @order = []
+ @constraints = []
+ @stop_words = []
+ @stop_on_unknown = false
+
+ #instance_eval(&b) if b # can't take arguments
+ cloaker(&b).bind(self).call(*a) if b
+ end
+
+ ## Define an option. +name+ is the option name, a unique identifier
+ ## for the option that you will use internally, which should be a
+ ## symbol or a string. +desc+ is a string description which will be
+ ## displayed in help messages.
+ ##
+ ## Takes the following optional arguments:
+ ##
+ ## [+:long+] Specify the long form of the argument, i.e. the form with two dashes. If unspecified, will be automatically derived based on the argument name by turning the +name+ option into a string, and replacing any _'s by -'s.
+ ## [+:short+] Specify the short form of the argument, i.e. the form with one dash. If unspecified, will be automatically derived from +name+.
+ ## [+:type+] Require that the argument take a parameter or parameters of type +type+. For a single parameter, the value can be a member of +SINGLE_ARG_TYPES+, or a corresponding Ruby class (e.g. +Integer+ for +:int+). For multiple-argument parameters, the value can be any member of +MULTI_ARG_TYPES+ constant. If unset, the default argument type is +:flag+, meaning that the argument does not take a parameter. The specification of +:type+ is not necessary if a +:default+ is given.
+ ## [+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus Trollop::options) will have a +nil+ value for this key unless the argument is given on the commandline. The argument type is derived automatically from the class of the default value given, so specifying a +:type+ is not necessary if a +:default+ is given. (But see below for an important caveat when +:multi+: is specified too.) If the argument is a flag, and the default is set to +true+, then if it is specified on the the commandline the value will be +false+.
+ ## [+:required+] If set to +true+, the argument must be provided on the commandline.
+ ## [+:multi+] If set to +true+, allows multiple occurrences of the option on the commandline. Otherwise, only a single instance of the option is allowed. (Note that this is different from taking multiple parameters. See below.)
+ ##
+ ## Note that there are two types of argument multiplicity: an argument
+ ## can take multiple values, e.g. "--arg 1 2 3". An argument can also
+ ## be allowed to occur multiple times, e.g. "--arg 1 --arg 2".
+ ##
+ ## Arguments that take multiple values should have a +:type+ parameter
+ ## drawn from +MULTI_ARG_TYPES+ (e.g. +:strings+), or a +:default:+
+ ## value of an array of the correct type (e.g. [String]). The
+ ## value of this argument will be an array of the parameters on the
+ ## commandline.
+ ##
+ ## Arguments that can occur multiple times should be marked with
+ ## +:multi+ => +true+. The value of this argument will also be an array.
+ ## In contrast with regular non-multi options, if not specified on
+ ## the commandline, the default value will be [], not nil.
+ ##
+ ## These two attributes can be combined (e.g. +:type+ => +:strings+,
+ ## +:multi+ => +true+), in which case the value of the argument will be
+ ## an array of arrays.
+ ##
+ ## There's one ambiguous case to be aware of: when +:multi+: is true and a
+ ## +:default+ is set to an array (of something), it's ambiguous whether this
+ ## is a multi-value argument as well as a multi-occurrence argument.
+ ## In thise case, Trollop assumes that it's not a multi-value argument.
+ ## If you want a multi-value, multi-occurrence argument with a default
+ ## value, you must specify +:type+ as well.
+
+ def opt name, desc="", opts={}
+ raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name
+
+ ## fill in :type
+ opts[:type] = # normalize
+ case opts[:type]
+ when :boolean, :bool; :flag
+ when :integer; :int
+ when :integers; :ints
+ when :double; :float
+ when :doubles; :floats
+ when Class
+ case opts[:type].name
+ when 'TrueClass', 'FalseClass'; :flag
+ when 'String'; :string
+ when 'Integer'; :int
+ when 'Float'; :float
+ when 'IO'; :io
+ when 'Date'; :date
+ else
+ raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'"
+ end
+ when nil; nil
+ else
+ raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
+ opts[:type]
+ end
+
+ ## for options with :multi => true, an array default doesn't imply
+ ## a multi-valued argument. for that you have to specify a :type
+ ## as well. (this is how we disambiguate an ambiguous situation;
+ ## see the docs for Parser#opt for details.)
+ disambiguated_default =
+ if opts[:multi] && opts[:default].is_a?(Array) && !opts[:type]
+ opts[:default].first
+ else
+ opts[:default]
+ end
+
+ type_from_default =
+ case disambiguated_default
+ when Integer; :int
+ when Numeric; :float
+ when TrueClass, FalseClass; :flag
+ when String; :string
+ when IO; :io
+ when Date; :date
+ when Array
+ if opts[:default].empty?
+ raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'"
+ end
+ case opts[:default][0] # the first element determines the types
+ when Integer; :ints
+ when Numeric; :floats
+ when String; :strings
+ when IO; :ios
+ when Date; :dates
+ else
+ raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'"
+ end
+ when nil; nil
+ else
+ raise ArgumentError, "unsupported argument type '#{opts[:default].class.name}'"
+ end
+
+ raise ArgumentError, ":type specification and default type don't match (default type is #{type_from_default})" if opts[:type] && type_from_default && opts[:type] != type_from_default
+
+ opts[:type] = opts[:type] || type_from_default || :flag
+
+ ## fill in :long
+ opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.gsub("_", "-")
+ opts[:long] =
+ case opts[:long]
+ when /^--([^-].*)$/
+ $1
+ when /^[^-]/
+ opts[:long]
+ else
+ raise ArgumentError, "invalid long option name #{opts[:long].inspect}"
+ end
+ raise ArgumentError, "long option name #{opts[:long].inspect} is already taken; please specify a (different) :long" if @long[opts[:long]]
+
+ ## fill in :short
+ opts[:short] = opts[:short].to_s if opts[:short] unless opts[:short] == :none
+ opts[:short] = case opts[:short]
+ when /^-(.)$/; $1
+ when nil, :none, /^.$/; opts[:short]
+ else raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
+ end
+
+ if opts[:short]
+ raise ArgumentError, "short option name #{opts[:short].inspect} is already taken; please specify a (different) :short" if @short[opts[:short]]
+ raise ArgumentError, "a short option name can't be a number or a dash" if opts[:short] =~ INVALID_SHORT_ARG_REGEX
+ end
+
+ ## fill in :default for flags
+ opts[:default] = false if opts[:type] == :flag && opts[:default].nil?
+
+ ## autobox :default for :multi (multi-occurrence) arguments
+ opts[:default] = [opts[:default]] if opts[:default] && opts[:multi] && !opts[:default].is_a?(Array)
+
+ ## fill in :multi
+ opts[:multi] ||= false
+
+ opts[:desc] ||= desc
+ @long[opts[:long]] = name
+ @short[opts[:short]] = name if opts[:short] && opts[:short] != :none
+ @specs[name] = opts
+ @order << [:opt, name]
+ end
+
+ ## Sets the version string. If set, the user can request the version
+ ## on the commandline. Should probably be of the form "
+ ## ".
+ def version s=nil; @version = s if s; @version end
+
+ ## Adds text to the help display. Can be interspersed with calls to
+ ## #opt to build a multi-section help page.
+ def banner s; @order << [:text, s] end
+ alias :text :banner
+
+ ## Marks two (or more!) options as requiring each other. Only handles
+ ## undirected (i.e., mutual) dependencies. Directed dependencies are
+ ## better modeled with Trollop::die.
+ def depends *syms
+ syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
+ @constraints << [:depends, syms]
+ end
+
+ ## Marks two (or more!) options as conflicting.
+ def conflicts *syms
+ syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
+ @constraints << [:conflicts, syms]
+ end
+
+ ## Defines a set of words which cause parsing to terminate when
+ ## encountered, such that any options to the left of the word are
+ ## parsed as usual, and options to the right of the word are left
+ ## intact.
+ ##
+ ## A typical use case would be for subcommand support, where these
+ ## would be set to the list of subcommands. A subsequent Trollop
+ ## invocation would then be used to parse subcommand options, after
+ ## shifting the subcommand off of ARGV.
+ def stop_on *words
+ @stop_words = [*words].flatten
+ end
+
+ ## Similar to #stop_on, but stops on any unknown word when encountered
+ ## (unless it is a parameter for an argument). This is useful for
+ ## cases where you don't know the set of subcommands ahead of time,
+ ## i.e., without first parsing the global options.
+ def stop_on_unknown
+ @stop_on_unknown = true
+ end
+
+ ## Parses the commandline. Typically called by Trollop::options,
+ ## but you can call it directly if you need more control.
+ ##
+ ## throws CommandlineError, HelpNeeded, and VersionNeeded exceptions.
+ def parse cmdline=ARGV
+ vals = {}
+ required = {}
+
+ opt :version, "Print version and exit" if @version unless @specs[:version] || @long["version"]
+ opt :help, "Show this message" unless @specs[:help] || @long["help"]
+
+ @specs.each do |sym, opts|
+ required[sym] = true if opts[:required]
+ vals[sym] = opts[:default]
+ vals[sym] = [] if opts[:multi] && !opts[:default] # multi arguments default to [], not nil
+ end
+
+ resolve_default_short_options
+
+ ## resolve symbols
+ given_args = {}
+ @leftovers = each_arg cmdline do |arg, params|
+ sym = case arg
+ when /^-([^-])$/
+ @short[$1]
+ when /^--([^-]\S*)$/
+ @long[$1]
+ else
+ raise CommandlineError, "invalid argument syntax: '#{arg}'"
+ end
+ raise CommandlineError, "unknown argument '#{arg}'" unless sym
+
+ if given_args.include?(sym) && !@specs[sym][:multi]
+ raise CommandlineError, "option '#{arg}' specified multiple times"
+ end
+
+ given_args[sym] ||= {}
+
+ given_args[sym][:arg] = arg
+ given_args[sym][:params] ||= []
+
+ # The block returns the number of parameters taken.
+ num_params_taken = 0
+
+ unless params.nil?
+ if SINGLE_ARG_TYPES.include?(@specs[sym][:type])
+ given_args[sym][:params] << params[0, 1] # take the first parameter
+ num_params_taken = 1
+ elsif MULTI_ARG_TYPES.include?(@specs[sym][:type])
+ given_args[sym][:params] << params # take all the parameters
+ num_params_taken = params.size
+ end
+ end
+
+ num_params_taken
+ end
+
+ ## check for version and help args
+ raise VersionNeeded if given_args.include? :version
+ raise HelpNeeded if given_args.include? :help
+
+ ## check constraint satisfaction
+ @constraints.each do |type, syms|
+ constraint_sym = syms.find { |sym| given_args[sym] }
+ next unless constraint_sym
+
+ case type
+ when :depends
+ syms.each { |sym| raise CommandlineError, "--#{@specs[constraint_sym][:long]} requires --#{@specs[sym][:long]}" unless given_args.include? sym }
+ when :conflicts
+ syms.each { |sym| raise CommandlineError, "--#{@specs[constraint_sym][:long]} conflicts with --#{@specs[sym][:long]}" if given_args.include?(sym) && (sym != constraint_sym) }
+ end
+ end
+
+ required.each do |sym, val|
+ raise CommandlineError, "option --#{@specs[sym][:long]} must be specified" unless given_args.include? sym
+ end
+
+ ## parse parameters
+ given_args.each do |sym, given_data|
+ arg = given_data[:arg]
+ params = given_data[:params]
+
+ opts = @specs[sym]
+ raise CommandlineError, "option '#{arg}' needs a parameter" if params.empty? && opts[:type] != :flag
+
+ vals["#{sym}_given".intern] = true # mark argument as specified on the commandline
+
+ case opts[:type]
+ when :flag
+ vals[sym] = !opts[:default]
+ when :int, :ints
+ vals[sym] = params.map { |pg| pg.map { |p| parse_integer_parameter p, arg } }
+ when :float, :floats
+ vals[sym] = params.map { |pg| pg.map { |p| parse_float_parameter p, arg } }
+ when :string, :strings
+ vals[sym] = params.map { |pg| pg.map { |p| p.to_s } }
+ when :io, :ios
+ vals[sym] = params.map { |pg| pg.map { |p| parse_io_parameter p, arg } }
+ when :date, :dates
+ vals[sym] = params.map { |pg| pg.map { |p| parse_date_parameter p, arg } }
+ end
+
+ if SINGLE_ARG_TYPES.include?(opts[:type])
+ unless opts[:multi] # single parameter
+ vals[sym] = vals[sym][0][0]
+ else # multiple options, each with a single parameter
+ vals[sym] = vals[sym].map { |p| p[0] }
+ end
+ elsif MULTI_ARG_TYPES.include?(opts[:type]) && !opts[:multi]
+ vals[sym] = vals[sym][0] # single option, with multiple parameters
+ end
+ # else: multiple options, with multiple parameters
+ end
+
+ ## modify input in place with only those
+ ## arguments we didn't process
+ cmdline.clear
+ @leftovers.each { |l| cmdline << l }
+
+ ## allow openstruct-style accessors
+ class << vals
+ def method_missing(m, *args)
+ self[m] || self[m.to_s]
+ end
+ end
+ vals
+ end
+
+ def parse_date_parameter param, arg #:nodoc:
+ begin
+ begin
+ time = Chronic.parse(param)
+ rescue NameError
+ # chronic is not available
+ end
+ time ? Date.new(time.year, time.month, time.day) : Date.parse(param)
+ rescue ArgumentError => e
+ raise CommandlineError, "option '#{arg}' needs a date"
+ end
+ end
+
+ ## Print the help message to +stream+.
+ def educate stream=$stdout
+ width # just calculate it now; otherwise we have to be careful not to
+ # call this unless the cursor's at the beginning of a line.
+
+ left = {}
+ @specs.each do |name, spec|
+ left[name] = "--#{spec[:long]}" +
+ (spec[:short] && spec[:short] != :none ? ", -#{spec[:short]}" : "") +
+ case spec[:type]
+ when :flag; ""
+ when :int; " "
+ when :ints; " "
+ when :string; " "
+ when :strings; " "
+ when :float; " "
+ when :floats; " "
+ when :io; " "
+ when :ios; " "
+ when :date; " "
+ when :dates; " "
+ end
+ end
+
+ leftcol_width = left.values.map { |s| s.length }.max || 0
+ rightcol_start = leftcol_width + 6 # spaces
+
+ unless @order.size > 0 && @order.first.first == :text
+ stream.puts "#@version\n" if @version
+ stream.puts "Options:"
+ end
+
+ @order.each do |what, opt|
+ if what == :text
+ stream.puts wrap(opt)
+ next
+ end
+
+ spec = @specs[opt]
+ stream.printf " %#{leftcol_width}s: ", left[opt]
+ desc = spec[:desc] + begin
+ default_s = case spec[:default]
+ when $stdout; ""
+ when $stdin; ""
+ when $stderr; ""
+ when Array
+ spec[:default].join(", ")
+ else
+ spec[:default].to_s
+ end
+
+ if spec[:default]
+ if spec[:desc] =~ /\.$/
+ " (Default: #{default_s})"
+ else
+ " (default: #{default_s})"
+ end
+ else
+ ""
+ end
+ end
+ stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
+ end
+ end
+
+ def width #:nodoc:
+ @width ||= if $stdout.tty?
+ begin
+ require 'curses'
+ Curses::init_screen
+ x = Curses::cols
+ Curses::close_screen
+ x
+ rescue Exception
+ 80
+ end
+ else
+ 80
+ end
+ end
+
+ def wrap str, opts={} # :nodoc:
+ if str == ""
+ [""]
+ else
+ str.split("\n").map { |s| wrap_line s, opts }.flatten
+ end
+ end
+
+ ## The per-parser version of Trollop::die (see that for documentation).
+ def die arg, msg
+ if msg
+ $stderr.puts "Error: argument --#{@specs[arg][:long]} #{msg}."
+ else
+ $stderr.puts "Error: #{arg}."
+ end
+ $stderr.puts "Try --help for help."
+ exit(-1)
+ end
+
+private
+
+ ## yield successive arg, parameter pairs
+ def each_arg args
+ remains = []
+ i = 0
+
+ until i >= args.length
+ if @stop_words.member? args[i]
+ remains += args[i .. -1]
+ return remains
+ end
+ case args[i]
+ when /^--$/ # arg terminator
+ remains += args[(i + 1) .. -1]
+ return remains
+ when /^--(\S+?)=(.*)$/ # long argument with equals
+ yield "--#{$1}", [$2]
+ i += 1
+ when /^--(\S+)$/ # long argument
+ params = collect_argument_parameters(args, i + 1)
+ unless params.empty?
+ num_params_taken = yield args[i], params
+ unless num_params_taken
+ if @stop_on_unknown
+ remains += args[i + 1 .. -1]
+ return remains
+ else
+ remains += params
+ end
+ end
+ i += 1 + num_params_taken
+ else # long argument no parameter
+ yield args[i], nil
+ i += 1
+ end
+ when /^-(\S+)$/ # one or more short arguments
+ shortargs = $1.split(//)
+ shortargs.each_with_index do |a, j|
+ if j == (shortargs.length - 1)
+ params = collect_argument_parameters(args, i + 1)
+ unless params.empty?
+ num_params_taken = yield "-#{a}", params
+ unless num_params_taken
+ if @stop_on_unknown
+ remains += args[i + 1 .. -1]
+ return remains
+ else
+ remains += params
+ end
+ end
+ i += 1 + num_params_taken
+ else # argument no parameter
+ yield "-#{a}", nil
+ i += 1
+ end
+ else
+ yield "-#{a}", nil
+ end
+ end
+ else
+ if @stop_on_unknown
+ remains += args[i .. -1]
+ return remains
+ else
+ remains << args[i]
+ i += 1
+ end
+ end
+ end
+
+ remains
+ end
+
+ def parse_integer_parameter param, arg
+ raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^\d+$/
+ param.to_i
+ end
+
+ def parse_float_parameter param, arg
+ raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE
+ param.to_f
+ end
+
+ def parse_io_parameter param, arg
+ case param
+ when /^(stdin|-)$/i; $stdin
+ else
+ require 'open-uri'
+ begin
+ open param
+ rescue SystemCallError => e
+ raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}"
+ end
+ end
+ end
+
+ def collect_argument_parameters args, start_at
+ params = []
+ pos = start_at
+ while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos]) do
+ params << args[pos]
+ pos += 1
+ end
+ params
+ end
+
+ def resolve_default_short_options
+ @order.each do |type, name|
+ next unless type == :opt
+ opts = @specs[name]
+ next if opts[:short]
+
+ c = opts[:long].split(//).find { |d| d !~ INVALID_SHORT_ARG_REGEX && !@short.member?(d) }
+ if c # found a character to use
+ opts[:short] = c
+ @short[c] = name
+ end
+ end
+ end
+
+ def wrap_line str, opts={}
+ prefix = opts[:prefix] || 0
+ width = opts[:width] || (self.width - 1)
+ start = 0
+ ret = []
+ until start > str.length
+ nextt =
+ if start + width >= str.length
+ str.length
+ else
+ x = str.rindex(/\s/, start + width)
+ x = str.index(/\s/, start) if x && x < start
+ x || str.length
+ end
+ ret << (ret.empty? ? "" : " " * prefix) + str[start ... nextt]
+ start = nextt + 1
+ end
+ ret
+ end
+
+ ## instance_eval but with ability to handle block arguments
+ ## thanks to why: http://redhanded.hobix.com/inspect/aBlockCostume.html
+ def cloaker &b
+ (class << self; self; end).class_eval do
+ define_method :cloaker_, &b
+ meth = instance_method :cloaker_
+ remove_method :cloaker_
+ meth
+ end
+ end
+end
+
+## The easy, syntactic-sugary entry method into Trollop. Creates a Parser,
+## passes the block to it, then parses +args+ with it, handling any errors or
+## requests for help or version information appropriately (and then exiting).
+## Modifies +args+ in place. Returns a hash of option values.
+##
+## The block passed in should contain zero or more calls to +opt+
+## (Parser#opt), zero or more calls to +text+ (Parser#text), and
+## probably a call to +version+ (Parser#version).
+##
+## The returned block contains a value for every option specified with
+## +opt+. The value will be the value given on the commandline, or the
+## default value if the option was not specified on the commandline. For
+## every option specified on the commandline, a key "