Class: Toys::CLI

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

Overview

A Toys-based CLI.

This is the entry point for command line execution, and the stable public interface to the framework. A CLI owns the configuration: it gathers all the settings in one place, constructs the Loader that finds and loads tool definitions, and constructs the Runner that runs them. It also provides #child, which clones the configuration so a tool can be run under modified settings.

Running a tool is delegated to the Runner; #run and #load_tool are thin wrappers around it that supply the CLI's configuration.

This is the class to instantiate to create a Toys-based command line executable. For example:

#!/usr/bin/env ruby
require "toys-core"
cli = Toys::CLI.new
cli.add_source do
  def run
    puts "Hello, world!"
  end
end
exit(cli.run(*ARGV))

The currently running CLI is also available at runtime, as Toys::Context#cli. Use it when a tool needs the CLI configuration itself, most often to build a modified copy with #child. For example:

# My .toys.rb
tool "bar" do
  def run
    # Run "some-tool" with the tools from the "my-tools" gem also
    # available.
    child = cli.child(copy_sources: true) do |c|
      c.add_source(Toys::SourceSpec.gem("my-tools"), high_priority: true)
    end
    child.run("some-tool")
  end
end

A tool that simply wants to invoke another tool should instead use the runner, as described in Runner.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(executable_name: nil, middleware_stack: nil, extra_delimiters: "", toplevel_tool_dir_name: nil, toplevel_tool_file_name: nil, mixin_lookup: nil, middleware_lookup: nil, template_lookup: nil, logger_factory: nil, logger: nil, base_level: nil, error_handler: nil, completion: nil, source_list: nil, git_cache: nil, gems_util: nil) ⇒ CLI

Create a CLI.

Most configuration parameters (besides tool definitions and tool lookup paths) are set as options passed to the constructor. These options fall roughly into four categories:

  • Options affecting output behavior:
    • logger: A global logger for all tools to use
    • logger_factory: A proc that returns a logger to use
    • base_level: The default log level
    • error_handler: Callback for handling exceptions
    • executable_name: The name of the executable
  • Options affecting tool specification
    • extra_delimiters: Tool name delimiters besides space
    • completion: Tab completion handler
  • Options affecting tool definition
    • middleware_stack: The middleware applied to all tools
    • mixin_lookup: Where to find well-known mixins
    • middleware_lookup: Where to find well-known middleware
    • template_lookup: Where to find well-known templates
  • Options affecting tool sources
    • toplevel_tool_dir_name: Directory name containing tool files
    • toplevel_tool_file_name: File name for tools
    • source_list: Initial sources to populate
    • git_cache: How to resolve git sources
    • gems_util: How to resolve gem sources

Parameters:

  • logger (Logger) (defaults to: nil)

    A global logger to use for all tools. This can be set if the CLI will call at most one tool at a time. However, it will behave incorrectly if the CLI might run multiple tools concurrently with different verbosity settings (since the logger cannot have multiple level settings simultaneously). In that case, do not set a global logger, but use the logger_factory parameter instead.

  • logger_factory (Proc) (defaults to: nil)

    A proc that takes a ToolDefinition as an argument, and returns a Logger to use when running that tool. Optional. If not provided (and no global logger is set), default_logger_factory is called to get a basic default.

  • base_level (Integer) (defaults to: nil)

    The logger level that should correspond to zero verbosity. Optional. If not provided, defaults to the level the logger has before a run adjusts it (which is often Logger::WARN). See the same argument to Runner#initialize for how this interacts with nested runs.

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

    A proc that is called when an unhandled exception is detected. See the error_handler argument to Runner#initialize for the handler's contract. Because a CLI always wraps errors, a handler installed here sees only a Toys::ContextualError or a bare SignalException. Optional. If not provided, default_error_handler is called to get a basic default handler that reraises the exception.

  • executable_name (String) (defaults to: nil)

    The executable name displayed in help text. Optional. Defaults to the ruby program name.

  • extra_delimiters (String) (defaults to: "")

    A string containing characters that can function as delimiters in a tool name. Defaults to empty. Allowed characters are period, colon, and slash.

  • completion (Toys::Completion::Base) (defaults to: nil)

    A specifier for shell tab completion for the CLI as a whole. Optional. If not provided, default_completion is called to get a default completion that delegates to the tool.

  • middleware_stack (Array<Toys::Middleware::Spec>) (defaults to: nil)

    An array of middleware that will be used by default for all tools. Optional. If not provided, uses a default set of middleware defined in default_middleware_stack. To include no middleware, pass the empty array explicitly.

  • mixin_lookup (Toys::ModuleLookup) (defaults to: nil)

    A lookup for well-known mixin modules (i.e. with symbol names). Optional. If not provided, defaults to the set of standard mixins provided by toys-core, as defined by default_mixin_lookup. If you explicitly want no standard mixins, pass an empty instance of ModuleLookup.

  • middleware_lookup (Toys::ModuleLookup) (defaults to: nil)

    A lookup for well-known middleware classes. Optional. If not provided, defaults to the set of standard middleware classes provided by toys-core, as defined by default_middleware_lookup. If you explicitly want no standard middleware, pass an empty instance of ModuleLookup.

  • template_lookup (Toys::ModuleLookup) (defaults to: nil)

    A lookup for well-known template classes. Optional. If not provided, defaults to the set of standard template classes provided by toys core, as defined by default_template_lookup. If you explicitly want no standard templates, pass an empty instance of ModuleLookup.

  • toplevel_tool_dir_name (String) (defaults to: nil)

    Tools are loaded from directories of this name that appear in a search path. Optional. If not provided, search paths do not load tool directories. The standard toys executable sets this to ".toys".

  • toplevel_tool_file_name (String) (defaults to: nil)

    Tools are loaded from files of this name that appear in a search path. Optional. If not provided, search paths do not load tool files. The standard toys executable sets this to ".toys.rb". Note: This setting does not affect the name of "index" toys files, which is fixed at ".toys.rb".

  • source_list (Toys::SourceList) (defaults to: nil)

    An optional list of sources to prepopulate into the CLI.

  • git_cache (Toys::Utils::GitCache, nil) (defaults to: nil)

    A custom GitCache instance to use when resolving git sources. Optional. If nil or not specified, uses a process-wide default GitCache.

  • gems_util (Toys::Utils::Gems, nil) (defaults to: nil)

    A custom Gems utility instance to use when resolving gem sources. Optional. If nil or not specified, uses a process-wide default Gems utility.



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/toys/cli.rb', line 159

def initialize(executable_name: nil,
               middleware_stack: nil,
               extra_delimiters: "",
               toplevel_tool_dir_name: nil,
               toplevel_tool_file_name: nil,
               mixin_lookup: nil,
               middleware_lookup: nil,
               template_lookup: nil,
               logger_factory: nil,
               logger: nil,
               base_level: nil,
               error_handler: nil,
               completion: nil,
               source_list: nil,
               git_cache: nil,
               gems_util: nil)
  @executable_name = executable_name || ::File.basename($PROGRAM_NAME)
  @middleware_stack = middleware_stack || CLI.default_middleware_stack
  @mixin_lookup = mixin_lookup || CLI.default_mixin_lookup
  @middleware_lookup = middleware_lookup || CLI.default_middleware_lookup
  @template_lookup = template_lookup || CLI.default_template_lookup
  @error_handler = error_handler || CLI.default_error_handler
  @completion = completion || CLI.default_completion
  @logger = logger
  @param_logger_factory = logger_factory
  @logger_factory = logger ? proc { |_tool| logger } : logger_factory || CLI.default_logger_factory
  @base_level = base_level
  @extra_delimiters = extra_delimiters
  @tool_name_splitter = ToolNameSplitter.new(extra_delimiters)
  @toplevel_tool_dir_name = toplevel_tool_dir_name
  @toplevel_tool_file_name = toplevel_tool_file_name
  @source_list = source_list&.dup || SourceList.new
  @git_cache = git_cache
  @gems_util = gems_util
  @loader = @runner = nil
  @source_definition_mutex = ::Monitor.new
end

Instance Attribute Details

#base_levelInteger? (readonly)

The initial logger level in this CLI, used as the level for verbosity 0. May be nil, indicating it will use the initial logger setting.

Returns:

  • (Integer, nil)


290
291
292
# File 'lib/toys/cli.rb', line 290

def base_level
  @base_level
end

#completionToys::Completion::Base, Proc (readonly)

The overall completion strategy for this CLI.

Returns:



296
297
298
# File 'lib/toys/cli.rb', line 296

def completion
  @completion
end

#executable_nameString (readonly)

The effective executable name used for usage text in this CLI.

Returns:

  • (String)


258
259
260
# File 'lib/toys/cli.rb', line 258

def executable_name
  @executable_name
end

#extra_delimitersString (readonly)

The string of tool name delimiter characters (besides space).

Returns:

  • (String)


264
265
266
# File 'lib/toys/cli.rb', line 264

def extra_delimiters
  @extra_delimiters
end

#loggerLogger? (readonly)

The global logger, if any.

Returns:

  • (Logger, nil)


277
278
279
# File 'lib/toys/cli.rb', line 277

def logger
  @logger
end

#logger_factoryProc (readonly)

The logger factory.

Returns:

  • (Proc)


283
284
285
# File 'lib/toys/cli.rb', line 283

def logger_factory
  @logger_factory
end

#tool_name_splitterToys::ToolNameSplitter (readonly)

The splitter that interprets delimiters in tool names, reflecting this CLI's #extra_delimiters.



271
272
273
# File 'lib/toys/cli.rb', line 271

def tool_name_splitter
  @tool_name_splitter
end

Class Method Details

.default_completionObject

Returns a default Completion that simply uses the tool's completion.



717
718
719
720
721
# File 'lib/toys/cli.rb', line 717

def default_completion
  proc do |context|
    context.tool.completion.call(context)
  end
end

.default_error_handlerProc

Returns a bare-bones error handler that simply reraises the error it is given. A Toys::ContextualError is reraised as itself, so that a rescue block has access to the context information. An unhandled SignalException (or a subclass such as Interrupt) is also reraised as itself, so that the Ruby VM has a chance to handle it normally.

Returns:

  • (Proc)


700
701
702
# File 'lib/toys/cli.rb', line 700

def default_error_handler
  Runner::DEFAULT_ERROR_HANDLER
end

.default_logger_factoryProc

Returns a default logger factory that generates simple loggers that write to the current stderr.

Returns:

  • (Proc)


710
711
712
# File 'lib/toys/cli.rb', line 710

def default_logger_factory
  Runner::DEFAULT_LOGGER_FACTORY
end

.default_middleware_lookupToys::ModuleLookup

Returns a default ModuleLookup for middleware that points at the StandardMiddleware module.

Returns:



678
679
680
# File 'lib/toys/cli.rb', line 678

def default_middleware_lookup
  ModuleLookup.new.add_path("toys/standard_middleware")
end

.default_middleware_stackArray<Toys::Middleware::Spec>

Returns a default set of middleware that may be used as a starting point for a typical CLI. This set includes the following in order:

Returns:



653
654
655
656
657
658
659
660
# File 'lib/toys/cli.rb', line 653

def default_middleware_stack
  [
    Middleware.spec(:set_default_descriptions),
    Middleware.spec(:show_help, help_flags: true, fallback_execution: true),
    Middleware.spec(:handle_usage_errors),
    Middleware.spec(:add_verbosity_flags),
  ]
end

.default_mixin_lookupToys::ModuleLookup

Returns a default ModuleLookup for mixins that points at the StandardMixins module.

Returns:



668
669
670
# File 'lib/toys/cli.rb', line 668

def default_mixin_lookup
  ModuleLookup.new.add_path("toys/standard_mixins")
end

.default_template_lookupToys::ModuleLookup

Returns a default empty ModuleLookup for templates.

Returns:



687
688
689
# File 'lib/toys/cli.rb', line 687

def default_template_lookup
  ModuleLookup.new
end

Instance Method Details

#add_config_block(high_priority: false, source_name: nil, context_directory: nil, &block) ⇒ self

Deprecated.

Prefer #add_source.

Add a block to the source list.

This is a deprecated legacy method that has been superseded by #add_source. Instead of:

cli.add_config_block do
  ...
end

You should now:

cli.add_source do
  ...
end

Or, if you need to configure the source name or context directory:

source = Toys::SourceSpec.block(context_directory: "/var/project") do
  ...
end
cli.add_source(source)

Parameters:

  • high_priority (boolean) (defaults to: false)

    Add the source at the head of the priority list rather than the tail.

  • source_name (String) (defaults to: nil)

    The source name that will be shown in documentation for tools defined in this block. If omitted, a default unique string will be generated.

  • block (Proc)

    The source block, executed in the context of the tool DSL DSL::Tool.

  • context_directory (String, nil) (defaults to: nil)

    The context directory for tools loaded from this block. You can pass a directory path as a string, or nil to denote no context. Defaults to nil.

Returns:

  • (self)

Raises:



630
631
632
633
634
635
636
# File 'lib/toys/cli.rb', line 630

def add_config_block(high_priority: false,
                     source_name: nil,
                     context_directory: nil,
                     &block)
  spec = SourceSpec.block(source_name: source_name, context_directory: context_directory, &block)
  add_source(spec, high_priority: high_priority)
end

#add_config_path(path, high_priority: false, source_name: nil, context_directory: :parent) ⇒ self

Deprecated.

Prefer #add_source.

Add a specific tool file or directory to the source list.

This is a deprecated legacy method that has been superseded by #add_source. However, note that while add_config_path sets a particular context directory by default, #add_source does not. So the equivalent of:

cli.add_config_path("/path/to/tools")

is technically:

source = Toys::SourceSpec.path("/path/to/tools",
                               context_directory: "/path/to")
cli.add_source(source)

Parameters:

  • path (String)

    A path to add. May reference a single tool file or a tool directory.

  • high_priority (boolean) (defaults to: false)

    Add the source at the head of the priority list rather than the tail.

  • source_name (String) (defaults to: nil)

    A custom name for the root source. Optional.

  • context_directory (String, nil, :path, :parent) (defaults to: :parent)

    The context directory for tools loaded from this path. You can pass a directory path as a string, :path to denote the given path, :parent to denote the given path's parent directory, or nil to denote no context. Defaults to :parent.

Returns:

  • (self)

Raises:



580
581
582
583
584
585
586
587
588
# File 'lib/toys/cli.rb', line 580

def add_config_path(path,
                    high_priority: false,
                    source_name: nil,
                    context_directory: :parent)
  path = SourceSpec.check_and_normalize_path(path)
  context_directory = resolve_context_directory(context_directory, path)
  spec = SourceSpec.path(path, source_name: source_name, context_directory: context_directory)
  add_source(spec, high_priority: high_priority)
end

#add_search_path(search_path, high_priority: false, context_directory: :path) ⇒ self

Checks the given search directory. If it contains a tool file and/or tool directory (identified by the toplevel_tool_file_name and toplevel_tool_dir_name constructor arguments), those are added to the source list. If the given search directory path does not exist or does not contain either the file or directory, nothing is added.

The main Toys executable uses this method to load tools from directories in the TOYS_PATH.

Parameters:

  • search_path (String, Pathname)

    A directory path to search for the well-known source file and directory. Must be a String or a Pathname. Paths should generally be absolute. Relative paths will be converted to absolute, using the current working directory at call time.

  • high_priority (boolean) (defaults to: false)

    Add the sources at the head of the priority list rather than the tail.

  • context_directory (String, Pathname, nil, :path, :parent) (defaults to: :path)

    The context directory for tools loaded from sources found using this method. You can pass a directory path as a String or Pathname, :path to denote the given search_path, :parent to denote the given search_path's parent directory, or nil to denote no context. Defaults to :path. If a path is provided, it should generally be an absolute path; any relative path will be expanded relative to the current working directory at call time.

Returns:

  • (self)

Raises:



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/toys/cli.rb', line 377

def add_search_path(search_path,
                    high_priority: false,
                    context_directory: :path)
  # Pre-check for source list finalization. Do this so that we error out
  # (instead of just silently do nothing) if the source list is finalized
  # and the "empty" checks below result in no attempt to add a source.
  check_source_list_open
  search_path = SourceSpec.check_and_normalize_path(search_path, name: "search_path")
  context_directory = resolve_context_directory(context_directory, search_path)
  paths = []
  if @toplevel_tool_file_name
    file_path = ::File.join(search_path, @toplevel_tool_file_name)
    paths << @toplevel_tool_file_name if !::File.directory?(file_path) && ::File.readable?(file_path)
  end
  if @toplevel_tool_dir_name
    dir_path = ::File.join(search_path, @toplevel_tool_dir_name)
    paths << @toplevel_tool_dir_name if ::File.directory?(dir_path) && ::File.readable?(dir_path)
  end
  unless paths.empty?
    spec = SourceSpec.path(search_path, relative_paths: paths, context_directory: context_directory)
    add_source(spec, high_priority: high_priority)
  end
  self
end

#add_search_path_hierarchy(start: nil, terminate: [], high_priority: false, context_directory: :path) ⇒ self

Walk up the directory hierarchy from the given start location, searching for toplevel tool files and directories, and add any found. Starts at the given directory and works up through parent directories until it reaches the file system root or it encounters one of the "terminate" directories.

The main Toys executable uses this method to load tools from the current directory and its ancestors.

Parameters:

  • start (String, Pathname, nil) (defaults to: nil)

    The first directory path to search. If not given, defaults to the current working directory. If provided, must be a String or a Pathname. Paths should generally be absolute. Relative paths will be converted to absolute, using the current working directory at call time.

  • terminate (Array<String,Pathname>) (defaults to: [])

    Optional list of directories that should terminate the search. If the walk up the directory tree encounters one of these directories, the search is halted without checking the terminating directory. Terminating directories should generally be absolute paths. Relative paths will be converted to absolute, using the current working directory at call time.

  • high_priority (boolean) (defaults to: false)

    Add the sources at the head of the priority list rather than the tail.

  • context_directory (String, Pathname, nil, :path, :parent) (defaults to: :path)

    The context directory for tools loaded from sources found using this method. You can pass a directory path as a String or Pathname, :path to denote the current path during the directory walk, :parent to denote the current walk directory's parent directory, or nil to denote no context. Defaults to :path, which is the behavior of the Toys executable when it loads tools from the current directory and its ancestors. If a context directory path is provided, it should generally be an absolute path; any relative path will be expanded relative to the current working directory at call time.

Returns:

  • (self)

Raises:



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'lib/toys/cli.rb', line 440

def add_search_path_hierarchy(start: nil,
                              terminate: [],
                              high_priority: false,
                              context_directory: :path)
  start = SourceSpec.check_and_normalize_path(start || ::Dir.getwd, name: "start path")
  terminate = terminate.map { |path| SourceSpec.check_and_normalize_path(path, name: "terminate path") }
  path = start
  paths = []
  loop do
    break if terminate.include?(path)
    paths << path
    next_path = ::File.dirname(path)
    break if next_path == path
    path = next_path
  end
  paths.reverse! if high_priority
  paths.each do |p|
    add_search_path(p, high_priority: high_priority, context_directory: context_directory)
  end
  self
end

#add_source(spec = nil, high_priority: false, &block) ⇒ self

Add a source to the source list, described by the given source spec.

This is generally used to load a static or "built-in" set of tools, either for a standalone command line executable based on Toys, or to provide a "default" set of tools for a dynamic executable. For example, the main Toys executable uses this to load the builtin tools from its "builtins" directory.

The source can be specified in one of three ways:

  • A source spec built using one of the SourceSpec module methods. If you need to configure the context directory or name of the source, you must use a full SourceSpec object.
  • A string (or other object convertible to a path, such as a Pathname) interpreted as a file system path, which will be passed to SourceSpec.path to get the source spec.
  • A block, which will be passed to SourceSpec.block to get the source spec. (Do not include an argument if passing a block.)

The spec is not resolved here. The loader resolves it, at most once, the first time it looks up a tool, so a source that cannot be read, fetched, or activated fails then rather than now.

Parameters:

  • spec (Toys::SourceSpec::Base, String) (defaults to: nil)

    The source spec to add.

  • high_priority (boolean) (defaults to: false)

    Add the source at the head of the priority list rather than the tail.

Returns:

  • (self)

Raises:

  • (ArgumentError)

    if no source is given, or if the given source is neither a source spec nor a legal path.

  • (Toys::SourceListFinalizedError)

    if the source list has already been finalized.



332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/toys/cli.rb', line 332

def add_source(spec = nil, high_priority: false, &block)
  if block
    raise ::ArgumentError, "Ambiguous source: both spec and block passed" if spec
    spec = SourceSpec.block(&block)
  elsif !spec.is_a?(SourceSpec::Base)
    raise ::ArgumentError, "No source spec, path, or block given" if spec.nil?
    # Anything else is taken as a path.
    spec = SourceSpec.path(spec)
  end
  ensure_source_list_open do
    @source_list.add(spec, high_priority: high_priority)
  end
  self
end

#child(copy_sources: false, **opts) {|cli| ... } ⇒ Toys::CLI

Make a clone of this CLI with the same settings.

By default, the new CLI has no tool sources, which is sometimes useful for calling another tool that has to be loaded from a different source configuration. Alternately, you can pass copy_sources: true to start with the same sources as the original (to which you can add additional sources before starting to load tools). Sources are copied before the block (if any) is called, so any sources the block adds at high priority will take priority over the originals.

Parameters:

  • copy_sources (boolean) (defaults to: false)

    If true, the new CLI is populated with the same sources as the original. Default is false, resulting in a copy with no sources initially.

  • opts (keywords)

    Any configuration arguments that should be modified from the original. See #initialize for a list of recognized keywords.

Yield Parameters:

  • cli (Toys::CLI)

    If you pass a block, the new CLI is yielded to it so you can add paths and make other modifications.

Returns:



218
219
220
221
222
# File 'lib/toys/cli.rb', line 218

def child(copy_sources: false, **opts)
  cli = CLI.new(**current_settings(copy_sources), **opts)
  yield cli if block_given?
  cli
end

#finalize_sources!self

Finalize the source list. Any subsequent attempt to add a source will raise SourceListFinalizedError.

Returns:

  • (self)


523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/toys/cli.rb', line 523

def finalize_sources!
  @source_definition_mutex.synchronize do
    unless @loader
      loader = Loader.new(@source_list,
                          middleware_stack: @middleware_stack,
                          tool_name_splitter: @tool_name_splitter,
                          mixin_lookup: @mixin_lookup,
                          template_lookup: @template_lookup,
                          middleware_lookup: @middleware_lookup,
                          git_cache: @git_cache,
                          gems_util: @gems_util)
      runner = Runner.new(loader,
                          logger_factory: @logger_factory,
                          base_level: @base_level,
                          error_handler: @error_handler,
                          executable_name: @executable_name,
                          external_data: {Context::Key::CLI => self})
      @loader = loader
      @runner = runner
    end
  end
  self
end

#load_tool(*args, verbosity: 0) {|context| ... } ⇒ Object

Prepare a tool to be run, but just execute the given block rather than performing a full run of the tool. This is intended for testing tools.

Unlike #run, this neither wraps errors nor passes them to the error handler. An error such as a failure to parse arguments or to load the requested tool is raised out of this method as-is, so the block does not execute and this method does not return.

Note that calling this finalizes this CLI's source list if not already finalized. Any subsequent attempt to add a source raises SourceListFinalizedError.

Parameters:

  • args (String...)

    Command line arguments specifying which tool to run and what arguments to pass to it. You may pass either a single array of strings, or a series of string arguments.

  • verbosity (Integer) (defaults to: 0)

    Initial verbosity. Default is 0.

Yield Parameters:

Returns:

  • (Object)

    The value returned from the block.



508
509
510
511
512
513
514
515
# File 'lib/toys/cli.rb', line 508

def load_tool(*args, verbosity: 0)
  result = nil
  runner.run(args.flatten, verbosity: verbosity,
             wrap_errors: false, handle_errors: false) do |ctx|
    result = yield ctx
  end
  result
end

#loaderToys::Loader

The current loader for this CLI.

Note that calling this finalizes this CLI's source list if not already finalized. Any subsequent attempt to add a source raises SourceListFinalizedError.

Returns:



233
234
235
236
# File 'lib/toys/cli.rb', line 233

def loader
  finalize_sources!
  @loader
end

#run(*args, verbosity: 0) ⇒ Integer

Run the CLI with the given command line arguments. Handles exceptions using the error handler.

Any error that is not handled by the tool itself is passed to this CLI's error handler, and this method returns the exit code that the handler produces. Ordinary errors arrive as a Toys::ContextualError wrapper, but a signal that no tool intercepted arrives as the SignalException itself, unwrapped. See the error_handler argument to #initialize.

Note that calling this finalizes this CLI's source list if not already finalized. Any subsequent attempt to add a source raises SourceListFinalizedError.

Parameters:

  • args (String...)

    Command line arguments specifying which tool to run and what arguments to pass to it. You may pass either a single array of strings, or a series of string arguments.

  • verbosity (Integer) (defaults to: 0)

    Initial verbosity. Default is 0.

Returns:

  • (Integer)

    The resulting process status code (i.e. 0 for success).



483
484
485
# File 'lib/toys/cli.rb', line 483

def run(*args, verbosity: 0)
  runner.run(args.flatten, verbosity: verbosity)
end

#runnerToys::Runner

The runner this CLI uses to run tools, configured with this CLI's settings. Use it directly when you need more control over a single run than #run provides, such as turning off error handling.

Note that calling this finalizes this CLI's source list if not already finalized. Any subsequent attempt to add a source raises SourceListFinalizedError.

Returns:



249
250
251
252
# File 'lib/toys/cli.rb', line 249

def runner
  finalize_sources!
  @runner
end