class Slop
Constants
- DEFAULT_OPTIONS
Returns a default Hash of configuration options this Slop instance uses.
- VERSION
Attributes
The Hash of sub-commands for this Slop instance.
The Hash of configuration options for this Slop instance.
The Array of Slop::Option objects tied to this Slop instance.
Public Class Methods
Create a new instance of Slop and optionally build options via a block.
config - A Hash of configuration options. block - An optional block used to specify options.
# File lib/slop.rb, line 128 def initialize(config = {}, &block) @config = DEFAULT_OPTIONS.merge(config) @options = [] @commands = {} @trash = [] @triggered_options = [] @unknown_options = [] @callbacks = {} @separators = {} @runner = nil @command = config.delete(:command) if block_given? block.arity == 1 ? yield(self) : instance_eval(&block) end if config[:help] on('-h', '--help', 'Display this help message.', :tail => true) do puts help exit end end end
Build a Slop object from a option specification.
This allows you to design your options via a simple String rather than programatically. Do note though that with this method, you're unable to pass any advanced options to the on() method when creating options.
string - The optspec String config - A Hash of configuration options to pass to ::new
Examples:
opts = Slop.optspec("ruby foo.rb [options] --- n,name= Your name a,age= Your age A,auth Sign in with auth p,passcode= Your secret pass code ") opts.fetch_option(:name).description #=> "Your name"
Returns a new instance of Slop.
# File lib/slop.rb, line 93 def optspec(string, config = {}) warn "[DEPRECATED] `Slop.optspec` is deprecated and will be removed in version 4" config[:banner], optspec = string.split(/^--+$/, 2) if string[/^--+$/] lines = optspec.split("\n").reject(&:empty?) opts = Slop.new(config) lines.each do |line| opt, description = line.split(' ', 2) short, long = opt.split(',').map { |s| s.sub(/\A--?/, '') } opt = opts.on(short, long, description) if long && long.end_with?('=') long.sub!(/\=$/, '') opt.config[:argument] = true end end opts end
items - The Array of items to extract options from (default: ARGV). config - The Hash of configuration options to send to ::new. block - An optional block used to add options.
Examples:
Slop.parse(ARGV, :help => true) do on '-n', '--name', 'Your username', :argument => true end
Returns a new instance of Slop.
# File lib/slop.rb, line 53 def parse(items = ARGV, config = {}, &block) parse! items.dup, config, &block end
items - The Array of items to extract options from (default: ARGV). config - The Hash of configuration options to send to ::new. block - An optional block used to add options.
Returns a new instance of Slop.
# File lib/slop.rb, line 62 def parse!(items = ARGV, config = {}, &block) config, items = items, ARGV if items.is_a?(Hash) && config.empty? slop = new config, &block slop.parse! items slop end
Public Instance Methods
Fetch an options argument value.
key - The Symbol or String option short or long flag.
Returns the Object value for this option, or nil.
# File lib/slop.rb, line 293 def [](key) option = fetch_option(key) option.value if option end
Add a callback.
label - The Symbol identifier to attach this callback.
Returns nothing.
# File lib/slop.rb, line 413 def add_callback(label, &block) (@callbacks[label] ||= []) << block end
Add a new command.
command - The Symbol or String used to identify this command. options - A Hash of configuration options (see ::new)
Returns a new instance of Slop mapped to this command.
# File lib/slop.rb, line 199 def command(command, options = {}, &block) options = @config.merge(options) @commands[command.to_s] = Slop.new(options.merge(:command => command.to_s), &block) end
Get or set the description (used for commands).
desc - The String to set the description.
Returns the description String.
# File lib/slop.rb, line 188 def description(desc = nil) config[:description] = desc if desc config[:description] end
Set the description (used for commands).
desc - The String to set the description.
# File lib/slop.rb, line 179 def description=(desc) config[:description] = desc end
Enumerable interface. Yields each Slop::Option.
# File lib/slop.rb, line 312 def each(&block) options.each(&block) end
Fetch a Slop object associated with this command.
command - The String or Symbol name of the command.
Examples:
opts.command :foo do on :v, :verbose, 'Enable verbose mode' end # ruby run.rb foo -v opts.fetch_command(:foo).verbose? #=> true
# File lib/slop.rb, line 404 def fetch_command(command) @commands[command.to_s] end
Fetch a Slop::Option object.
key - The Symbol or String option key.
Examples:
opts.on(:foo, 'Something fooey', :argument => :optional) opt = opts.fetch_option(:foo) opt.class #=> Slop::Option opt.accepts_optional_argument? #=> true
Returns an Option or nil if none were found.
# File lib/slop.rb, line 388 def fetch_option(key) options.find { |option| [option.long, option.short].include?(clean(key)) } end
Fetch a list of options which were missing from the parsed list.
Examples:
opts = Slop.new do on :n, :name= on :p, :password= end opts.parse %w[ --name Lee ] opts.missing #=> ['password']
Returns an Array of Strings representing missing options.
# File lib/slop.rb, line 372 def missing (options - @triggered_options).map(&:key) end
Add an Option.
objects - An Array with an optional Hash as the last element.
Examples:
on '-u', '--username=', 'Your username' on :v, :verbose, 'Enable verbose mode'
Returns the created instance of Slop::Option.
# File lib/slop.rb, line 276 def on(*objects, &block) option = build_option(objects, &block) original = options.find do |o| o.long and o.long == option.long or o.short and o.short == option.short end options.delete(original) if original options << option option end
Parse a list of items, executing and gathering options along the way.
items - The Array of items to extract options from (default: ARGV). block - An optional block which when used will yield non options.
Returns an Array of original items.
# File lib/slop.rb, line 210 def parse(items = ARGV, &block) parse! items.dup, &block items end
Parse a list of items, executing and gathering options along the way. unlike parse() this method will remove any options and option arguments from the original Array.
items - The Array of items to extract options from (default: ARGV). block - An optional block which when used will yield non options.
Returns an Array of original items with options removed.
# File lib/slop.rb, line 223 def parse!(items = ARGV, &block) if items.empty? && @callbacks[:empty] @callbacks[:empty].each { |cb| cb.call(self) } return items end # reset the trash so it doesn't carry over if you parse multiple # times with the same instance @trash.clear if cmd = @commands[items[0]] items.shift return cmd.parse! items end items.each_with_index do |item, index| @trash << index && break if item == '--' autocreate(items, index) if config[:autocreate] process_item(items, index, &block) unless @trash.include?(index) end items.reject!.with_index { |item, index| @trash.include?(index) } missing_options = options.select { |opt| opt.required? && opt.count < 1 } if missing_options.any? raise MissingOptionError, "Missing required option(s): #{missing_options.map(&:key).join(', ')}" end if @unknown_options.any? raise InvalidOptionError, "Unknown options #{@unknown_options.join(', ')}" end if @triggered_options.empty? && @callbacks[:no_options] @callbacks[:no_options].each { |cb| cb.call(self) } end if @runner.respond_to?(:call) @runner.call(self, items) unless config[:help] and present?(:help) end items end
Check for an options presence.
Examples:
opts.parse %w( --foo ) opts.present?(:foo) #=> true opts.present?(:bar) #=> false
Returns true if all of the keys are present in the parsed arguments.
# File lib/slop.rb, line 348 def present?(*keys) keys.all? { |key| (opt = fetch_option(key)) && opt.count > 0 } end
Override this method so we can check if an option? method exists.
Returns true if this option key exists in our list of options.
# File lib/slop.rb, line 355 def respond_to_missing?(method_name, include_private = false) options.any? { |o| o.key == method_name.to_s.chop } || super end
Specify code to be executed when these options are parsed.
callable - An object responding to a call method.
yields - The instance of Slop parsing these options
An Array of unparsed arguments
Example:
Slop.parse do on :v, :verbose run do |opts, args| puts "Arguments: #{args.inspect}" if opts.verbose? end end
# File lib/slop.rb, line 332 def run(callable = nil, &block) @runner = callable || block unless @runner.respond_to?(:call) raise ArgumentError, "You must specify a callable object or a block to #run" end end
Add string separators between options.
text - The String text to print.
# File lib/slop.rb, line 420 def separator(text) if @separators[options.size] @separators[options.size] << "\n#{text}" else @separators[options.size] = text end end
Is strict mode enabled?
Returns true if strict mode is enabled, false otherwise.
# File lib/slop.rb, line 155 def strict? config[:strict] end
Returns a new Hash with option flags as keys and option values as values.
include_commands - If true, merge options from all sub-commands.
# File lib/slop.rb, line 302 def to_hash(include_commands = false) hash = Hash[options.map { |opt| [opt.key.to_sym, opt.value] }] if include_commands @commands.each { |cmd, opts| hash.merge!(cmd.to_sym => opts.to_hash) } end hash end
Print a handy Slop help string.
Returns the banner followed by available option help strings.
# File lib/slop.rb, line 431 def to_s heads = options.reject(&:tail?) tails = (options - heads) opts = (heads + tails).select(&:help).map(&:to_s) optstr = opts.each_with_index.map { |o, i| (str = @separators[i + 1]) ? [o, str].join("\n") : o }.join("\n") if @commands.any? optstr << "\n" if !optstr.empty? optstr << "\nAvailable commands:\n\n" optstr << commands_to_help optstr << "\n\nSee `<command> --help` for more information on a specific command." end banner = config[:banner] if banner.nil? banner = "Usage: #{File.basename($0, '.*')}" banner << " #{@command}" if @command banner << " [command]" if @commands.any? banner << " [options]" end if banner "#{banner}\n#{@separators[0] ? "#{@separators[0]}\n" : ''}#{optstr}" else optstr end end
Private Instance Methods
Autocreate an option on the fly. See the :autocreate Slop config option.
items - The Array of items we're parsing. index - The current Integer index for the item we're processing.
Returns nothing.
# File lib/slop.rb, line 615 def autocreate(items, index) flag = items[index] if !fetch_option(flag) && !@trash.include?(index) option = build_option(Array(flag)) argument = items[index + 1] option.config[:argument] = (argument && argument !~ /\A--?/) option.config[:autocreated] = true options << option end end
Build an option from a list of objects.
objects - An Array of objects used to build this option.
Returns a new instance of Slop::Option.
# File lib/slop.rb, line 631 def build_option(objects, &block) config = {} config[:argument] = true if @config[:arguments] config[:optional_argument] = true if @config[:optional_arguments] if objects.last.is_a?(Hash) config.merge!(objects.pop) end short = extract_short_flag(objects, config) long = extract_long_flag(objects, config) desc = objects.shift if objects[0].respond_to?(:to_str) Option.new(self, short, long, desc, config, &block) end
Remove any leading – characters from a string.
object - The Object we want to cast to a String and clean.
Returns the newly cleaned String with leading – characters removed.
# File lib/slop.rb, line 675 def clean(object) object.to_s.sub(/\A--?/, '') end
# File lib/slop.rb, line 679 def commands_to_help padding = 0 @commands.each { |c, _| padding = c.size if c.size > padding } @commands.map do |cmd, opts| " #{cmd}#{' ' * (padding - cmd.size)} #{opts.description}" end.join("\n") end
Execute a `-abc` type option where a, b and c are all options. This method is only executed if the multiple_switches argument is true.
option - The first Option object. argument - The argument to this option. (Split into multiple Options). items - The Array of items currently being parsed. index - The index of the current item being processed.
Returns nothing.
# File lib/slop.rb, line 570 def execute_multiple_switches(option, argument, items, index) execute_option(option, nil, index) flags = argument.split('') flags.each do |key| if opt = fetch_option(key) opt.count += 1 if (opt.expects_argument? || opt.accepts_optional_argument?) && (flags[-1] == opt.key) && (val = items[index+1]) execute_option(opt, val, index, key) else execute_option(opt, nil, index, key) end else raise InvalidOptionError, "Unknown option -#{key}" if strict? end end end
Execute an option, firing off callbacks and assigning arguments.
option - The Slop::Option object found by process_item. argument - The argument Object to assign to this option. index - The current Integer index of the object we're processing. item - The optional String item we're processing.
Returns nothing.
# File lib/slop.rb, line 537 def execute_option(option, argument, index, item = nil) if !option if config[:multiple_switches] && strict? raise InvalidOptionError, "Unknown option -#{item}" end return end if argument unless item && item.end_with?("=#{argument}") @trash << index + 1 unless option.argument_in_value end option.value = argument else option.value = option.count > 0 end if option.match? && !argument.match(option.config[:match]) raise InvalidArgumentError, "#{argument} is an invalid argument" end option.call(option.value) end
Extract the long flag from an item.
objects - The Array of objects passed from build_option. config - The Hash of configuration options built in build_option.
# File lib/slop.rb, line 660 def extract_long_flag(objects, config) flag = objects.first.to_s if flag =~ /\A(?:--?)?[a-zA-Z0-9][a-zA-Z0-9_.-]+\=?\??\z/ config[:argument] ||= true if flag.end_with?('=') config[:optional_argument] = true if flag.end_with?('=?') objects.shift clean(flag).sub(/\=\??\z/, '') end end
Extract an option from a flag.
flag - The flag key used to extract an option.
Returns an Array of [option, argument].
# File lib/slop.rb, line 593 def extract_option(flag) option = fetch_option(flag) option ||= fetch_option(flag.downcase) if config[:ignore_case] option ||= fetch_option(flag.gsub(/([^-])-/, '\1_')) unless option case flag when /\A--?([^=]+)=(.+)\z/, /\A-([a-zA-Z])(.+)\z/, /\A--no-(.+)\z/ option, argument = fetch_option($1), ($2 || false) option.argument_in_value = true if option end end [option, argument] end
# File lib/slop.rb, line 647 def extract_short_flag(objects, config) flag = objects[0].to_s if flag =~ /\A-?\w=?\z/ config[:argument] ||= flag.end_with?('=') objects.shift flag.delete('-=') end end
Convenience method for present?(:option).
Examples:
opts.parse %Q( --verbose ) opts.verbose? #=> true opts.other? #=> false
Returns true if this option is present. If this method does not end with a ? character it will instead call super().
# File lib/slop.rb, line 473 def method_missing(method, *args, &block) meth = method.to_s if meth.end_with?('?') meth.chop! present?(meth) || present?(meth.gsub('_', '-')) else super end end
Process a list item, figure out if it's an option, execute any callbacks, assign any option arguments, and do some sanity checks.
items - The Array of items to process. index - The current Integer index of the item we want to process. block - An optional block which when passed will yield non options.
Returns nothing.
# File lib/slop.rb, line 491 def process_item(items, index, &block) return unless item = items[index] option, argument = extract_option(item) if item.start_with?('-') if option option.count += 1 unless item.start_with?('--no-') option.count += 1 if option.key[0, 3] == "no-" @trash << index @triggered_options << option if option.expects_argument? argument ||= items.at(index + 1) if !argument || argument =~ /\A--?[a-zA-Z][a-zA-Z0-9_-]*\z/ raise MissingArgumentError, "#{option.key} expects an argument" end execute_option(option, argument, index, item) elsif option.accepts_optional_argument? argument ||= items.at(index + 1) if argument && argument =~ /\A([^\-?]|-\d)+/ execute_option(option, argument, index, item) else option.call(nil) end elsif config[:multiple_switches] && argument execute_multiple_switches(option, argument, items, index) else option.value = option.count > 0 option.call(nil) end else @unknown_options << item if strict? && item =~ /\A--?/ block.call(item) if block && !@trash.include?(index) end end