class Pry::Slop
rubocop:disable Metrics/ClassLength
Constants
- DEFAULT_OPTIONS
Returns a default Hash of configuration options this
Slop
instance uses.- VERSION
Attributes
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/pry/slop.rb, line 127 def initialize(config = {}, &block) @config = DEFAULT_OPTIONS.merge(config) @options = [] @commands = {} @trash = [] @triggered_options = [] @unknown_options = [] @callbacks = {} @separators = {} @runner = nil if block_given? block.arity == 1 ? yield(self) : instance_eval(&block) end return unless config[:help] on('-h', '--help', 'Display this help message.', tail: true) do warn help 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 Slop.new
Examples:
opts = Slop.optspec(<<-SPEC) ruby foo.rb [options] --- n,name= Your name a,age= Your age A,auth Sign in with auth p,passcode= Your secret pass code SPEC opts.fetch_option(:name).description #=> "Your name"
Returns a new instance of Slop
.
# File lib/pry/slop.rb, line 97 def optspec(string, config = {}) 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 Slop.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/pry/slop.rb, line 54 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 Slop.new()
. block - An optional block used to add options.
Returns a new instance of Slop
.
# File lib/pry/slop.rb, line 63 def parse!(items = ARGV, config = {}, &block) if items.is_a?(Hash) && config.empty? config = items items = ARGV end slop = Pry::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/pry/slop.rb, line 278 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/pry/slop.rb, line 398 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 Slop::new
)
Returns a new instance of Slop
mapped to this command.
# File lib/pry/slop.rb, line 196 def command(command, options = {}, &block) @commands[command.to_s] = Pry::Slop.new(options, &block) end
Get or set the description (used for commands).
desc - The String to set the description.
Returns the description String.
# File lib/pry/slop.rb, line 185 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/pry/slop.rb, line 176 def description=(desc) config[:description] = desc end
Enumerable interface. Yields each Slop::Option
.
# File lib/pry/slop.rb, line 297 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/pry/slop.rb, line 389 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/pry/slop.rb, line 373 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/pry/slop.rb, line 357 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/pry/slop.rb, line 265 def on(*objects, &block) option = build_option(objects, &block) 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/pry/slop.rb, line 206 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/pry/slop.rb, line 219 def parse!(items = ARGV, &block) if items.empty? && @callbacks[:empty] @callbacks[:empty].each { |cb| cb.call(self) } return items end if (cmd = @commands[items[0]]) return cmd.parse! items[1..-1] 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 @runner.call(self, items) if @runner.respond_to?(:call) 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/pry/slop.rb, line 333 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/pry/slop.rb, line 340 def respond_to_missing?(method_name, include_all = 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/pry/slop.rb, line 317 def run(callable = nil, &block) @runner = callable || block return if @runner.respond_to?(:call) raise ArgumentError, "You must specify a callable object or a block to #run" end
Add string separators between options.
text - The String text to print.
# File lib/pry/slop.rb, line 405 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/pry/slop.rb, line 152 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/pry/slop.rb, line 287 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/pry/slop.rb, line 416 def to_s heads = options.reject(&:tail?) tails = (options - heads) opts = (heads + tails).select(&:help).map(&:to_s) optstr = opts.each_with_index.map do |o, i| (str = @separators[i + 1]) ? [o, str].join("\n") : o end.join("\n") if @commands.any? optstr << "\n" unless 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] banner ||= "Usage: #{File.basename($PROGRAM_NAME, '.*')}" \ "#{' [command]' if @commands.any?} [options]" 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/pry/slop.rb, line 590 def autocreate(items, index) flag = items[index] return 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
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/pry/slop.rb, line 606 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.last) objects.pop end short = extract_short_flag(objects, config) long = extract_long_flag(objects, config) desc = objects[0].respond_to?(:to_str) ? objects.shift : nil 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/pry/slop.rb, line 659 def clean(object) object.to_s.sub(/\A--?/, '') end
# File lib/pry/slop.rb, line 663 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). index - The index of the current item being processed.
Returns nothing.
# File lib/pry/slop.rb, line 552 def execute_multiple_switches(option, argument, index) execute_option(option, nil, index) argument.split('').each do |key| next unless (opt = fetch_option(key)) opt.count += 1 execute_option(opt, nil, index, key) 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/pry/slop.rb, line 519 def execute_option(option, argument, index, item = nil) unless 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/pry/slop.rb, line 644 def extract_long_flag(objects, config) flag = objects.first.to_s return unless flag =~ /\A(?:--?)?[a-zA-Z][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
Extract an option from a flag.
flag - The flag key used to extract an option.
Returns an Array of [option, argument].
# File lib/pry/slop.rb, line 567 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 = fetch_option(Regexp.last_match(1)) argument = Regexp.last_match(2) || false option.argument_in_value = true if option end end [option, argument] end
Extract the short 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/pry/slop.rb, line 626 def extract_short_flag(objects, config) flag = clean(objects.first) if flag.size == 2 && flag.end_with?('=') config[:argument] ||= true flag.chop! end return unless flag.size == 1 objects.shift flag end
Convenience method for present?(:option).
Examples:
opts.parse %( --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/pry/slop.rb, line 454 def method_missing(method, *args, &block) meth = method.to_s if meth.end_with?('?') meth = meth.chop present?(meth) || present?(meth.tr('_', '-')) 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/pry/slop.rb, line 472 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, index) else option.value = option.count > 0 option.call(nil) end else @unknown_options << item if strict? && item =~ /\A--?/ yield(item) if block && !@trash.include?(index) end end