Module: Toys

Defined in:
lib/toys/utils/xdg.rb,
lib/toys/cli.rb,
lib/toys/core.rb,
lib/toys/flag.rb,
lib/toys/mixin.rb,
lib/toys/compat.rb,
lib/toys/errors.rb,
lib/toys/loader.rb,
lib/toys/runner.rb,
lib/toys/context.rb,
lib/toys/acceptor.rb,
lib/toys/dsl/base.rb,
lib/toys/dsl/flag.rb,
lib/toys/dsl/tool.rb,
lib/toys/template.rb,
lib/toys/arg_parser.rb,
lib/toys/completion.rb,
lib/toys/flag_group.rb,
lib/toys/middleware.rb,
lib/toys/unique_key.rb,
lib/toys/utils/exec.rb,
lib/toys/utils/gems.rb,
lib/toys/source_info.rb,
lib/toys/source_list.rb,
lib/toys/source_spec.rb,
lib/toys/utils/pager.rb,
lib/toys/dsl/internal.rb,
lib/toys/module_lookup.rb,
lib/toys/dsl/flag_group.rb,
lib/toys/positional_arg.rb,
lib/toys/utils/terminal.rb,
lib/toys/tool_definition.rb,
lib/toys/utils/git_cache.rb,
lib/toys/utils/help_text.rb,
lib/toys/wrappable_string.rb,
lib/toys/loader/load_state.rb,
lib/toys/utils/standard_ui.rb,
lib/toys/dsl/positional_arg.rb,
lib/toys/source_info/origin.rb,
lib/toys/tool_name_splitter.rb,
lib/toys/standard_mixins/xdg.rb,
lib/toys/loader/tool_registry.rb,
lib/toys/standard_mixins/exec.rb,
lib/toys/standard_mixins/gems.rb,
lib/toys/standard_mixins/pager.rb,
lib/toys/standard_mixins/bundler.rb,
lib/toys/utils/completion_engine.rb,
lib/toys/standard_mixins/highline.rb,
lib/toys/standard_mixins/terminal.rb,
lib/toys/standard_mixins/fileutils.rb,
lib/toys/standard_mixins/git_cache.rb,
lib/toys/standard_middleware/show_help.rb,
lib/toys/standard_middleware/apply_config.rb,
lib/toys/standard_middleware/show_root_version.rb,
lib/toys/standard_middleware/add_verbosity_flags.rb,
lib/toys/standard_middleware/handle_usage_errors.rb,
lib/toys/standard_middleware/set_default_descriptions.rb,
lib/toys-core.rb

Overview

Toys is a configurable command line tool. Write commands in source files using a simple DSL, and Toys will provide the command line executable and take care of all the details such as argument parsing, online help, and error reporting. Toys is designed for software developers, IT professionals, and other power users who want to write and organize scripts to automate their workflows. It can also be used as a Rake replacement, providing a more natural command line interface for your project's build tasks.

This module contains the command line framework underlying Toys. It can be used to create command line executables using the Toys DSL and classes.

Common starting points

Some of the most commonly needed class documentation is listed below:

  • For information on the DSL used to write tools, start with DSL::Tool.
  • The base class for tool runtime (i.e. that defines the basic methods available to a tool's implementation) is Context.
  • For information on writing mixins, see Mixin.
  • For information on writing templates, see Template.
  • For information on writing acceptors, see Acceptor.
  • For information on writing custom shell completions, see Completion.
  • Standard mixins are defined under the StandardMixins module.
  • Various utilities are defined under Utils. Some of these serve as the implementations of corresponding mixins.
  • The main entrypoint for the command line framework is CLI.

Architecture layers

The classes directly under the Toys module are not grouped by directory, but fall into four layers, listed here from the outside in. Except where noted below, dependencies point downward.

  • Execution — runs tools. CLI is the main entrypoint and owns the configuration, Runner holds the environment tools run in and carries out each run, ArgParser parses the command line, and Context is the base class for tool runtime.
  • Loading — resolves a tool name to a definition. Loader discovers and loads tool definitions, SourceInfo tracks their provenance, and InputFile reads tool files. A source is described unresolved by a SourceSpec; SourceList is the ordered collection of root sources that a loader reads tools from. The loader resolves each spec into a SourceInfo when it first needs that priority level.
  • Definition — models a tool. ToolDefinition is the central class, with Flag, FlagGroup, and PositionalArg as its components, along with the pluggable Acceptor and Completion types that the DSL attaches to flags and args.
  • Support — shared vocabulary used by all of the above. This includes the pluggable extension types Mixin, Template, and Middleware, which are resolved by name through ModuleLookup, as well as WrappableString, ToolNameSplitter which interprets delimiters in tool names, the named sentinel UniqueKey, and the error classes.

The deliberate upward dependencies are:

  • The definition layer builds each tool class as a subclass of Context, so that a tool's implementation inherits the runtime methods defined there.
  • Completion is computed against a partially parsed command line, so the completion classes in the definition layer reach upward for the machinery to do it. Completion::Context holds a Loader and builds a ArgParser, and a tool's default completion uses that loader to enumerate subtools and to resolve delegation targets.
  • ToolDefinition retains the SourceInfo describing where it was defined.
  • The context key constants under Context::Key, which are UniqueKey instances, act as shared vocabulary, and are referenced from any layer.

Defined Under Namespace

Modules: Acceptor, Completion, Core, DSL, FlagGroup, InputFile, Middleware, Mixin, SourceSpec, StandardMiddleware, StandardMixins, Template, Utils Classes: ArgParser, ArgParsingError, CLI, Context, ContextualError, Flag, Loader, ModuleLookup, NotRunnableError, PositionalArg, Runner, SourceInfo, SourceList, SourceListFinalizedError, Tool, ToolDefinition, ToolDefinitionError, ToolNameSplitter, ToolSourceError, UniqueKey, WrappableString

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.executable_pathString?

Path to the executable. This can, for example, be invoked to run a subtool in a clean environment.

Returns:

  • (String)

    if there is an executable

  • (nil)

    if there is no such executable



150
151
152
# File 'lib/toys-core.rb', line 150

def executable_path
  @executable_path
end

.framework_lib_pathsArray<String> (readonly)

Array of directory absolute paths within which Ruby files for the toys-core (and toys, if present) gems live.

Returns:

  • (Array<String>)

    Array of directory paths



158
159
160
# File 'lib/toys-core.rb', line 158

def framework_lib_paths
  @framework_lib_paths
end

Class Method Details

.Tool(*args, name: nil, base: nil) ⇒ Object

Create a base class for defining a tool with a given name.

This method returns a base class for defining a tool with a given name. This is useful if the naming behavior of Tool is not adequate for your tool.

Example

class FooBar < Toys.Tool("Foo_Bar")
  desc "This is a tool called Foo_Bar"

  def run
    puts "Foo_Bar called"
  end
end

Parameters:

  • name (String) (defaults to: nil)

    Name of the tool. Defaults to a name inferred from the class name. (See Tool.)

  • base (Class) (defaults to: nil)

    Use this tool class as the base class, and inherit helper methods from it.

  • args (String, Class)

    Any string-valued positional argument is interpreted as the name. Any class-valued positional argument is interpreted as the base class.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/toys/dsl/base.rb', line 28

def Toys.Tool(*args, name: nil, base: nil) # rubocop:disable Naming/MethodName
  args.each do |arg|
    case arg
    when ::Class
      raise ::ArgumentError, "Both base keyword argument and class-valued argument received" if base
      base = arg
    when ::String, ::Symbol
      raise ::ArgumentError, "Both name keyword argument and string-valued argument received" if name
      name = arg
    else
      raise ::ArgumentError, "Unrecognized argument: #{arg}"
    end
  end
  if base && !base.ancestors.include?(::Toys::Context)
    raise ::ArgumentError, "Base class must itself be a tool"
  end
  return base || ::Toys::Tool if name.nil?
  ::Class.new(base || ::Toys::Context) do
    base_class = self
    define_singleton_method(:inherited) do |tool_class|
      # We set up LoadState *before* calling super, to make sure that, if the
      # base is already a Tool subclass that has one of these `inherited`
      # methods defined (and thus executes during super) the outermost
      # prepare_subclass needs to be called first so it wins.
      ::Toys::Loader::LoadState.prepare_subclass(tool_class, given_name: base_class == self ? name.to_s : nil)
      super(tool_class)
      # The DSL installs a method_added hook, so setup_subclass_dsl must be
      # called *after* super to avoid the hook firing as the superclass methods
      # are added.
      ::Toys::DSL::Internal.setup_subclass_dsl(tool_class)
    end
  end
end