Class: Toys::CLI
- Inherits:
-
Object
- Object
- Toys::CLI
- Defined in:
- core-docs/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.
Defined in the toys-core gem
Direct Known Subclasses
Instance Attribute Summary collapse
-
#base_level ⇒ Integer?
readonly
The initial logger level in this CLI, used as the level for verbosity 0.
-
#completion ⇒ Toys::Completion::Base, Proc
readonly
The overall completion strategy for this CLI.
-
#executable_name ⇒ String
readonly
The effective executable name used for usage text in this CLI.
-
#extra_delimiters ⇒ String
readonly
The string of tool name delimiter characters (besides space).
-
#logger ⇒ Logger?
readonly
The global logger, if any.
-
#logger_factory ⇒ Proc
readonly
The logger factory.
-
#tool_name_splitter ⇒ Toys::ToolNameSplitter
readonly
The splitter that interprets delimiters in tool names, reflecting this CLI's #extra_delimiters.
Class Method Summary collapse
-
.default_completion ⇒ Object
Returns a default Completion that simply uses the tool's completion.
-
.default_error_handler ⇒ Proc
Returns a bare-bones error handler that simply reraises the error it is given.
-
.default_logger_factory ⇒ Proc
Returns a default logger factory that generates simple loggers that write to the current stderr.
-
.default_middleware_lookup ⇒ Toys::ModuleLookup
Returns a default ModuleLookup for middleware that points at the StandardMiddleware module.
-
.default_middleware_stack ⇒ Array<Toys::Middleware::Spec>
Returns a default set of middleware that may be used as a starting point for a typical CLI.
-
.default_mixin_lookup ⇒ Toys::ModuleLookup
Returns a default ModuleLookup for mixins that points at the StandardMixins module.
-
.default_template_lookup ⇒ Toys::ModuleLookup
Returns a default empty ModuleLookup for templates.
Instance Method Summary collapse
-
#add_config_block(high_priority: false, source_name: nil, context_directory: nil, &block) ⇒ self
deprecated
Deprecated.
Prefer #add_source.
-
#add_config_path(path, high_priority: false, source_name: nil, context_directory: :parent) ⇒ self
deprecated
Deprecated.
Prefer #add_source.
-
#add_search_path(search_path, high_priority: false, context_directory: :path) ⇒ self
Checks the given search directory.
-
#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.
-
#add_source(spec = nil, high_priority: false, &block) ⇒ self
Add a source to the source list, described by the given source spec.
-
#child(copy_sources: false, **opts) {|cli| ... } ⇒ Toys::CLI
Make a clone of this CLI with the same settings.
-
#finalize_sources! ⇒ self
Finalize the source list.
-
#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
constructor
Create a CLI.
-
#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.
-
#loader ⇒ Toys::Loader
The current loader for this CLI.
-
#run(*args, verbosity: 0) ⇒ Integer
Run the CLI with the given command line arguments.
-
#runner ⇒ Toys::Runner
The runner this CLI uses to run tools, configured with this CLI's settings.
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 uselogger_factory: A proc that returns a logger to usebase_level: The default log levelerror_handler: Callback for handling exceptionsexecutable_name: The name of the executable
- Options affecting tool specification
extra_delimiters: Tool name delimiters besides spacecompletion: Tab completion handler
- Options affecting tool definition
middleware_stack: The middleware applied to all toolsmixin_lookup: Where to find well-known mixinsmiddleware_lookup: Where to find well-known middlewaretemplate_lookup: Where to find well-known templates
- Options affecting tool sources
toplevel_tool_dir_name: Directory name containing tool filestoplevel_tool_file_name: File name for toolssource_list: Initial sources to populategit_cache: How to resolve git sourcesgems_util: How to resolve gem sources
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'core-docs/toys/cli.rb', line 156 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) # Source available in the toys-core gem end |
Instance Attribute Details
#base_level ⇒ Integer? (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.
264 265 266 |
# File 'core-docs/toys/cli.rb', line 264 def base_level @base_level end |
#completion ⇒ Toys::Completion::Base, Proc (readonly)
The overall completion strategy for this CLI.
270 271 272 |
# File 'core-docs/toys/cli.rb', line 270 def completion @completion end |
#executable_name ⇒ String (readonly)
The effective executable name used for usage text in this CLI.
232 233 234 |
# File 'core-docs/toys/cli.rb', line 232 def executable_name @executable_name end |
#extra_delimiters ⇒ String (readonly)
The string of tool name delimiter characters (besides space).
238 239 240 |
# File 'core-docs/toys/cli.rb', line 238 def extra_delimiters @extra_delimiters end |
#logger ⇒ Logger? (readonly)
The global logger, if any.
251 252 253 |
# File 'core-docs/toys/cli.rb', line 251 def logger @logger end |
#logger_factory ⇒ Proc (readonly)
The logger factory.
257 258 259 |
# File 'core-docs/toys/cli.rb', line 257 def logger_factory @logger_factory end |
#tool_name_splitter ⇒ Toys::ToolNameSplitter (readonly)
The splitter that interprets delimiters in tool names, reflecting this CLI's #extra_delimiters.
245 246 247 |
# File 'core-docs/toys/cli.rb', line 245 def tool_name_splitter @tool_name_splitter end |
Class Method Details
.default_completion ⇒ Object
Returns a default Completion that simply uses the tool's completion.
612 613 614 |
# File 'core-docs/toys/cli.rb', line 612 def default_completion # Source available in the toys-core gem end |
.default_error_handler ⇒ Proc
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.
595 596 597 |
# File 'core-docs/toys/cli.rb', line 595 def default_error_handler # Source available in the toys-core gem end |
.default_logger_factory ⇒ Proc
Returns a default logger factory that generates simple loggers that write to the current stderr.
605 606 607 |
# File 'core-docs/toys/cli.rb', line 605 def default_logger_factory # Source available in the toys-core gem end |
.default_middleware_lookup ⇒ Toys::ModuleLookup
Returns a default ModuleLookup for middleware that points at the StandardMiddleware module.
573 574 575 |
# File 'core-docs/toys/cli.rb', line 573 def default_middleware_lookup # Source available in the toys-core gem end |
.default_middleware_stack ⇒ Array<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:
- StandardMiddleware::SetDefaultDescriptions providing defaults for description fields.
- StandardMiddleware::ShowHelp adding the
--helpflag and providing default behavior for namespaces. - StandardMiddleware::HandleUsageErrors
- StandardMiddleware::AddVerbosityFlags adding the
--verboseand--quietflags for managing the logger level.
553 554 555 |
# File 'core-docs/toys/cli.rb', line 553 def default_middleware_stack # Source available in the toys-core gem end |
.default_mixin_lookup ⇒ Toys::ModuleLookup
Returns a default ModuleLookup for mixins that points at the StandardMixins module.
563 564 565 |
# File 'core-docs/toys/cli.rb', line 563 def default_mixin_lookup # Source available in the toys-core gem end |
.default_template_lookup ⇒ Toys::ModuleLookup
Returns a default empty ModuleLookup for templates.
582 583 584 |
# File 'core-docs/toys/cli.rb', line 582 def default_template_lookup # Source available in the toys-core gem end |
Instance Method Details
#add_config_block(high_priority: false, source_name: nil, context_directory: nil, &block) ⇒ self
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)
531 532 533 534 535 536 |
# File 'core-docs/toys/cli.rb', line 531 def add_config_block(high_priority: false, source_name: nil, context_directory: nil, &block) # Source available in the toys-core gem end |
#add_config_path(path, high_priority: false, source_name: nil, context_directory: :parent) ⇒ self
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)
484 485 486 487 488 489 |
# File 'core-docs/toys/cli.rb', line 484 def add_config_path(path, high_priority: false, source_name: nil, context_directory: :parent) # Source available in the toys-core gem 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.
340 341 342 343 344 |
# File 'core-docs/toys/cli.rb', line 340 def add_search_path(search_path, high_priority: false, context_directory: :path) # Source available in the toys-core gem 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.
384 385 386 387 388 389 |
# File 'core-docs/toys/cli.rb', line 384 def add_search_path_hierarchy(start: nil, terminate: [], high_priority: false, context_directory: :path) # Source available in the toys-core gem 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.
306 307 308 |
# File 'core-docs/toys/cli.rb', line 306 def add_source(spec = nil, high_priority: false, &block) # Source available in the toys-core gem 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.
196 197 198 |
# File 'core-docs/toys/cli.rb', line 196 def child(copy_sources: false, **opts) # Source available in the toys-core gem end |
#finalize_sources! ⇒ self
Finalize the source list. Any subsequent attempt to add a source will raise SourceListFinalizedError.
447 448 449 |
# File 'core-docs/toys/cli.rb', line 447 def finalize_sources! # Source available in the toys-core gem 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.
437 438 439 |
# File 'core-docs/toys/cli.rb', line 437 def load_tool(*args, verbosity: 0) # Source available in the toys-core gem end |
#loader ⇒ Toys::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.
209 210 211 |
# File 'core-docs/toys/cli.rb', line 209 def loader # Source available in the toys-core gem 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.
412 413 414 |
# File 'core-docs/toys/cli.rb', line 412 def run(*args, verbosity: 0) # Source available in the toys-core gem end |
#runner ⇒ Toys::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.
224 225 226 |
# File 'core-docs/toys/cli.rb', line 224 def runner # Source available in the toys-core gem end |