Class: Toys::Definition::Tool

Inherits:
Object
  • Object
show all
Defined in:
lib/toys/definition/tool.rb

Overview

A Tool is a single command that can be invoked using Toys. It has a name, a series of one or more words that you use to identify the tool on the command line. It also has a set of formal flags and command line arguments supported, and a block that gets run when the tool is executed.

Constant Summary collapse

OPTPARSER_ACCEPTORS =

Built-in acceptors (i.e. those recognized by OptionParser). You can reference these acceptors directly. Otherwise, you have to add one explicitly to the tool using #add_acceptor.

::Set.new(
  [
    ::Object,
    ::NilClass,
    ::String,
    ::Integer,
    ::Float,
    ::Numeric,
    ::TrueClass,
    ::FalseClass,
    ::Array,
    ::Regexp,
    ::OptionParser::DecimalInteger,
    ::OptionParser::OctalInteger,
    ::OptionParser::DecimalNumeric
  ]
).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#default_dataHash (readonly)

Return the default argument data.

Returns:

  • (Hash)


168
169
170
# File 'lib/toys/definition/tool.rb', line 168

def default_data
  @default_data
end

#descToys::Utils::WrappableString

Returns the short description string.



125
126
127
# File 'lib/toys/definition/tool.rb', line 125

def desc
  @desc
end

#flag_definitionsArray<Toys::Definition::Flag> (readonly)

Return a list of all defined flags.

Returns:



137
138
139
# File 'lib/toys/definition/tool.rb', line 137

def flag_definitions
  @flag_definitions
end

#full_nameArray<String> (readonly)

Return the name of the tool as an array of strings. This array may not be modified.

Returns:

  • (Array<String>)


107
108
109
# File 'lib/toys/definition/tool.rb', line 107

def full_name
  @full_name
end

#long_descArray<Toys::Utils::WrappableString>

Returns the long description strings as an array.

Returns:



131
132
133
# File 'lib/toys/definition/tool.rb', line 131

def long_desc
  @long_desc
end

#middleware_stackArray<Object> (readonly)

Returns the middleware stack

Returns:

  • (Array<Object>)


174
175
176
# File 'lib/toys/definition/tool.rb', line 174

def middleware_stack
  @middleware_stack
end

#optional_arg_definitionsArray<Toys::Definition::Arg> (readonly)

Return a list of all defined optional positional arguments.

Returns:



149
150
151
# File 'lib/toys/definition/tool.rb', line 149

def optional_arg_definitions
  @optional_arg_definitions
end

#priorityInteger (readonly)

Return the priority of this tool definition.

Returns:

  • (Integer)


113
114
115
# File 'lib/toys/definition/tool.rb', line 113

def priority
  @priority
end

#remaining_args_definitionToys::Definition::Arg? (readonly)

Return the remaining arguments specification, or nil if remaining arguments are currently not supported by this tool.

Returns:



156
157
158
# File 'lib/toys/definition/tool.rb', line 156

def remaining_args_definition
  @remaining_args_definition
end

#required_arg_definitionsArray<Toys::Definition::Arg> (readonly)

Return a list of all defined required positional arguments.

Returns:



143
144
145
# File 'lib/toys/definition/tool.rb', line 143

def required_arg_definitions
  @required_arg_definitions
end

#source_pathString (readonly)

Returns the path to the file that contains the definition of this tool.

Returns:

  • (String)


180
181
182
# File 'lib/toys/definition/tool.rb', line 180

def source_path
  @source_path
end

#tool_classClass (readonly)

Return the tool class.

Returns:

  • (Class)


119
120
121
# File 'lib/toys/definition/tool.rb', line 119

def tool_class
  @tool_class
end

#used_flagsArray<String> (readonly)

Return a list of flags that have been used in the flag definitions.

Returns:

  • (Array<String>)


162
163
164
# File 'lib/toys/definition/tool.rb', line 162

def used_flags
  @used_flags
end

Instance Method Details

#add_acceptor(acceptor) ⇒ Object

Add an acceptor to the tool. This acceptor may be refereneced by name when adding a flag or an arg.

Parameters:



407
408
409
410
411
412
413
414
415
# File 'lib/toys/definition/tool.rb', line 407

def add_acceptor(acceptor)
  if @acceptors.key?(acceptor.name)
    raise ToolDefinitionError,
          "An acceptor named #{acceptor.name.inspect} has already been" \
          " defined in tool #{display_name.inspect}."
  end
  @acceptors[acceptor.name] = acceptor
  self
end

#add_flag(key, flags = [], accept: nil, default: nil, handler: nil, report_collisions: true, desc: nil, long_desc: nil) ⇒ Object

Add a flag to the current tool. Each flag must specify a key which the script may use to obtain the flag value from the context. You may then provide the flags themselves in OptionParser form.

Parameters:

  • key (String, Symbol)

    The key to use to retrieve the value from the execution context.

  • flags (Array<String>) (defaults to: [])

    The flags in OptionParser format.

  • accept (Object) (defaults to: nil)

    An acceptor that validates and/or converts the value. You may provide either the name of an acceptor you have defined, or one of the default acceptors provided by OptionParser. Optional. If not specified, accepts any value as a string.

  • default (Object) (defaults to: nil)

    The default value. This is the value that will be set in the context if this flag is not provided on the command line. Defaults to nil.

  • handler (Proc, nil) (defaults to: nil)

    An optional handler for setting/updating the value. If given, it should take two arguments, the new given value and the previous value, and it should return the new value that should be set. The default handler simply replaces the previous value. i.e. the default is effectively -> (val, _prev) { val }.

  • report_collisions (Boolean) (defaults to: true)

    Raise an exception if a flag is requested that is already in use or marked as disabled. Default is true.

  • desc (String, Array<String>, Toys::Utils::WrappableString) (defaults to: nil)

    Short description for the flag. See #desc= for a description of allowed formats. Defaults to the empty string.

  • long_desc (Array<String,Array<String>,Toys::Utils::WrappableString>) (defaults to: nil)

    Long description for the flag. See #long_desc= for a description of allowed formats. Defaults to the empty array.



496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/toys/definition/tool.rb', line 496

def add_flag(key, flags = [],
             accept: nil, default: nil, handler: nil,
             report_collisions: true,
             desc: nil, long_desc: nil)
  check_definition_state(is_arg: true)
  accept = resolve_acceptor(accept)
  flag_def = Definition::Flag.new(key, flags, @used_flags, report_collisions,
                                  accept, handler, default)
  flag_def.desc = desc if desc
  flag_def.long_desc = long_desc if long_desc
  @flag_definitions << flag_def if flag_def.active?
  @default_data[key] = default
  self
end

#add_initializer(proc, *args) ⇒ Object

Add an initializer.

Parameters:

  • proc (Proc)

    The initializer block

  • args (Object...)

    Arguments to pass to the initializer



644
645
646
647
648
# File 'lib/toys/definition/tool.rb', line 644

def add_initializer(proc, *args)
  check_definition_state
  @initializers << [proc, args]
  self
end

#add_mixin(name, mixin_module) ⇒ Object

Add a named mixin module to this tool.

Parameters:

  • name (String)

    The name of the mixin.

  • mixin_module (Module)

    The mixin module.



423
424
425
426
427
428
429
430
431
432
# File 'lib/toys/definition/tool.rb', line 423

def add_mixin(name, mixin_module)
  name = name.to_s
  if @mixins.key?(name)
    raise ToolDefinitionError,
          "A mixin named #{name.inspect} has already been defined in tool" \
          " #{display_name.inspect}."
  end
  @mixins[name] = mixin_module
  self
end

#add_optional_arg(key, default: nil, accept: nil, display_name: nil, desc: nil, long_desc: nil) ⇒ Object

Add an optional positional argument to the current tool. You must specify a key which the script may use to obtain the argument value from the context. If an optional argument is not given on the command line, the value is set to the given default.

Parameters:

  • key (String, Symbol)

    The key to use to retrieve the value from the execution context.

  • default (Object) (defaults to: nil)

    The default value. This is the value that will be set in the context if this argument is not provided on the command line. Defaults to nil.

  • accept (Object) (defaults to: nil)

    An acceptor that validates and/or converts the value. You may provide either the name of an acceptor you have defined, or one of the default acceptors provided by OptionParser. Optional. If not specified, accepts any value as a string.

  • display_name (String) (defaults to: nil)

    A name to use for display (in help text and error reports). Defaults to the key in upper case.

  • desc (String, Array<String>, Toys::Utils::WrappableString) (defaults to: nil)

    Short description for the arg. See #desc= for a description of allowed formats. Defaults to the empty string.

  • long_desc (Array<String,Array<String>,Toys::Utils::WrappableString>) (defaults to: nil)

    Long description for the arg. See #long_desc= for a description of allowed formats. Defaults to the empty array.



583
584
585
586
587
588
589
590
591
592
# File 'lib/toys/definition/tool.rb', line 583

def add_optional_arg(key, default: nil, accept: nil, display_name: nil,
                     desc: nil, long_desc: nil)
  check_definition_state(is_arg: true)
  accept = resolve_acceptor(accept)
  arg_def = Definition::Arg.new(key, :optional, accept, default,
                                desc, long_desc, display_name)
  @optional_arg_definitions << arg_def
  @default_data[key] = default
  self
end

#add_required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil) ⇒ Object

Add a required positional argument to the current tool. You must specify a key which the script may use to obtain the argument value from the context.

Parameters:

  • key (String, Symbol)

    The key to use to retrieve the value from the execution context.

  • accept (Object) (defaults to: nil)

    An acceptor that validates and/or converts the value. You may provide either the name of an acceptor you have defined, or one of the default acceptors provided by OptionParser. Optional. If not specified, accepts any value as a string.

  • display_name (String) (defaults to: nil)

    A name to use for display (in help text and error reports). Defaults to the key in upper case.

  • desc (String, Array<String>, Toys::Utils::WrappableString) (defaults to: nil)

    Short description for the arg. See #desc= for a description of allowed formats. Defaults to the empty string.

  • long_desc (Array<String,Array<String>,Toys::Utils::WrappableString>) (defaults to: nil)

    Long description for the arg. See #long_desc= for a description of allowed formats. Defaults to the empty array.



550
551
552
553
554
555
556
# File 'lib/toys/definition/tool.rb', line 550

def add_required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil)
  check_definition_state(is_arg: true)
  accept = resolve_acceptor(accept)
  arg_def = Definition::Arg.new(key, :required, accept, nil, desc, long_desc, display_name)
  @required_arg_definitions << arg_def
  self
end

#add_template(name, template_class) ⇒ Object

Add a named template class to this tool.

Parameters:

  • name (String)

    The name of the template.

  • template_class (Class)

    The template class.



440
441
442
443
444
445
446
447
448
449
# File 'lib/toys/definition/tool.rb', line 440

def add_template(name, template_class)
  name = name.to_s
  if @templates.key?(name)
    raise ToolDefinitionError,
          "A template named #{name.inspect} has already been defined in tool" \
          " #{display_name.inspect}."
  end
  @templates[name] = template_class
  self
end

#append_long_desc(long_desc) ⇒ Object

Append long description strings.

Each string may be provided as a Utils::WrappableString, a single string (which will be wrapped), or an array of strings, which will be interpreted as string fragments that will be concatenated and wrapped.

Parameters:



396
397
398
399
# File 'lib/toys/definition/tool.rb', line 396

def append_long_desc(long_desc)
  check_definition_state
  @long_desc += Utils::WrappableString.make_array(long_desc)
end

#arg_definitionsArray<Toys::Definition::Arg>

Returns all arg definitions in order: required, optional, remaining.

Returns:



262
263
264
265
266
# File 'lib/toys/definition/tool.rb', line 262

def arg_definitions
  result = required_arg_definitions + optional_arg_definitions
  result << remaining_args_definition if remaining_args_definition
  result
end

#argument_parsing_disabled?Boolean

Returns true if this tool has disabled argument parsing.

Returns:

  • (Boolean)


254
255
256
# File 'lib/toys/definition/tool.rb', line 254

def argument_parsing_disabled?
  @disable_argument_parsing
end

#custom_acceptorsArray<Toys::Definition::Acceptor>

Returns a list of all custom acceptors used by this tool.

Returns:



272
273
274
275
276
277
278
279
280
281
# File 'lib/toys/definition/tool.rb', line 272

def custom_acceptors
  result = []
  flag_definitions.each do |f|
    result << f.accept if f.accept.is_a?(Acceptor)
  end
  arg_definitions.each do |a|
    result << a.accept if a.accept.is_a?(Acceptor)
  end
  result.uniq
end

#definition_finished?Boolean

Returns true if this tool's definition has been finished and is locked.

Returns:

  • (Boolean)


246
247
248
# File 'lib/toys/definition/tool.rb', line 246

def definition_finished?
  @definition_finished
end

#disable_argument_parsingObject

Disable argument parsing for this tool



454
455
456
457
458
459
460
461
462
463
# File 'lib/toys/definition/tool.rb', line 454

def disable_argument_parsing
  check_definition_state
  if includes_arguments?
    raise ToolDefinitionError,
          "Cannot disable argument parsing for tool #{display_name.inspect}" \
          " because arguments have already been defined."
  end
  @disable_argument_parsing = true
  self
end

#disable_flag(*flags) ⇒ Object

Mark one or more flags as disabled, preventing their use by any subsequent flag definition. This may be used to prevent middleware from defining a particular flag.

Parameters:

  • flags (String...)

    The flags to disable



518
519
520
521
522
523
524
525
526
527
# File 'lib/toys/definition/tool.rb', line 518

def disable_flag(*flags)
  check_definition_state(is_arg: true)
  flags = flags.uniq
  intersection = @used_flags & flags
  unless intersection.empty?
    raise ToolDefinitionError, "Cannot disable flags already used: #{intersection.inspect}"
  end
  @used_flags.concat(flags)
  self
end

#display_nameString

Returns a displayable name of this tool, generally the full name delimited by spaces.

Returns:

  • (String)


195
196
197
# File 'lib/toys/definition/tool.rb', line 195

def display_name
  full_name.join(" ")
end

#include_mixin(name) ⇒ Object

Include the given mixin in the tool class.

Parameters:

  • name (String, Symbol, Module)

    The mixin name or module



338
339
340
341
# File 'lib/toys/definition/tool.rb', line 338

def include_mixin(name)
  tool_class.include(name)
  self
end

#includes_arguments?Boolean

Returns true if at least one flag or positional argument is defined for this tool.

Returns:

  • (Boolean)


228
229
230
231
232
# File 'lib/toys/definition/tool.rb', line 228

def includes_arguments?
  !default_data.empty? || !flag_definitions.empty? ||
    !required_arg_definitions.empty? || !optional_arg_definitions.empty? ||
    !remaining_args_definition.nil?
end

#includes_definition?Boolean

Returns true if this tool has any definition information.

Returns:

  • (Boolean)


238
239
240
# File 'lib/toys/definition/tool.rb', line 238

def includes_definition?
  includes_arguments? || runnable?
end

#includes_description?Boolean

Returns true if there is a specific description set for this tool.

Returns:

  • (Boolean)


219
220
221
# File 'lib/toys/definition/tool.rb', line 219

def includes_description?
  !long_desc.empty? || !desc.empty?
end

#lock_source_path(path) ⇒ Object

Sets the path to the file that defines this tool. A tool may be defined from at most one path. If a different path is already set, raises ToolDefinitionError

Parameters:

  • path (String)

    The path to the file defining this tool



350
351
352
353
354
355
356
357
# File 'lib/toys/definition/tool.rb', line 350

def lock_source_path(path)
  if source_path && source_path != path
    raise ToolDefinitionError,
          "Cannot redefine tool #{display_name.inspect} in #{path}" \
          " (already defined in #{source_path})"
  end
  @source_path = path
end

#resolve_acceptor(accept) ⇒ Object

Resolve the given acceptor. You may pass in a Acceptor, an acceptor name, a well-known acceptor understood by OptionParser, or nil.

Returns either nil or an acceptor that is usable by OptionParser.

If an acceptor name is given, it may be resolved by this tool or any of its ancestors. Raises ToolDefinitionError if the name is not recognized.

Parameters:

  • accept (Object)

    An acceptor input.

Returns:

  • (Object)

    The resolved acceptor.



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/toys/definition/tool.rb', line 297

def resolve_acceptor(accept)
  return accept if accept.nil? || accept.is_a?(Acceptor)
  name = accept
  accept = @acceptors.fetch(name) do |k|
    if @parent
      @parent.resolve_acceptor(k)
    elsif OPTPARSER_ACCEPTORS.include?(k)
      k
    end
  end
  if accept.nil?
    raise ToolDefinitionError, "Unknown acceptor: #{name.inspect}"
  end
  accept
end

#resolve_mixin(name) ⇒ Module?

Get the named mixin from this tool or its ancestors.

Parameters:

  • name (String)

    The mixin name

Returns:

  • (Module, nil)

    The mixin module, or nil if not found.



329
330
331
# File 'lib/toys/definition/tool.rb', line 329

def resolve_mixin(name)
  @mixins.fetch(name.to_s) { |k| @parent ? @parent.resolve_mixin(k) : nil }
end

#resolve_template(name) ⇒ Class?

Get the named template from this tool or its ancestors.

Parameters:

  • name (String)

    The template name

Returns:

  • (Class, nil)

    The template class, or nil if not found.



319
320
321
# File 'lib/toys/definition/tool.rb', line 319

def resolve_template(name)
  @templates.fetch(name.to_s) { |k| @parent ? @parent.resolve_template(k) : nil }
end

#root?Boolean

Returns true if this tool is a root tool.

Returns:

  • (Boolean)


203
204
205
# File 'lib/toys/definition/tool.rb', line 203

def root?
  full_name.empty?
end

#runnable=(proc) ⇒ Object

Set the runnable block

Parameters:

  • proc (Proc)

    The runnable block



634
635
636
# File 'lib/toys/definition/tool.rb', line 634

def runnable=(proc)
  @tool_class.to_run(&proc)
end

#runnable?Boolean

Returns true if this tool is marked as runnable.

Returns:

  • (Boolean)


211
212
213
# File 'lib/toys/definition/tool.rb', line 211

def runnable?
  @runnable
end

#set_remaining_args(key, default: [], accept: nil, display_name: nil, desc: nil, long_desc: nil) ⇒ Object

Specify what should be done with unmatched positional arguments. You must specify a key which the script may use to obtain the remaining args from the context.

Parameters:

  • key (String, Symbol)

    The key to use to retrieve the value from the execution context.

  • default (Object) (defaults to: [])

    The default value. This is the value that will be set in the context if no unmatched arguments are provided on the command line. Defaults to the empty array [].

  • accept (Object) (defaults to: nil)

    An acceptor that validates and/or converts the value. You may provide either the name of an acceptor you have defined, or one of the default acceptors provided by OptionParser. Optional. If not specified, accepts any value as a string.

  • display_name (String) (defaults to: nil)

    A name to use for display (in help text and error reports). Defaults to the key in upper case.

  • desc (String, Array<String>, Toys::Utils::WrappableString) (defaults to: nil)

    Short description for the arg. See #desc= for a description of allowed formats. Defaults to the empty string.

  • long_desc (Array<String,Array<String>,Toys::Utils::WrappableString>) (defaults to: nil)

    Long description for the arg. See #long_desc= for a description of allowed formats. Defaults to the empty array.



618
619
620
621
622
623
624
625
626
627
# File 'lib/toys/definition/tool.rb', line 618

def set_remaining_args(key, default: [], accept: nil, display_name: nil,
                       desc: nil, long_desc: nil)
  check_definition_state(is_arg: true)
  accept = resolve_acceptor(accept)
  arg_def = Definition::Arg.new(key, :remaining, accept, default,
                                desc, long_desc, display_name)
  @remaining_args_definition = arg_def
  @default_data[key] = default
  self
end

#simple_nameString

Returns the local name of this tool.

Returns:

  • (String)


186
187
188
# File 'lib/toys/definition/tool.rb', line 186

def simple_name
  full_name.last
end