class Pry::Slop

rubocop:disable Metrics/ClassLength

Constants

DEFAULT_OPTIONS

Returns a default Hash of configuration options this Slop instance uses.

VERSION

Attributes

config[R]

The Hash of configuration options for this Slop instance.

options[R]

The Array of Slop::Option objects tied to this Slop instance.

Public Class Methods

new(config = {}) { |self| ... } click to toggle source

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
optspec(string, config = {}) click to toggle source

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
parse(items = ARGV, config = {}, &block) click to toggle source

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
parse!(items = ARGV, config = {}, &block) click to toggle source

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

[](key) click to toggle source

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
Also aliased as: get
add_callback(label, &block) click to toggle source

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
banner(banner = nil) click to toggle source

Get or set the banner.

banner - The String to set the banner.

Returns the banner String.

banner=(banner) click to toggle source

Set the banner.

banner - The String to set the banner.

command(command, options = {}, &block) click to toggle source

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
description(desc = nil) click to toggle source

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
description=(desc) click to toggle source

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
each(&block) click to toggle source

Enumerable interface. Yields each Slop::Option.

# File lib/pry/slop.rb, line 297
def each(&block)
  options.each(&block)
end
fetch_command(command) click to toggle source

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_option(key) click to toggle source

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
get(key)
Alias for: []
help()
Alias for: to_s
missing() click to toggle source

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
on(*objects, &block) click to toggle source

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
Also aliased as: option, opt
opt(*objects, &block)
Alias for: on
option(*objects, &block)
Alias for: on
parse(items = ARGV, &block) click to toggle source

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!(items = ARGV, &block) click to toggle source

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
present?(*keys) click to toggle source

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
respond_to_missing?(method_name, include_all = false) click to toggle source

Override this method so we can check if an option? method exists.

Returns true if this option key exists in our list of options.

Calls superclass method
# 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
run(callable = nil, &block) click to toggle source

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
separator(text) click to toggle source

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
strict?() click to toggle source

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
to_h(include_commands = false)
Alias for: to_hash
to_hash(include_commands = false) click to toggle source

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
Also aliased as: to_h
to_s() click to toggle source

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
Also aliased as: help

Private Instance Methods

autocreate(items, index) click to toggle source

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_option(objects, &block) click to toggle source

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
clean(object) click to toggle source

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
commands_to_help() click to toggle source
# 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_multiple_switches(option, argument, index) click to toggle source

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_option(option, argument, index, item = nil) click to toggle source

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_long_flag(objects, config) click to toggle source

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_option(flag) click to toggle source

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_short_flag(objects, config) click to toggle source

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
method_missing(method, *args, &block) click to toggle source

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().

Calls superclass method
# 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_item(items, index) { |item| ... } click to toggle source

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