slop-4.2.0/0000755000004100000410000000000012555132036012524 5ustar www-datawww-dataslop-4.2.0/Rakefile0000644000004100000410000000110612555132036014167 0ustar www-datawww-databegin require 'bundler/gem_tasks' rescue LoadError end require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' t.test_files = Dir['test/*_test.rb'] end # begin # require 'rdoc/task' # # requires sdoc and horo gems # RDoc::Task.new do |rdoc| # rdoc.title = 'Slop API Documentation' # rdoc.rdoc_dir = 'doc' # rdoc.options << '-f' << 'sdoc' # rdoc.options << '-T' << 'rails' # rdoc.options << '-e' << 'UTF-8' # rdoc.options << '-g' # rdoc.rdoc_files.include('lib/**/*.rb') # end # rescue LoadError # end task :default => :test slop-4.2.0/Gemfile0000644000004100000410000000004612555132036014017 0ustar www-datawww-datasource "https://rubygems.org" gemspecslop-4.2.0/.travis.yml0000644000004100000410000000015712555132036014640 0ustar www-datawww-datarvm: - 2.0.0 - 2.1 - 2.2 - rbx-2 notifications: email: on_success: change on_failure: always slop-4.2.0/lib/0000755000004100000410000000000012555132036013272 5ustar www-datawww-dataslop-4.2.0/lib/slop/0000755000004100000410000000000012555132036014247 5ustar www-datawww-dataslop-4.2.0/lib/slop/result.rb0000644000004100000410000000455412555132036016122 0ustar www-datawww-datamodule Slop # This class encapsulates a Parser and Options pair. The idea is that # the Options class shouldn't have to deal with what happens when options # are parsed, and the Parser shouldn't have to deal with the state of # options once parsing is complete. This keeps the API really simple; A # Parser parses, Options handles options, and this class handles the # result of those actions. This class contains the important most used # methods. class Result attr_reader :parser, :options def initialize(parser) @parser = parser @options = parser.options end # Returns an options value, nil if the option does not exist. def [](flag) (o = option(flag)) && o.value end alias get [] # Set the value for an option. Raises an ArgumentError if the option # does not exist. def []=(flag, value) if o = option(flag) o.value = value else raise ArgumentError, "no option with flag `#{flag}'" end end alias set []= # Returns an Option if it exists. Ignores any prefixed hyphens. def option(flag) cleaned = -> (f) { f.to_s.sub(/\A--?/, '').tr('_', '-') } options.find do |o| o.flags.any? { |f| cleaned.(f) == cleaned.(flag) } end end def method_missing(name, *args, &block) if respond_to_missing?(name) (o = option(name.to_s.chomp("?"))) && used_options.include?(o) else super end end def respond_to_missing?(name, include_private = false) name.to_s.end_with?("?") || super end # Returns an Array of Option instances that were used. def used_options parser.used_options end # Returns an Array of Option instances that were not used. def unused_options parser.unused_options end # Example: # # opts = Slop.parse do |o| # o.string '--host' # o.int '-p' # end # # # ruby run.rb connect --host 123 helo # opts.arguments #=> ["connect", "helo"] # # Returns an Array of String arguments that were not parsed. def arguments parser.arguments end alias args arguments # Returns a hash with option key => value. def to_hash Hash[options.reject(&:null?).map { |o| [o.key, o.value] }] end alias to_h to_hash def to_s(**opts) options.to_s(**opts) end end end slop-4.2.0/lib/slop/parser.rb0000644000004100000410000000637612555132036016104 0ustar www-datawww-datamodule Slop class Parser # Our Options instance. attr_reader :options # A Hash of configuration options. attr_reader :config # Returns an Array of String arguments that were not parsed. attr_reader :arguments def initialize(options, **config) @options = options @config = config reset end # Reset the parser, useful to use the same instance to parse a second # time without duplicating state. def reset @arguments = [] @options.each(&:reset) self end # Traverse `strings` and process options one by one. Anything after # `--` is ignored. If a flag includes a equals (=) it will be split # so that `flag, argument = s.split('=')`. # # The `call` method will be executed immediately for each option found. # Once all options have been executed, any found options will have # the `finish` method called on them. # # Returns a Slop::Result. def parse(strings) reset # reset before every parse pairs = strings.each_cons(2).to_a # this ensures we still support the last string being a flag, # otherwise it'll only be used as an argument. pairs << [strings.last, nil] @arguments = strings.dup pairs.each do |flag, arg| break if !flag # ignore everything after '--', flag or not if flag == '--' arguments.delete(flag) break end # support `foo=bar` if flag.include?("=") flag, arg = flag.split("=") end if opt = try_process(flag, arg) # since the option was parsed, we remove it from our # arguments (plus the arg if necessary) arguments.delete(flag) arguments.delete(arg) if opt.expects_argument? end end Result.new(self).tap do |result| used_options.each { |o| o.finish(result) } end end # Returns an Array of Option instances that were used. def used_options options.select { |o| o.count > 0 } end # Returns an Array of Option instances that were not used. def unused_options options.to_a - used_options end private # We've found an option, process and return it def process(option, arg) option.ensure_call(arg) option end # Try and find an option to process def try_process(flag, arg) if option = matching_option(flag) process(option, arg) elsif flag.start_with?("--no-") && option = matching_option(flag.sub("no-", "")) process(option, false) elsif flag =~ /\A-[^-]/ && flag.size > 2 # try and process as a set of grouped short flags. drop(1) removes # the prefixed -, then we add them back to each flag separately. flags = flag.split("").drop(1).map { |f| "-#{f}" } last = flags.pop flags.each { |f| try_process(f, nil) } try_process(last, arg) # send the argument to the last flag else if flag.start_with?("-") && !suppress_errors? raise UnknownOption.new("unknown option `#{flag}'", "#{flag}") end end end def suppress_errors? config[:suppress_errors] end def matching_option(flag) options.find { |o| o.flags.include?(flag) } end end end slop-4.2.0/lib/slop/options.rb0000644000004100000410000000655212555132036016277 0ustar www-datawww-datamodule Slop class Options include Enumerable DEFAULT_CONFIG = { suppress_errors: false, type: "null", banner: true, } # The Array of Option instances we've created. attr_reader :options # An Array of separators used for the help text. attr_reader :separators # Our Parser instance. attr_reader :parser # A Hash of configuration options. attr_reader :config # The String banner prefixed to the help string. attr_accessor :banner def initialize(**config) @options = [] @separators = [] @banner = "usage: #{$0} [options]" @config = DEFAULT_CONFIG.merge(config) @parser = Parser.new(self, @config) yield self if block_given? end # Add a new option. This method is an alias for adding a NullOption # (i.e an option with an ignored return value). # # Example: # # opts = Slop.parse do |o| # o.on '--version' do # puts Slop::VERSION # end # end # # opts.to_hash #=> {} # # Returns the newly created Option subclass. def on(*flags, **config, &block) desc = flags.pop unless flags.last.start_with?('-') config = self.config.merge(config) klass = Slop.string_to_option_class(config[:type].to_s) option = klass.new(flags, desc, config, &block) add_option option end # Add a separator between options. Used when displaying # the help text. def separator(string) if separators[options.size] separators.last << "\n#{string}" else separators[options.size] = string end end # Sugar to avoid `options.parser.parse(x)`. def parse(strings) parser.parse(strings) end # Implements the Enumerable interface. def each(&block) options.each(&block) end # Handle custom option types. Will fall back to raising an # exception if an option is not defined. def method_missing(name, *args, **config, &block) if respond_to_missing?(name) config[:type] = name on(*args, config, &block) else super end end def respond_to_missing?(name, include_private = false) Slop.option_defined?(name) || super end # Return a copy of our options Array. def to_a options.dup end # Returns the help text for this options. Used by Result#to_s. def to_s(prefix: " " * 4) str = config[:banner] ? "#{banner}\n" : "" len = longest_flag_length options.select(&:help?).sort_by(&:tail).each_with_index do |opt, i| # use the index to fetch an associated separator if sep = separators[i] str << "#{sep}\n" end str << "#{prefix}#{opt.to_s(offset: len)}\n" end str end private def longest_flag_length (o = longest_option) && o.flag.length || 0 end def longest_option options.max { |a, b| a.flag.length <=> b.flag.length } end def add_option(option) options.each do |o| flags = o.flags & option.flags # Raise an error if we found an existing option with the same # flags. I can't immediately see a use case for this.. if flags.any? raise ArgumentError, "duplicate flags: #{flags}" end end options << option option end end end slop-4.2.0/lib/slop/types.rb0000644000004100000410000000362412555132036015745 0ustar www-datawww-datamodule Slop # Cast the option argument to a String. class StringOption < Option def call(value) value.to_s end end # Cast the option argument to true or false. # Override default_value to default to false instead of nil. # This option type does not expect an argument. However, the API # supports value being passed. This is to ensure it can capture # an explicit false value class BoolOption < Option attr_accessor :explicit_value def call(value) self.explicit_value = value true end def value if force_false? false else super end end def force_false? explicit_value == false end def default_value config[:default] || false end def expects_argument? false end end BooleanOption = BoolOption # Cast the option argument to an Integer. class IntegerOption < Option def call(value) value =~ /\A\d+\z/ && value.to_i end end IntOption = IntegerOption # Cast the option argument to a Float. class FloatOption < Option def call(value) # TODO: scientific notation, etc. value =~ /\A\d*\.*\d+\z/ && value.to_f end end # Collect multiple items into a single Array. Support # arguments separated by commas or multiple occurences. class ArrayOption < Option def call(value) @value ||= [] @value.concat value.split(delimiter, limit) end def default_value config[:default] || [] end def delimiter config[:delimiter] || "," end def limit config[:limit] || 0 end end # Cast the option argument to a Regexp. class RegexpOption < Option def call(value) Regexp.new(value) end end # An option that discards the return value, inherits from Bool # since it does not expect an argument. class NullOption < BoolOption def null? true end end end slop-4.2.0/lib/slop/option.rb0000644000004100000410000000644112555132036016111 0ustar www-datawww-datamodule Slop class Option DEFAULT_CONFIG = { help: true, tail: false, } # An Array of flags this option matches. attr_reader :flags # A custom description used for the help text. attr_reader :desc # A Hash of configuration options. attr_reader :config # An Integer count for the total times this option # has been executed. attr_reader :count # A custom proc that yields the option value when # it's executed. attr_reader :block # The end value for this option. attr_writer :value def initialize(flags, desc, **config, &block) @flags = flags @desc = desc @config = DEFAULT_CONFIG.merge(config) @block = block reset end # Reset the option count and value. Used when calling .reset # on the Parser. def reset @value = nil @count = 0 end # Since `call()` can be used/overriden in subclasses, this # method is used to do general tasks like increment count. This # ensures you don't *have* to call `super` when overriding `call()`. # It's used in the Parser. def ensure_call(value) @count += 1 if value.nil? && expects_argument? && !suppress_errors? raise Slop::MissingArgument.new("missing argument for #{flag}", flags) end @value = call(value) block.call(@value) if block.respond_to?(:call) end # This method is called immediately when an option is found. # Override it in sub-classes. def call(_value) raise NotImplementedError, "you must override the `call' method for option #{self.class}" end # By default this method does nothing. It's called when all options # have been parsed and allows you to mutate the `@value` attribute # according to other options. def finish(_result) end # Override this if this option type does not expect an argument # (i.e a boolean option type). def expects_argument? true end # Override this if you want to ignore the return value for an option # (i.e so Result#to_hash does not include it). def null? false end # Returns the value for this option. Falls back to the default (or nil). def value @value || default_value end # Returns the default value for this option (default is nil). def default_value config[:default] end # Returns true if we should ignore errors that cause exceptions to be raised. def suppress_errors? config[:suppress_errors] end # Returns all flags joined by a comma. Used by the help string. def flag flags.join(", ") end # Returns the last key as a symbol. Used in Options.to_hash. def key (config[:key] || flags.last.sub(/\A--?/, '')).tr("-", "_").to_sym end # Returns true if this option should be displayed in help text. def help? config[:help] end # Returns true if this option should be added to the tail of the help text. def tail? config[:tail] end # Returns 1 if this option should be added to the tail of the help text. # Used for sorting. def tail tail? ? 1 : -1 end # Returns the help text for this option (flags and description). def to_s(offset: 0) "%-#{offset}s %s" % [flag, desc] end end end slop-4.2.0/lib/slop/error.rb0000644000004100000410000000144312555132036015727 0ustar www-datawww-datamodule Slop # Base error class. class Error < StandardError end # Raised when calling `call` on Slop::Option (this # method must be overriden in subclasses) class NotImplementedError < Error end # Raised when an option that expects an argument is # executed without one. Suppress with the `suppress_errors` # config option. class MissingArgument < Error attr_reader :flags # Get all the flags that matches # the option with the missing argument def initialize(msg, flags) super(msg) @flags = flags end end # Raised when an unknown option is parsed. Suppress # with the `suppress_errors` config option. class UnknownOption < Error attr_reader :flag def initialize(msg, flag) super(msg) @flag = flag end end end slop-4.2.0/lib/slop.rb0000644000004100000410000000270412555132036014577 0ustar www-datawww-datarequire 'slop/option' require 'slop/options' require 'slop/parser' require 'slop/result' require 'slop/types' require 'slop/error' module Slop VERSION = '4.2.0' # Parse an array of options (defaults to ARGV). Accepts an # optional hash of configuration options and block. # # Example: # # opts = Slop.parse(["-host", "localhost"]) do |o| # o.string '-host', 'a hostname', default: '0.0.0.0' # end # opts.to_hash #=> { host: 'localhost' } # # Returns a Slop::Result. def self.parse(items = ARGV, **config, &block) Options.new(config, &block).parse(items) end # Example: # # Slop.option_defined?(:string) #=> true # Slop.option_defined?(:omg) #=> false # # Returns true if an option is defined. def self.option_defined?(name) const_defined?(string_to_option(name.to_s)) end # Example: # # Slop.string_to_option("string") #=> "StringOption" # Slop.string_to_option("some_thing") #=> "SomeThingOption" # # Returns a camel-cased class looking string with Option suffix. def self.string_to_option(s) s.gsub(/(?:^|_)([a-z])/) { $1.capitalize } + "Option" end # Example: # # Slop.string_to_option_class("string") #=> Slop::StringOption # Slop.string_to_option_class("foo") #=> uninitialized constant FooOption # # Returns the full qualified option class. Uses `#string_to_option`. def self.string_to_option_class(s) const_get(string_to_option(s)) end end slop-4.2.0/metadata.yml0000644000004100000410000000425612555132036015036 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: slop version: !ruby/object:Gem::Version version: 4.2.0 platform: ruby authors: - Lee Jarvis autorequire: bindir: bin cert_chain: [] date: 2015-06-18 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 5.0.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 5.0.0 description: A DSL for gathering options and parsing command line flags email: ljjarvis@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".travis.yml" - CHANGELOG.md - Gemfile - LICENSE - README.md - Rakefile - lib/slop.rb - lib/slop/error.rb - lib/slop/option.rb - lib/slop/options.rb - lib/slop/parser.rb - lib/slop/result.rb - lib/slop/types.rb - slop.gemspec - test/error_test.rb - test/option_test.rb - test/options_test.rb - test/parser_test.rb - test/result_test.rb - test/test_helper.rb - test/types_test.rb homepage: http://github.com/leejarvis/slop licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 2.0.0 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.5 signing_key: specification_version: 4 summary: Simple Lightweight Option Parsing test_files: - test/error_test.rb - test/option_test.rb - test/options_test.rb - test/parser_test.rb - test/result_test.rb - test/test_helper.rb - test/types_test.rb has_rdoc: slop-4.2.0/slop.gemspec0000644000004100000410000000117712555132036015054 0ustar www-datawww-data$:.unshift './lib' require 'slop' Gem::Specification.new do |s| s.name = 'slop' s.version = Slop::VERSION s.summary = 'Simple Lightweight Option Parsing' s.description = 'A DSL for gathering options and parsing command line flags' s.author = 'Lee Jarvis' s.email = 'ljjarvis@gmail.com' s.homepage = 'http://github.com/leejarvis/slop' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- test/*`.split("\n") s.license = 'MIT' s.required_ruby_version = '>= 2.0.0' s.add_development_dependency 'rake' s.add_development_dependency 'minitest', '~> 5.0.0' end slop-4.2.0/test/0000755000004100000410000000000012555132036013503 5ustar www-datawww-dataslop-4.2.0/test/types_test.rb0000644000004100000410000000557712555132036016251 0ustar www-datawww-datarequire 'test_helper' describe Slop::BoolOption do before do @options = Slop::Options.new @verbose = @options.bool "--verbose" @quiet = @options.bool "--quiet" @inversed = @options.bool "--inversed", default: true @result = @options.parse %w(--verbose --no-inversed) end it "returns true if used" do assert_equal true, @result[:verbose] end it "returns false if not used" do assert_equal false, @result[:quiet] end it "can be inversed via --no- prefix" do assert_equal false, @result[:inversed] end end describe Slop::IntegerOption do before do @options = Slop::Options.new @age = @options.integer "--age" @result = @options.parse %w(--age 20) end it "returns the value as an integer" do assert_equal 20, @result[:age] end it "returns nil for non-numbers by default" do @result.parser.parse %w(--age hello) assert_equal nil, @result[:age] end end describe Slop::FloatOption do before do @options = Slop::Options.new @apr = @options.float "--apr" @apr_value = 2.9 @result = @options.parse %W(--apr #{@apr_value}) end it "returns the value as a float" do assert_equal @apr_value, @result[:apr] end it "returns nil for non-numbers by default" do @result.parser.parse %w(--apr hello) assert_equal nil, @result[:apr] end end describe Slop::ArrayOption do before do @options = Slop::Options.new @files = @options.array "--files" @delim = @options.array "-d", delimiter: ":" @limit = @options.array "-l", limit: 2 @result = @options.parse %w(--files foo.txt,bar.rb) end it "defaults to []" do assert_equal [], @result[:d] end it "parses comma separated args" do assert_equal %w(foo.txt bar.rb), @result[:files] end it "collects multiple option values" do @result.parser.parse %w(--files foo.txt --files bar.rb) assert_equal %w(foo.txt bar.rb), @result[:files] end it "can use a custom delimiter" do @result.parser.parse %w(-d foo.txt:bar.rb) assert_equal %w(foo.txt bar.rb), @result[:d] end it "can use a custom limit" do @result.parser.parse %w(-l foo,bar,baz) assert_equal ["foo", "bar,baz"], @result[:l] end end describe Slop::NullOption do before do @options = Slop::Options.new @version = @options.null('--version') @result = @options.parse %w(--version) end it 'has a return value of true' do assert_equal true, @result[:version] end it 'is not included in to_hash' do assert_equal({}, @result.to_hash) end end describe Slop::RegexpOption do before do @options = Slop::Options.new @exclude = @options.regexp "--exclude" @exclude_value = "redirect|news" @result = @options.parse %W(--exclude #{@exclude_value}) end it "returns the value as a Regexp" do assert_equal Regexp.new(@exclude_value), @result[:exclude] end end slop-4.2.0/test/error_test.rb0000644000004100000410000000220712555132036016221 0ustar www-datawww-datarequire 'test_helper' # All raised errors tested here describe Slop::MissingArgument do it "raises when an argument is missing" do opts = Slop::Options.new opts.string "-n", "--name" assert_raises(Slop::MissingArgument) { opts.parse %w(--name) } #Assert returns the argument question begin opts.parse %w(--name) rescue Slop::MissingArgument => e assert_equal(e.flags, ["-n", "--name"]) end end it "does not raise when errors are suppressed" do opts = Slop::Options.new(suppress_errors: true) opts.string "-n", "--name" opts.parse %w(--name) end end describe Slop::UnknownOption do it "raises when an option is unknown" do opts = Slop::Options.new opts.string "-n", "--name" assert_raises(Slop::UnknownOption) { opts.parse %w(--foo) } #Assert returns the unknown option in question begin opts.parse %w(--foo) rescue Slop::UnknownOption => e assert_equal(e.flag, "--foo") end end it "does not raise when errors are suppressed" do opts = Slop::Options.new(suppress_errors: true) opts.string "-n", "--name" opts.parse %w(--foo) end end slop-4.2.0/test/options_test.rb0000644000004100000410000000433412555132036016566 0ustar www-datawww-datarequire 'test_helper' describe Slop::Options do before do @options = Slop::Options.new end describe "#on" do it "defaults to null type" do assert_kind_of Slop::NullOption, @options.on("--foo") end it "accepts custom types" do module Slop; class FooOption < Option; end; end assert_kind_of Slop::FooOption, @options.on("--foo", type: :foo) end it "adds multiple flags" do option = @options.on("-f", "-F", "--foo") assert_equal %w(-f -F --foo), option.flags end it "accepts a trailing description" do option = @options.on("--foo", "fooey") assert_equal "fooey", option.desc end it "adds the option" do option = @options.on("--foo") assert_equal [option], @options.to_a end it "raises an error when a duplicate flag is used" do @options.on("--foo") assert_raises(ArgumentError) { @options.on("--foo") } end end describe "#method_missing" do it "uses the method name as an option type" do option = @options.string("--name") assert_kind_of Slop::StringOption, option end it "raises if a type doesn't exist" do assert_raises(NoMethodError) { @options.unknown } end end describe "#respond_to?" do it "handles custom types" do module Slop; class BarOption < Option; end; end assert @options.respond_to?(:bar) end end describe "#to_s" do it "is prefixed with the banner" do assert_match(/^usage/, @options.to_s) end it "aligns option strings" do @options.on "-f", "--foo", "fooey" @options.on "-s", "short" assert_match(/^ -f, --foo fooey/, @options.to_s) assert_match(/^ -s short/, @options.to_s) end it "can use a custom prefix" do @options.on "-f", "--foo" assert_match(/^ -f, --foo/, @options.to_s(prefix: " ")) end it "ignores options with help: false" do @options.on "-x", "something", help: false refute_match(/something/, @options.to_s) end it "adds 'tail' options to the bottom of the help text" do @options.on "-h", "--help", tail: true @options.on "-f", "--foo" assert_match(/^ -h, --help/, @options.to_s.lines.last) end end end slop-4.2.0/test/option_test.rb0000644000004100000410000000132412555132036016377 0ustar www-datawww-datarequire 'test_helper' describe Slop::Option do def option(*args) Slop::Option.new(*args) end describe "#flag" do it "returns the flags joined by a comma" do assert_equal "-f, --bar", option(%w(-f --bar), nil).flag assert_equal "--bar", option(%w(--bar), nil).flag end end describe "#key" do it "uses the last flag and strips trailing hyphens" do assert_equal :foo, option(%w(-f --foo), nil).key end it "converts dashes to underscores to make multi-word options symbol-friendly" do assert_equal :foo_bar, option(%w(-f --foo-bar), nil).key end it "can be overridden" do assert_equal :bar, option(%w(-f --foo), nil, key: "bar").key end end end slop-4.2.0/test/test_helper.rb0000644000004100000410000000011712555132036016345 0ustar www-datawww-data$VERBOSE = true require 'slop' require 'minitest/autorun' require 'stringio' slop-4.2.0/test/result_test.rb0000644000004100000410000000566112555132036016415 0ustar www-datawww-datarequire 'test_helper' module Slop class ReverseEverythingOption < BoolOption def finish(result) result.used_options.grep(Slop::StringOption).each do |opt| opt.value = opt.value.reverse end end end end describe Slop::Result do before do @options = Slop::Options.new @verbose = @options.bool "-v", "--verbose" @name = @options.string "--name" @unused = @options.string "--unused" @long_option = @options.string "--long-option" @result = @options.parse %w(foo -v --name lee --long-option bar argument) end it "increments option count" do # test this here so it's more "full stack" assert_equal 1, @verbose.count assert_equal 1, @long_option.count @result.parser.parse %w(-v --verbose) assert_equal 2, @verbose.count end it "handles default values" do @options.string("--foo", default: "bar") @result.parser.parse %w() assert_equal "bar", @result[:foo] end it "handles custom finishing" do @options.string "--foo" @options.reverse_everything "-r" @result.parser.parse %w(-r --name lee --foo bar) assert_equal %w(eel rab), @result.to_hash.values_at(:name, :foo) end it "yields arguments to option blocks" do output = nil @options.string("--foo") { |v| output = v } @result.parser.parse %w(--foo bar) assert_equal output, "bar" end describe "#[]" do it "returns an options value" do assert_equal "lee", @result["name"] assert_equal "lee", @result[:name] assert_equal "lee", @result["--name"] assert_equal "bar", @result["long_option"] assert_equal "bar", @result[:long_option] assert_equal "bar", @result["--long-option"] end end describe "#[]=" do it "sets an options value" do assert_equal "lee", @result["name"] @result["name"] = "bob" assert_equal "bob", @result[:name] end it "raises if an option isn't found" do assert_raises ArgumentError do @result["zomg"] = "something" end end end describe "#method_missing" do it "checks if options have been used" do assert_equal true, @result.verbose? assert_equal false, @result.unused? assert_equal true, @result.long_option? end end describe "#option" do it "returns an option by flag" do assert_equal @verbose, @result.option("--verbose") assert_equal @verbose, @result.option("-v") assert_equal @long_option, @result.option("--long-option") end it "ignores prefixed hyphens" do assert_equal @verbose, @result.option("verbose") assert_equal @verbose, @result.option("-v") end it "returns nil if nothing is found" do assert_equal nil, @result.option("foo") end end describe "#to_hash" do it "returns option keys and values" do assert_equal({ verbose: true, name: "lee", unused: nil, long_option: "bar" }, @result.to_hash) end end end slop-4.2.0/test/parser_test.rb0000644000004100000410000000346612555132036016374 0ustar www-datawww-datarequire 'test_helper' describe Slop::Parser do before do @options = Slop::Options.new @verbose = @options.bool "-v", "--verbose" @name = @options.string "-n", "--name" @unused = @options.string "--unused" @parser = Slop::Parser.new(@options) @result = @parser.parse %w(foo -v --name lee argument) end it "ignores everything after --" do @parser.parse %w(-v -- --name lee) assert_equal [@verbose], @parser.used_options end it "parses flag=argument" do @options.integer "-p", "--port" @result.parser.parse %w(--name=bob -p=123) assert_equal "bob", @result[:name] assert_equal 123, @result[:port] end describe "parsing grouped short flags" do before do @options.bool "-q", "--quiet" end it "parses boolean flags" do @result.parser.parse %w(-qv) assert_equal true, @result.quiet? assert_equal true, @result.verbose? end it "sends the argument to the last flag" do @result.parser.parse %w(-qvn foo) assert_equal "foo", @result[:name] end it "doesn't screw up single hyphen long options" do @options.string "-host" @result.parser.parse %w(-host localhost) assert_equal "localhost", @result[:host] end end describe "#used_options" do it "returns all options that were parsed" do assert_equal [@verbose, @name], @parser.used_options end end describe "#unused_options" do it "returns all options that were not parsed" do assert_equal [@unused], @parser.unused_options end end describe "#arguments" do it "returns all unparsed arguments" do assert_equal %w(foo argument), @parser.arguments end it "does not return --" do @parser.parse %w(-v -- --name lee) assert_equal %w(--name lee), @parser.arguments end end end slop-4.2.0/.gitignore0000644000004100000410000000006212555132036014512 0ustar www-datawww-data.rvmrc .yardoc doc *.swp *.gem *.rbc Gemfile.lock slop-4.2.0/LICENSE0000644000004100000410000000203112555132036013525 0ustar www-datawww-dataCopyright (c) Lee Jarvis 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. slop-4.2.0/CHANGELOG.md0000644000004100000410000000175212555132036014342 0ustar www-datawww-dataChangelog ========= v4.2.0 (2015-04-18) ------------------- Features: * Support for Regexp option type #167 (Laurent Arnoud) * Support prefixed `--no-` for explicitly setting boolean options to `false` #168 * Better handling of flags with multiple words #169 (Tim Rogers) v4.1.0 (2015-04-18) ------------------- Features: * Support for FloatOption #156 (Rick Hull) * Support for `limit` config to ArrayOption. * Support for `tail` config to add options to the bottom of the help text. * Add explicit setter (#[]=) to Result class. #162 * Implement flag gettings for UnknownOption and MissingArgument error classes. #165 (sigurdsvela) Minor enhancements: * Reset parser every time `parse` is called. Bug fixes: * Remove "--" from unprocessed arguments #157 (David Rodríguez). v4.0.0 (2014-12-27) ------------------- Features: * Rebuilt from the ground up. See the v3 changelog for all existing changes: https://github.com/leejarvis/slop/blob/v3/CHANGES.md slop-4.2.0/README.md0000644000004100000410000002053312555132036014006 0ustar www-datawww-dataSlop ==== Slop is a simple option parser with an easy to remember syntax and friendly API. Version 4 of Slop is aimed at Ruby 2.0 or later. Please use [Version 3](https://github.com/leejarvis/slop/tree/v3) for Ruby 1.9 support. [![Build Status](https://travis-ci.org/leejarvis/slop.svg?branch=master)](http://travis-ci.org/leejarvis/slop) Installation ------------ gem install slop Usage ----- ```ruby opts = Slop.parse do |o| o.string '-h', '--host', 'a hostname' o.integer '--port', 'custom port', default: 80 o.bool '-v', '--verbose', 'enable verbose mode' o.bool '-q', '--quiet', 'suppress output (quiet mode)' o.bool '-c', '--check-ssl-certificate', 'check SSL certificate for host' o.on '--version', 'print the version' do puts Slop::VERSION exit end end ARGV #=> -v --host 192.168.0.1 --check-ssl-certificate opts[:host] #=> 192.168.0.1 opts.verbose? #=> true opts.quiet? #=> false opts.check_ssl_certificate? #=> true opts.to_hash #=> { host: "192.168.0.1", port: 80, verbose: true, quiet: false, check_ssl_certificate: true } ``` Option types ------------ Built in Option types are as follows: ```ruby o.string #=> Slop::StringOption, expects an argument o.bool #=> Slop::BoolOption, no argument, aliased to BooleanOption o.integer #=> Slop::IntegerOption, expects an argument, aliased to IntOption o.float #=> Slop::FloatOption, expects an argument o.array #=> Slop::ArrayOption, expects an argument o.regexp #=> Slop::RegexpOption, expects an argument o.null #=> Slop::NullOption, no argument and ignored from `to_hash` o.on #=> alias for o.null ``` You can see all built in types in `slop/types.rb`. Suggestions or pull requests for more types are welcome. Advanced Usage -------------- This example is really just to describe how the underlying API works. It's not necessarily the best way to do it. ```ruby opts = Slop::Options.new opts.banner = "usage: connect [options] ..." opts.separator "" opts.separator "Connection options:" opts.string "-H", "--hostname", "a hostname" opts.int "-p", "--port", "a port", default: 80 opts.separator "" opts.separator "Extra options:" opts.array "--files", "a list of files to import" opts.bool "-v", "--verbose", "enable verbose mode", default: true parser = Slop::Parser.new(opts) result = parser.parse(["--hostname", "192.168.0.1", "--no-verbose"]) result.to_hash #=> { hostname: "192.168.0.1", port: 80, # files: [], verbose: false } puts opts # prints out help ``` Arguments --------- It's common to want to retrieve an array of arguments that were not processed by the parser (i.e options or consumed arguments). You can do that with the `Result#arguments` method: ```ruby args = %w(connect --host google.com GET) opts = Slop.parse args do |o| o.string '--host' end p opts.arguments #=> ["connect", "GET"] # also aliased to `args` ``` Arrays ------ Slop has a built in `ArrayOption` for handling array values: ```ruby opts = Slop.parse do |o| # the delimiter defaults to ',' o.array '--files', 'a list of files', delimiter: ',' end # both of these will return o[:files] as ["foo.txt", "bar.rb"]: # --files foo.txt,bar.rb # --files foo.txt --files bar.rb ``` Custom option types ------------------- Slop uses option type classes for every new option added. They default to the `NullOption`. When you type `o.array` Slop looks for an option called `Slop::ArrayOption`. This class must contain at least 1 method, `call`. This method is executed at parse time, and the return value of this method is used for the option value. We can use this to build custom option types: ```ruby module Slop class PathOption < Option def call(value) Pathname.new(value) end end end opts = Slop.parse %w(--path ~/) do |o| o.path '--path', 'a custom path name' end p opts[:path] #=> # ``` Custom options can also implement a `finish` method. This method by default does nothing, but it's executed once *all* options have been parsed. This allows us to go back and mutate state without having to rely on options being parsed in a particular order. Here's an example: ```ruby module Slop class FilesOption < ArrayOption def finish(opts) if opts.expand? self.value = value.map { |f| File.expand_path(f) } end end end end opts = Slop.parse %w(--files foo.txt,bar.rb -e) do |o| o.files '--files', 'an array of files' o.bool '-e', '--expand', 'if used, list of files will be expanded' end p opts[:files] #=> ["/full/path/foo.txt", "/full/path/bar.rb"] ``` Errors ------ Slop will raise errors for the following: * An option used without an argument when it expects one: `Slop::MissingArgument` * An option used that Slop doesn't know about: `Slop::UnknownOption` These errors inherit from `Slop::Error`, so you can rescue them all. Alternatively you can suppress these errors with the `suppress_errors` config option: ```ruby opts = Slop.parse suppress_errors: true do o.string '-name' end # or per option: opts = Slop.parse do o.string '-host', suppress_errors: true o.int '-port' end ``` Printing help ------------- The return value of `Slop.parse` is a `Slop::Result` which provides a nice help string to display your options. Just `puts opts` or call `opts.to_s`: ```ruby opts = Slop.parse do |o| o.string '-h', '--host', 'hostname' o.int '-p', '--port', 'port (default: 80)', default: 80 o.string '--username' o.separator '' o.separator 'other options:' o.bool '--quiet', 'suppress output' o.on '-v', '--version' do puts "1.1.1" end end puts opts ``` Output: ``` % ruby run.rb usage: run.rb [options] -h, --host hostname -p, --port port (default: 80) --username other options: --quiet suppress output -v, --version ``` This method takes an optional `prefix` value, which defaults to `" " * 4`: ``` puts opts.to_s(prefix: " ") ``` It'll deal with aligning your descriptions according to the longest option flag. Here's an example of adding your own help option: ```ruby o.on '--help' do puts o exit end ``` Commands -------- As of version 4, Slop does not have built in support for git-style subcommands. You can use version 3 of Slop (see `v3` branch). I also expect there to be some external libraries released soon that wrap around Slop to provide support for this feature. I'll update this document when that happens. Upgrading from version 3 ------------------------ Slop v4 is completely non-backwards compatible. The code has been rewritten from the group up. If you're already using version 3 you have *have* to update your code to use version 4. Here's an overview of the more fundamental changes: #### No more `instance_eval` Before: ```ruby Slop.parse do on 'v', 'version' do puts VERSION end end ``` After: ```ruby Slop.parse do |o| o.on '-v', '--version' do puts VERSION end end ``` #### No more `as` for option types Instead, the type is declared in the method call. Before: ```ruby on 'port=', as: Integer ``` After: ```ruby o.int '--port' # or integer ``` See the custom types section of the document. #### No more trailing `=` Instead, the "does this option expect an argument" question is answered by the option type (i.e `on` and `bool` options do not expect arguments, all others do. They handle type conversion, too. #### Hyphens are required This was a hard decision to make, but you must provide prefixed hyphens when declaring your flags. This makes the underlying code much nicer and much less ambiguous, which leads to less error prone code. It also means you can easily support single hyphen prefix for a long flag, i.e `-hostname` which you could not do before. It also provides a hidden feature, which is infinity flag aliases: `o.string '-f', '-x', '--foo', '--bar', 'this is insane'` #### Strict is now on by default v3 had a `strict` option. v4 has no such option, and to suppress errors you can instead provide the `suppress_errors: true` option to Slop. #### No more parse! Where v3 has both `Slop.parse` and `Slop.parse!`, v4 only has `parse`. The former was used to decide whether Slop should or should not mutate the original args (usually ARGV). This is almost never what you want, and it can lead to confusion. Instead, `Slop::Result` provides an `arguments` methods: ```ruby opts = Slop.parse do |o| o.string '--hostname', '...' end # ARGV is "hello --hostname foo bar" p opts.arguments #=> ["hello", "bar"] ```