Class: Slop

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/slop.rb,
lib/slop/option.rb,
lib/slop/commands.rb

Defined Under Namespace

Classes: Commands, Error, InvalidArgumentError, InvalidCommandError, InvalidOptionError, MissingArgumentError, MissingOptionError, Option

Constant Summary collapse

VERSION =
'3.6.0'
DEFAULT_OPTIONS =

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

{
  :strict => false,
  :help => false,
  :banner => nil,
  :ignore_case => false,
  :autocreate => false,
  :arguments => false,
  :optional_arguments => false,
  :multiple_switches => true,
  :longest_flag => 0
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = {}, &block) ⇒ Slop

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.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

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



473
474
475
476
477
478
479
480
481
# 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

Instance Attribute Details

#commandsObject (readonly)

The Hash of sub-commands for this Slop instance.



122
123
124
# File 'lib/slop.rb', line 122

def commands
  @commands
end

#configObject (readonly)

The Hash of configuration options for this Slop instance.



116
117
118
# File 'lib/slop.rb', line 116

def config
  @config
end

#optionsObject (readonly)

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



119
120
121
# File 'lib/slop.rb', line 119

def options
  @options
end

Class Method Details

.optspec(string, config = {}) ⇒ Object

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.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 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

.parse(items = ARGV, config = {}, &block) ⇒ Object

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.



53
54
55
# File 'lib/slop.rb', line 53

def parse(items = ARGV, config = {}, &block)
  parse! items.dup, config, &block
end

.parse!(items = ARGV, config = {}, &block) ⇒ Object

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.



62
63
64
65
66
67
# 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

Instance Method Details

#[](key) ⇒ Object Also known as: get

Fetch an options argument value.

key - The Symbol or String option short or long flag.

Returns the Object value for this option, or nil.



293
294
295
296
# File 'lib/slop.rb', line 293

def [](key)
  option = fetch_option(key)
  option.value if option
end

#add_callback(label, &block) ⇒ Object

Add a callback.

label - The Symbol identifier to attach this callback.

Returns nothing.



413
414
415
# File 'lib/slop.rb', line 413

def add_callback(label, &block)
  (@callbacks[label] ||= []) << block
end

Get or set the banner.

banner - The String to set the banner.

Returns the banner String.



171
172
173
174
# File 'lib/slop.rb', line 171

def banner(banner = nil)
  config[:banner] = banner if banner
  config[:banner]
end

#banner=(banner) ⇒ Object

Set the banner.

banner - The String to set the banner.



162
163
164
# File 'lib/slop.rb', line 162

def banner=(banner)
  config[:banner] = banner
end

#command(command, options = {}, &block) ⇒ Object

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.



199
200
201
202
# 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

#description(desc = nil) ⇒ Object

Get or set the description (used for commands).

desc - The String to set the description.

Returns the description String.



188
189
190
191
# File 'lib/slop.rb', line 188

def description(desc = nil)
  config[:description] = desc if desc
  config[:description]
end

#description=(desc) ⇒ Object

Set the description (used for commands).

desc - The String to set the description.



179
180
181
# File 'lib/slop.rb', line 179

def description=(desc)
  config[:description] = desc
end

#each(&block) ⇒ Object

Enumerable interface. Yields each Slop::Option.



312
313
314
# File 'lib/slop.rb', line 312

def each(&block)
  options.each(&block)
end

#fetch_command(command) ⇒ Object

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


404
405
406
# File 'lib/slop.rb', line 404

def fetch_command(command)
  @commands[command.to_s]
end

#fetch_option(key) ⇒ Object

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.



388
389
390
# File 'lib/slop.rb', line 388

def fetch_option(key)
  options.find { |option| [option.long, option.short].include?(clean(key)) }
end

#missingObject

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.



372
373
374
# File 'lib/slop.rb', line 372

def missing
  (options - @triggered_options).map(&:key)
end

#on(*objects, &block) ⇒ Object Also known as: option, opt

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.



276
277
278
279
280
281
282
283
284
# 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(items = ARGV, &block) ⇒ Object

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.



210
211
212
213
# File 'lib/slop.rb', line 210

def parse(items = ARGV, &block)
  parse! items.dup, &block
  items
end

#parse!(items = ARGV, &block) ⇒ Object

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.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# 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

#present?(*keys) ⇒ Boolean

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.

Returns:

  • (Boolean)


348
349
350
# File 'lib/slop.rb', line 348

def present?(*keys)
  keys.all? { |key| (opt = fetch_option(key)) && opt.count > 0 }
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

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

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

Returns:

  • (Boolean)


355
356
357
# 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

#run(callable = nil, &block) ⇒ Object

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


332
333
334
335
336
337
# 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

#separator(text) ⇒ Object

Add string separators between options.

text - The String text to print.



420
421
422
423
424
425
426
# 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

#strict?Boolean

Is strict mode enabled?

Returns true if strict mode is enabled, false otherwise.

Returns:

  • (Boolean)


155
156
157
# File 'lib/slop.rb', line 155

def strict?
  config[:strict]
end

#to_hash(include_commands = false) ⇒ Object Also known as: to_h

Returns a new Hash with option flags as keys and option values as values.

include_commands - If true, merge options from all sub-commands.



302
303
304
305
306
307
308
# 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

#to_sObject Also known as: help

Print a handy Slop help string.

Returns the banner followed by available option help strings.



431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# 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