Module: Toys::DSL::Tool
- Defined in:
- lib/toys/dsl/tool.rb
Overview
This module defines the DSL for a Toys source.
A Toys source defines one or more named tools. It provides syntax for setting the description, defining flags and arguments, specifying how to execute the tool, and requesting mixin modules and other services. It also lets you define subtools, nested arbitrarily deep, using blocks.
Simple example
Create a file called .toys.rb in the current directory, with the
following contents:
tool "greet" do
desc "Prints a simple greeting"
optional_arg :recipient, default: "world"
def run
puts "Hello, #{recipient}!"
end
end
The DSL directives tool, desc, optional_arg, and others are defined
in this module.
Now you can execute it using:
toys greet
or try:
toys greet rubyists
Instance Method Summary collapse
-
#acceptor(name, spec = nil, type_desc: nil, &block) ⇒ self
Create a named acceptor that can be referenced by name from any flag or positional argument in this tool or its subtools.
-
#alias_tool(word, target) ⇒ self
deprecated
Deprecated.
Use #tool and pass
:delegate_relativeinstead -
#all_required(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
Create a flag group of type
:required. -
#at_least_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
(also: #at_least_one_required)
Create a flag group of type
:at_least_one. -
#at_most_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
(also: #at_most_one_required)
Create a flag group of type
:at_most_one. -
#complete_tool_args(spec = nil, **options, &block) ⇒ self
Set the shell completion strategy for this tool's arguments.
-
#completion(name, spec = nil, **options, &block) ⇒ self
Create a named completion procedure that may be used by name by any flag or positional arg in this tool or any subtool.
-
#context_directory ⇒ String?
Return the context directory for this tool.
-
#current_tool ⇒ Toys::ToolDefinition
Return the current tool definition.
-
#delegate_to(target) ⇒ self
Causes the current tool to delegate to another tool, specified by the full tool name.
-
#desc(str) ⇒ self
(also: #short_desc)
Set the short description for the current tool.
-
#disable_argument_parsing ⇒ self
Disable argument parsing for this tool.
-
#disable_flag(*flags) ⇒ self
Mark one or more flags as disabled, preventing their use by any subsequent flag definition.
-
#enforce_flags_before_args(state = true) ⇒ self
Enforce that all flags must be provided before any positional args.
-
#exactly_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
(also: #exactly_one_required)
Create a flag group of type
:exactly_one. -
#expand(template_class, *args, **kwargs) {|template| ... } ⇒ self
Expand the given template in the current location.
-
#find_data(path, type: nil) ⇒ String?
Find the given data path (file or directory).
-
#flag(key, *flags, accept: nil, default: nil, handler: nil, complete_flags: nil, complete_values: nil, report_collisions: true, group: nil, desc: nil, long_desc: nil, display_name: nil, add_method: nil, &block) ⇒ self
Add a flag to the current tool.
-
#flag_group(type: :optional, desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
Create a flag group.
-
#include(mixin, *args, **kwargs) ⇒ self
Specify that the given module should be mixed into this tool, and its methods made available when running the tool.
-
#include?(mod) ⇒ boolean
Determine if the given module/mixin has already been included.
-
#inheritable_helper_methods(val) ⇒ self
Set whether this tool's helper methods are inherited by subtools.
-
#load(path, context_directory: nil, as: nil) ⇒ self
Load another tool file or directory, as if its contents were inserted at the current location.
-
#load_gem(name, *versions, version: nil, path: nil, toys_dir: nil, context_directory: nil, as: nil) ⇒ self
Load tools from a gem, as if its contents were inserted at the current location.
-
#load_git(remote: nil, path: nil, commit: nil, update: false, context_directory: nil, as: nil) ⇒ self
Load tools from a public git repository, as if its contents were inserted at the current location.
-
#long_desc(*strs, file: nil, data: nil) ⇒ self
Add to the long description for the current tool.
-
#mixin(name, mixin_module = nil, &block) ⇒ self
Create a named mixin module that can be included by name from this tool or its subtools.
-
#on_interrupt(handler = nil, &block) ⇒ self
Specify how to handle interrupts.
-
#on_signal(signal, handler = nil, &block) ⇒ self
Specify how to handle the given signal.
-
#on_usage_error(handler = nil, &block) ⇒ self
Specify how to handle usage errors.
-
#optional_arg(key, default: nil, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self
(also: #optional)
Add an optional positional argument to the current tool.
-
#remaining_args(key, default: [], accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self
(also: #remaining)
Specify what should be done with unmatched positional arguments.
-
#require_exact_flag_match(state = true) ⇒ self
Require that flags must match exactly.
-
#required_arg(key, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self
(also: #required)
Add a required positional argument to the current tool.
-
#set(key, value = nil) ⇒ Object
Set option values statically without creating helper methods.
-
#set_context_directory(dir) ⇒ self
Set a custom context directory for this tool.
-
#source_info ⇒ Toys::SourceInfo
Return the current source info object.
-
#static(key, value = nil) ⇒ Object
Set option values statically and create helper methods.
-
#subtool_apply(&block) ⇒ Object
Applies the given block to all subtools, recursively.
-
#template(name, template_class = nil, &block) ⇒ self
Create a named template that can be expanded by name from this tool or its subtools.
-
#to_run(handler = nil, &block) ⇒ self
(also: #on_run)
Specify how to run this tool.
-
#tool(words, if_defined: :combine, delegate_to: nil, delegate_relative: nil, &block) ⇒ self
Create a subtool.
-
#toys_version!(*requirements) ⇒ self
Asserts that the current Toys version against the given requirements, raising an exception if not.
-
#toys_version?(*requirements) ⇒ boolean
Determines whether the current Toys version satisfies the given requirements.
-
#treat_unknown_flags_as_args(state = true) ⇒ self
Treat unknown flags as positional arguments.
-
#truncate_load_path! ⇒ Object
Remove lower-priority sources from the load path.
Instance Method Details
#acceptor(name, spec = nil, type_desc: nil, &block) ⇒ self
Create a named acceptor that can be referenced by name from any flag or positional argument in this tool or its subtools.
An acceptor validates the string parameter passed to a flag or positional argument. It also optionally converts the string to a different object before storing it in your tool's data.
Acceptors can be defined in one of four ways.
You can provide a regular expression. This acceptor validates only if the regex matches the entire string parameter.
You can also provide an optional conversion function as a block. If provided, function must take a variable number of arguments, the first being the matched string and the remainder being the captures from the regular expression. It should return the converted object that will be stored in the context data. If you do not provide a block, the original string will be used.
You can provide an array of possible values. The acceptor validates if the string parameter matches the string form of one of the array elements (i.e. the results of calling
to_son the array elements.)An array acceptor automatically converts the string parameter to the actual array element that it matched. For example, if the symbol
:foois in the array, it will match the string"foo", and then store the symbol:fooin the tool data.You can provide a range of possible values, along with a conversion function that converts a string parameter to a type comparable by the range. (See the "function" spec below for a detailed description of conversion functions.) If the range has numeric endpoints, the conversion function is optional because a default will be provided.
You can provide a function by passing it as a proc or a block. This function performs both validation and conversion. It should take the string parameter as its argument, and it must either return the object that should be stored in the tool data, or raise an exception (descended from
StandardError) to indicate that the string parameter is invalid.
Example
The following example creates an acceptor named "hex" that is defined via a regular expression. It uses the acceptor to validate values passed to a flag.
tool "example" do
acceptor "hex", /[0-9a-fA-F]+/, type_desc: "hex numbers"
flag :number, accept: "hex"
def run
puts "number was #{number}"
end
end
105 106 107 108 109 |
# File 'lib/toys/dsl/tool.rb', line 105 def acceptor(name, spec = nil, type_desc: nil, &block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.add_acceptor(name, spec, type_desc: type_desc || name.to_s, &block) self end |
#alias_tool(word, target) ⇒ self
Use #tool and pass :delegate_relative instead
Create an alias, representing an "alternate name" for a tool.
Note: This is functionally equivalent to creating a tool with the
:delegate_relative option. As such, alias_tool is considered
deprecated.
Example
This example defines a tool and an alias pointing to it. Both the tool
name test and the alias t will then refer to the same tool.
tool "test" do
def run
puts "Running tests..."
end
end
alias_tool "t", "test"
# Note: the following is preferred over alias_tool:
# tool "t", delegate_relative: "test"
360 361 362 363 |
# File 'lib/toys/dsl/tool.rb', line 360 def alias_tool(word, target) tool(word, delegate_relative: target) self end |
#all_required(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
Create a flag group of type :required. If a block is given, flags
defined in the block belong to the group. All flags in this group are
required.
Example
The following example creates a group of required flags.
tool "login" do
all_required do
flag :username, "--username=VAL", desc: "Set username (required)"
flag :password, "--password=VAL", desc: "Set password (required)"
end
# ...
end
760 761 762 763 764 |
# File 'lib/toys/dsl/tool.rb', line 760 def all_required(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) flag_group(type: :required, desc: desc, long_desc: long_desc, name: name, report_collisions: report_collisions, prepend: prepend, &block) end |
#at_least_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self Also known as: at_least_one_required
Create a flag group of type :at_least_one. If a block is given, flags
defined in the block belong to the group. At least one flag in this
group must be provided on the command line.
Example
The following example creates a group of flags in which one or more may be set.
tool "run-tests" do
at_least_one do
flag :unit, desc: "Run unit tests"
flag :integration, desc: "Run integration tests"
flag :performance, desc: "Run performance tests"
end
# ...
end
851 852 853 854 855 |
# File 'lib/toys/dsl/tool.rb', line 851 def at_least_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) flag_group(type: :at_least_one, desc: desc, long_desc: long_desc, name: name, report_collisions: report_collisions, prepend: prepend, &block) end |
#at_most_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self Also known as: at_most_one_required
Create a flag group of type :at_most_one. If a block is given, flags
defined in the block belong to the group. At most one flag in this
group may be provided on the command line.
Example
The following example creates a group of flags in which either one or none may be set, but not more than one.
tool "provision-server" do
at_most_one do
flag :restore_from_backup, "--restore-from-backup=VAL"
flag :restore_from_image, "--restore-from-image=VAL"
flag :clone_existing, "--clone-existing=VAL"
end
# ...
end
805 806 807 808 809 |
# File 'lib/toys/dsl/tool.rb', line 805 def at_most_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) flag_group(type: :at_most_one, desc: desc, long_desc: long_desc, name: name, report_collisions: report_collisions, prepend: prepend, &block) end |
#complete_tool_args(spec = nil, **options, &block) ⇒ self
Set the shell completion strategy for this tool's arguments. You can pass one of the following:
- The string name of a completion defined in this tool or any of its its ancestors.
- A hash of options to pass to the constructor of ToolDefinition::DefaultCompletion.
-
nilor:defaultto select the standard completion strategy (which is ToolDefinition::DefaultCompletion with no extra options). - Any other specification recognized by Completion.create.
Example
The namespace "foo" supports completion only of subtool names. It does not complete the standard flags (like --help).
tool "foo" do
complete_tool_args complete_args: false, complete_flags: false,
complete_flag_values: false
tool "bar" do
def run
puts "in foo bar"
end
end
end
1597 1598 1599 1600 1601 1602 |
# File 'lib/toys/dsl/tool.rb', line 1597 def complete_tool_args(spec = nil, **, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.completion = ToolDefinition::ScalarSpec.from(spec, , block) self end |
#completion(name, spec = nil, **options, &block) ⇒ self
Create a named completion procedure that may be used by name by any flag or positional arg in this tool or any subtool.
A completion controls tab completion for the value of a flag or
positional argument. In general, it is a Ruby Proc that takes a
context object (of type Completion::Context) and returns an
array of completion candidate strings.
Completions can be specified in one of three ways.
- A Proc object itself, either passed directly to this directive or provided as a block.
- A static array of strings, indicating the completion candidates independent of context.
- The symbol
:file_systemwhich indicates that paths in the file system should serve as completion candidates.
Example
The following example defines a completion that uses only the immediate
files in the current directory as candidates. (This is different from
the :file_system completion which will descend into subdirectories
similar to how bash completes most of its file system commands.)
completion "local-files" do |_context|
`/bin/ls`.split("\n")
end
tool "example" do
flag :file, complete_values: "local-files"
def run
puts "selected file #{file}"
end
end
258 259 260 261 262 |
# File 'lib/toys/dsl/tool.rb', line 258 def completion(name, spec = nil, **, &block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.add_completion(name, spec, **, &block) self end |
#context_directory ⇒ String?
Return the context directory for this tool. Generally, this is set to the directory containing the toys tool directory structure being read, but it may be unset (nil) if the tool was not loaded from a normal tool file. It may also be changed by the tool definition itself.
1860 1861 1862 1863 |
# File 'lib/toys/dsl/tool.rb', line 1860 def context_directory cur_tool = DSL::Internal.current_tool(self, false) cur_tool&.context_directory || source_info.context_directory end |
#current_tool ⇒ Toys::ToolDefinition
Return the current tool definition. This object can be queried to determine such information as the name, but it should not be altered.
1871 1872 1873 |
# File 'lib/toys/dsl/tool.rb', line 1871 def current_tool DSL::Internal.current_tool(self, false) end |
#delegate_to(target) ⇒ self
Causes the current tool to delegate to another tool, specified by the full tool name. When run, it simply invokes the target tool with the same arguments.
Example
This example defines a tool that runs one of its subtools. Running the
test tool will have the same effect (and recognize the same args) as
the subtool test unit.
tool "test" do
tool "unit" do
flag :faster
def run
puts "running tests..."
end
end
delegate_to "test:unit"
end
391 392 393 394 395 396 397 |
# File 'lib/toys/dsl/tool.rb', line 391 def delegate_to(target) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? state = DSL::Internal.current_load_state(self) cur_tool.delegate_to(state.canonical_absolute_tool_name(target)) self end |
#desc(str) ⇒ self Also known as: short_desc
Set the short description for the current tool. The short description
is displayed with the tool in a subtool list. You may also use the
equivalent method short_desc.
The description is a WrappableString, which may be word-wrapped when displayed in a help screen. You may pass a WrappableString directly to this method, or you may pass any input that can be used to construct a wrappable string:
- If you pass a String, its whitespace will be compacted (i.e. tabs, newlines, and multiple consecutive whitespace will be turned into a single space), and it will be word-wrapped on whitespace.
- If you pass an Array of Strings, each string will be considered a literal word that cannot be broken, and wrapping will be done across the strings in the array. In this case, whitespace is not compacted.
Examples
If you pass in a sentence as a simple string, it may be word wrapped when displayed:
desc "This sentence may be wrapped."
To specify a sentence that should never be word-wrapped, pass it as the sole element of a string array:
desc ["This sentence will not be wrapped."]
616 617 618 619 620 621 |
# File 'lib/toys/dsl/tool.rb', line 616 def desc(str) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.desc = str self end |
#disable_argument_parsing ⇒ self
Disable argument parsing for this tool. Arguments will not be parsed and the options will not be populated. Instead, tools can retrieve the full unparsed argument list by calling Context#args.
This directive is mutually exclusive with any of the directives that declare arguments or flags.
Example
tool "mytool" do
disable_argument_parsing
def run
puts "Arguments passed: #{args}"
end
end
1529 1530 1531 1532 1533 1534 |
# File 'lib/toys/dsl/tool.rb', line 1529 def disable_argument_parsing cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.disable_argument_parsing self end |
#disable_flag(*flags) ⇒ self
Mark one or more flags as disabled, preventing their use by any subsequent flag definition. This can be used to prevent middleware from defining a particular flag.
Example
This tool does not support the -v and -q short forms for the two
verbosity flags (although it still supports the long forms --verbose
and --quiet.)
tool "mytool" do
disable_flag "-v", "-q"
def run
# ...
end
end
1557 1558 1559 1560 1561 1562 |
# File 'lib/toys/dsl/tool.rb', line 1557 def disable_flag(*flags) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.disable_flag(*flags) self end |
#enforce_flags_before_args(state = true) ⇒ self
Enforce that all flags must be provided before any positional args.
That is, as soon as the first positional arg appears in the command
line arguments, flag parsing is disabled as if -- had appeared.
Issuing this directive by itself turns on enforcement. You may turn it
off by passing false as the parameter.
1445 1446 1447 1448 1449 1450 |
# File 'lib/toys/dsl/tool.rb', line 1445 def enforce_flags_before_args(state = true) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.enforce_flags_before_args(state) self end |
#exactly_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self Also known as: exactly_one_required
Create a flag group of type :exactly_one. If a block is given, flags
defined in the block belong to the group. Exactly one flag in this
group must be provided on the command line.
Example
The following example creates a group of flags in which exactly one must be set.
tool "deploy" do
exactly_one do
flag :server, "--server=IP_ADDR", desc: "Deploy to server"
flag :vm, "--vm=ID", desc: "Deploy to a VM"
flag :container, "--container=ID", desc: "Deploy to a container"
end
# ...
end
897 898 899 900 901 |
# File 'lib/toys/dsl/tool.rb', line 897 def exactly_one(desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) flag_group(type: :exactly_one, desc: desc, long_desc: long_desc, name: name, report_collisions: report_collisions, prepend: prepend, &block) end |
#expand(template_class, *args, **kwargs) {|template| ... } ⇒ self
Expand the given template in the current location.
The template may be specified as a class or a well-known template name. You may also provide arguments to pass to the template.
Example
The following example creates and uses a simple template.
template "hello-generator" do
def initialize(name, )
@name = name
@message =
end
attr_reader :name, :message
expansion do |template|
tool template.name do
to_run do
puts template.
end
end
end
end
"hello-generator", "mytool", "mytool is running!"
575 576 577 578 579 580 581 |
# File 'lib/toys/dsl/tool.rb', line 575 def (template_class, *args, **kwargs) template_class = DSL::Internal.current_load_state(self).resolve_template(template_class) template = template_class.new(*args, **kwargs) yield template if block_given? class_exec(template, &template_class.expansion) self end |
#find_data(path, type: nil) ⇒ String?
Find the given data path (file or directory).
Data directories are a convenient place to put images, archives, keys,
or other such static data needed by your tools. Data files are located
in a directory called .data inside a Toys directory. This directive
locates a data file during tool definition.
Example
This tool reads its description from a text file in the .data
directory.
tool "mytool" do
path = find_data("mytool-desc.txt", type: :file)
desc IO.read(path) if path
def run
# ...
end
end
1847 1848 1849 |
# File 'lib/toys/dsl/tool.rb', line 1847 def find_data(path, type: nil) source_info.find_data(path, type: type) end |
#flag(key, *flags, accept: nil, default: nil, handler: nil, complete_flags: nil, complete_values: nil, report_collisions: true, group: nil, desc: nil, long_desc: nil, display_name: nil, add_method: nil, &block) ⇒ self
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.
If the given key is a symbol representing a valid method name, then a helper method is automatically added to retrieve the value. Otherwise, if the key is a string or does not represent a valid method name, the tool can retrieve the value by calling Context#get.
Attributes of the flag may be passed in as arguments to this method, or set in a block passed to this method. If you provide a block, you can use directives in Flag within the block.
Flag syntax
The flags themselves should be provided in OptionParser form. Following are examples of valid syntax.
-
-a: A short boolean switch. When this appears as an argument, the value is set totrue. -
--abc: A long boolean switch. When this appears as an argument, the value is set totrue. -
-aVALor-a VAL: A short flag that takes a required value. These two forms are treated identically. If this argument appears with a value attached (e.g.-afoo), the attached string (e.g."foo") is taken as the value. Otherwise, the following argument is taken as the value (e.g. for-a foo, the value is set to"foo".) The following argument is treated as the value even if it looks like a flag (e.g.-a -acauses the string"-a"to be taken as the value.) -
-a[VAL]: A short flag that takes an optional value. If this argument appears with a value attached (e.g.-afoo), the attached string (e.g."foo") is taken as the value. Otherwise, the value is set totrue. The following argument is never interpreted as the value. (Compare with-a [VAL].) -
-a [VAL]: A short flag that takes an optional value. If this argument appears with a value attached (e.g.-afoo), the attached string (e.g."foo") is taken as the value. Otherwise, if the following argument does not look like a flag (i.e. it does not begin with a hyphen), it is taken as the value. (e.g.-a foocauses the string"foo"to be taken as the value.). If there is no following argument, or the following argument looks like a flag, the value is set totrue. (Compare with-a[VAL].) -
--abc=VALor--abc VAL: A long flag that takes a required value. These two forms are treated identically. If this argument appears with a value attached (e.g.--abc=foo), the attached string (e.g."foo") is taken as the value. Otherwise, the following argument is taken as the value (e.g. for--abc foo, the value is set to"foo".) The following argument is treated as the value even if it looks like a flag (e.g.--abc --defcauses the string"--def"to be taken as the value.) -
--abc[=VAL]: A long flag that takes an optional value. If this argument appears with a value attached (e.g.--abc=foo), the attached string (e.g."foo") is taken as the value. Otherwise, the value is set totrue. The following argument is never interpreted as the value. (Compare with--abc [VAL].) -
--abc [VAL]: A long flag that takes an optional value. If this argument appears with a value attached (e.g.--abc=foo), the attached string (e.g."foo") is taken as the value. Otherwise, if the following argument does not look like a flag (i.e. it does not begin with a hyphen), it is taken as the value. (e.g.--abc foocauses the string"foo"to be taken as the value.). If there is no following argument, or the following argument looks like a flag, the value is set totrue. (Compare with--abc=[VAL].) -
--[no-]abc: A long boolean switch that can be turned either on or off. This effectively creates two flags,--abcwhich sets the value totrue, and--no-abcwhich sets the falue tofalse.
Default flag syntax
If no flag syntax strings are provided, a default syntax will be inferred based on the key and other options.
Specifically, if the key has one character, then that character will be chosen as a short flag. If the key has multiple characters, a long flag will be generated.
Furthermore, if a custom completion, a non-boolean acceptor, or a non-boolean default value is provided in the options, then the flag will be considered to take a value. Otherwise, it will be considered to be a boolean switch.
For example, the following pairs of flags are identical:
flag :a
flag :a, "-a"
flag :abc_def
flag :abc_def, "--abc-def"
flag :number, accept: Integer
flag :number, "--number=VAL", accept: Integer
More examples
A flag that sets its value to the number of times it appears on the command line:
flag :verbose, "-v", "--verbose",
default: 0, handler: ->(_val, count) { count + 1 }
An example using block form:
flag :shout do
flags "-s", "--shout"
default false
desc "Say it louder"
long_desc "This flag says it lowder.",
"You might use this when people can't hear you.",
"",
"Example:",
[" toys say --shout hello"]
end
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 |
# File 'lib/toys/dsl/tool.rb', line 1082 def flag(key, *flags, accept: nil, default: nil, handler: nil, complete_flags: nil, complete_values: nil, report_collisions: true, group: nil, desc: nil, long_desc: nil, display_name: nil, add_method: nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? flag_dsl = DSL::Flag.new( flags.flatten, accept, default, handler, complete_flags, complete_values, report_collisions, group, desc, long_desc, display_name, add_method ) flag_dsl.instance_exec(flag_dsl, &block) if block flag_dsl._add_to(cur_tool, key) DSL::Internal.maybe_add_getter(self, key, flag_dsl._get_add_method) self end |
#flag_group(type: :optional, desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) ⇒ self
Create a flag group. If a block is given, flags defined in the block belong to the group. The flags in the group are listed together in help screens.
Example
The following example creates a flag group in which all flags are optional.
tool "execute" do
flag_group desc: "Debug Flags" do
flag :debug, "-D", desc: "Enable debugger"
flag :warnings, "-W[VAL]", desc: "Enable warnings"
end
# ...
end
711 712 713 714 715 716 717 718 719 720 721 |
# File 'lib/toys/dsl/tool.rb', line 711 def flag_group(type: :optional, desc: nil, long_desc: nil, name: nil, report_collisions: true, prepend: false, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.add_flag_group(type: type, desc: desc, long_desc: long_desc, name: name, report_collisions: report_collisions, prepend: prepend) group = prepend ? cur_tool.flag_groups.first : cur_tool.flag_groups.last flag_group_dsl = DSL::FlagGroup.new(self, cur_tool, group) flag_group_dsl.instance_exec(flag_group_dsl, &block) if block self end |
#include(mixin, *args, **kwargs) ⇒ self
Specify that the given module should be mixed into this tool, and its methods made available when running the tool.
You can provide either a module, the string name of a mixin that you have defined in this tool or one of its ancestors, or the symbol name of a well-known mixin.
The standard Ruby Module#include method can be invoked by calling
include_module instead of include.
Example
Include the well-known mixin :terminal and perform some terminal
magic.
tool "spin" do
include :terminal
def run
# The spinner method is defined by the :terminal mixin.
spinner(leading_text: "Waiting...", final_text: "\n") do
sleep 5
end
end
end
1787 1788 1789 1790 1791 1792 1793 |
# File 'lib/toys/dsl/tool.rb', line 1787 def include(mixin, *args, **kwargs) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? mod = DSL::Internal.current_load_state(self).resolve_mixin(mixin) cur_tool.include_mixin(mod, *args, **kwargs) self end |
#include?(mod) ⇒ boolean
Determine if the given module/mixin has already been included.
You can provide either a module, the string name of a mixin that you have defined in this tool or one of its ancestors, or the symbol name of a well-known mixin.
1806 1807 1808 |
# File 'lib/toys/dsl/tool.rb', line 1806 def include?(mod) super(DSL::Internal.current_load_state(self).resolve_mixin(mod)) end |
#inheritable_helper_methods(val) ⇒ self
Set whether this tool's helper methods are inherited by subtools.
1964 1965 1966 1967 1968 |
# File 'lib/toys/dsl/tool.rb', line 1964 def inheritable_helper_methods(val) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.inheritable_helper_methods = val self end |
#load(path, context_directory: nil, as: nil) ⇒ self
Load another tool file or directory, as if its contents were inserted at the current location.
Note that this directive has restrictions within a #subtool_apply block. See the #subtool_apply documentation for details.
419 420 421 422 423 424 425 426 427 428 429 430 431 |
# File 'lib/toys/dsl/tool.rb', line 419 def load(path, context_directory: nil, as: nil) if as tool(as) do load(path, context_directory: context_directory) end return self end spec = SourceSpec.path(path, context_directory: context_directory) DSL::Internal.current_load_state(self).load_source(spec) self end |
#load_gem(name, *versions, version: nil, path: nil, toys_dir: nil, context_directory: nil, as: nil) ⇒ self
Load tools from a gem, as if its contents were inserted at the current location.
Note that this directive has restrictions within a #subtool_apply block. See the #subtool_apply documentation for details.
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
# File 'lib/toys/dsl/tool.rb', line 517 def load_gem(name, *versions, version: nil, path: nil, toys_dir: nil, context_directory: nil, as: nil) version = versions + Array(version) if as tool(as) do load_gem(name, version: version, path: path, toys_dir: toys_dir, context_directory: context_directory) end return self end spec = SourceSpec.gem(name, version: version, path: path, toys_dir: toys_dir, context_directory: context_directory) DSL::Internal.current_load_state(self).load_source(spec) self end |
#load_git(remote: nil, path: nil, commit: nil, update: false, context_directory: nil, as: nil) ⇒ self
Load tools from a public git repository, as if its contents were inserted at the current location.
Note that this directive has restrictions within a #subtool_apply block. See the #subtool_apply documentation for details.
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/toys/dsl/tool.rb', line 464 def load_git(remote: nil, path: nil, commit: nil, update: false, context_directory: nil, as: nil) if as tool(as) do load_git(remote: remote, path: path, commit: commit, update: update, context_directory: context_directory) end return self end spec = SourceSpec.git(remote, path: path, commit: commit, update: update, context_directory: context_directory) DSL::Internal.current_load_state(self).load_source(spec) self end |
#long_desc(*strs, file: nil, data: nil) ⇒ self
Add to the long description for the current tool. The long description is displayed in the usage documentation for the tool itself. This directive may be given multiple times, and the results are cumulative.
A long description is a series of descriptions, which are generally displayed in a series of lines/paragraphs. Each individual description uses the form described in the #desc documentation, and may be word-wrapped when displayed. To insert a blank line, include an empty string as one of the descriptions.
Example
long_desc "This initial paragraph might get word wrapped.",
"This next paragraph is followed by a blank line.",
"",
["This line will not be wrapped."],
[" This indent is preserved."]
long_desc "This line is appended to the description."
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
# File 'lib/toys/dsl/tool.rb', line 652 def long_desc(*strs, file: nil, data: nil) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? if file source_path = source_info.source_path unless source_path raise ::Toys::ToolDefinitionError, "Cannot set long_desc from a file because the tool is not defined in a file" end file = ::File.join(::File.dirname(source_path), file) elsif data file = source_info.find_data(data, type: :file) end strs += DSL::Internal.load_long_desc_file(file) if file cur_tool.append_long_desc(strs) self end |
#mixin(name, mixin_module = nil, &block) ⇒ self
Create a named mixin module that can be included by name from this tool or its subtools.
A mixin is a module that defines methods that can be called from a tool. It is commonly used to provide "utility" methods, implementing common functionality and allowing tools to share code.
Normally you provide a block and define the mixin's methods in that block. Alternatively, you can create a module separately and pass it directly to this directive.
Example
The following example creates a named mixin and uses it in a tool.
mixin "error-reporter" do
def error
logger.error "An error occurred: #{}"
exit 1
end
end
tool "build" do
include "error-reporter"
def run
puts "Building..."
error "Build failed!"
end
end
149 150 151 152 153 |
# File 'lib/toys/dsl/tool.rb', line 149 def mixin(name, mixin_module = nil, &block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.add_mixin(name, mixin_module, &block) self end |
#on_interrupt(handler = nil, &block) ⇒ self
Specify how to handle interrupts.
You can provide either a block to be called, a Proc to be called, or the name of a method to be called. In each case, the block, Proc, or method can optionally take one argument, the Interrupt exception that was raised.
Note: this is equivalent to on_signal("SIGINT").
Example
tool "foo" do
def run
sleep 10
end
on_interrupt do
puts "I was interrupted."
end
end
1685 1686 1687 1688 1689 1690 |
# File 'lib/toys/dsl/tool.rb', line 1685 def on_interrupt(handler = nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.interrupt_handler = handler || block self end |
#on_signal(signal, handler = nil, &block) ⇒ self
Specify how to handle the given signal.
You can provide either a block to be called, a Proc to be called, or the name of a method to be called. In each case, the block, Proc, or method can optionally take one argument, the SignalException that was raised.
Example
tool "foo" do
def run
sleep 10
end
on_signal("QUIT") do |e|
puts "Signal caught: #{e.signm}."
end
end
1717 1718 1719 1720 1721 1722 |
# File 'lib/toys/dsl/tool.rb', line 1717 def on_signal(signal, handler = nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.set_signal_handler(signal, handler || block) self end |
#on_usage_error(handler = nil, &block) ⇒ self
Specify how to handle usage errors.
You can provide either a block to be called, a Proc to be called, or the name of a method to be called. In each case, the block, Proc, or method can optionally take one argument, the array of usage errors reported.
Example
This tool runs even if a usage error is encountered, by setting the
run method as the usage error handler.
tool "foo" do
def run
puts "Errors: #{usage_errors.join("\n")}"
end
on_usage_error :run
end
1749 1750 1751 1752 1753 1754 |
# File 'lib/toys/dsl/tool.rb', line 1749 def on_usage_error(handler = nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.usage_error_handler = handler || block self end |
#optional_arg(key, default: nil, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self Also known as: optional
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.
If the given key is a symbol representing a valid method name, then a helper method is automatically added to retrieve the value. Otherwise, if the key is a string or does not represent a valid method name, the tool can retrieve the value by calling Context#get.
Attributes of the arg may be passed in as arguments to this method, or set in a block passed to this method. If you provide a block, you can use directives in PositionalArg within the block.
It is legal to declare a required argument after an optional argument, but at parse time, all required arguments are parsed first, followed by optional arguments. Thus, it is generally recommended to declare them in that order to avoid confusion. Within each type, arguments are parsed in the order they are declared.
Example
This tool creates a "link" to a given target. The link location is optional; if it is not given, it is inferred from the target.
tool "ln" do
required_arg :target
optional_arg :location
def run
loc = location || File.basename(target)
puts "linking to #{target} from #{loc}..."
end
end
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 |
# File 'lib/toys/dsl/tool.rb', line 1252 def optional_arg(key, default: nil, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? arg_dsl = DSL::PositionalArg.new(accept, default, complete, display_name, desc, long_desc, add_method) arg_dsl.instance_exec(arg_dsl, &block) if block arg_dsl._add_optional_to(cur_tool, key) DSL::Internal.maybe_add_getter(self, key, arg_dsl._get_add_method) self end |
#remaining_args(key, default: [], accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self Also known as: remaining
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.
If the given key is a symbol representing a valid method name, then a helper method is automatically added to retrieve the value. Otherwise, if the key is a string or does not represent a valid method name, the tool can retrieve the value by calling Context#get.
Attributes of the arg may be passed in as arguments to this method, or set in a block passed to this method. If you provide a block, you can use directives in PositionalArg within the block.
Remaining arguments are parsed only after explicit required and
optional arguments have been parsed and matched. While it is legal for
the remaining_args directive to appear before required_arg or
optional_arg directives, it is generally recommended that it appear
last in order to avoid confusion.
Example
This tool displays a "list" of the given directories. If no directories ar given, lists the current directory.
tool "ln" do
remaining_args :directories
def run
dirs = directories.empty? ? [Dir.pwd] : directories
dirs.each do |dir|
puts "Listing directory #{dir}..."
end
end
end
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 |
# File 'lib/toys/dsl/tool.rb', line 1338 def remaining_args(key, default: [], accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? arg_dsl = DSL::PositionalArg.new(accept, default, complete, display_name, desc, long_desc, add_method) arg_dsl.instance_exec(arg_dsl, &block) if block arg_dsl._set_remaining_on(cur_tool, key) DSL::Internal.maybe_add_getter(self, key, arg_dsl._get_add_method) self end |
#require_exact_flag_match(state = true) ⇒ self
Require that flags must match exactly. That is, flags must appear in their entirety on the command line. (If false, substrings of flags are accepted as long as they are unambiguous.)
Issuing this directive by itself turns on exact match. You may turn it
off by passing false as the parameter.
1463 1464 1465 1466 1467 1468 |
# File 'lib/toys/dsl/tool.rb', line 1463 def require_exact_flag_match(state = true) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.require_exact_flag_match(state) self end |
#required_arg(key, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) ⇒ self Also known as: required
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.
If the given key is a symbol representing a valid method name, then a helper method is automatically added to retrieve the value. Otherwise, if the key is a string or does not represent a valid method name, the tool can retrieve the value by calling Context#get.
Attributes of the arg may be passed in as arguments to this method, or set in a block passed to this method. If you provide a block, you can use directives in PositionalArg within the block.
It is legal to declare a required argument after an optional argument, but at parse time, all required arguments are parsed first, followed by optional arguments. Thus, it is generally recommended to declare them in that order to avoid confusion. Within each type, arguments are parsed in the order they are declared.
Example
This tool "moves" something from a source to destination, and takes two required arguments:
tool "mv" do
required_arg :source
required_arg :dest
def run
puts "moving from #{source} to #{dest}..."
end
end
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 |
# File 'lib/toys/dsl/tool.rb', line 1166 def required_arg(key, accept: nil, complete: nil, display_name: nil, desc: nil, long_desc: nil, add_method: nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? arg_dsl = DSL::PositionalArg.new(accept, nil, complete, display_name, desc, long_desc, add_method) arg_dsl.instance_exec(arg_dsl, &block) if block arg_dsl._add_required_to(cur_tool, key) DSL::Internal.maybe_add_getter(self, key, arg_dsl._get_add_method) self end |
#set(key, value) ⇒ self #set(hash) ⇒ self
Set option values statically without creating helper methods.
Example
tool "hello" do
set :greeting, "Hi there"
def run
puts "#{get(:greeting)}, world!"
end
end
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 |
# File 'lib/toys/dsl/tool.rb', line 1423 def set(key, value = nil) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? if key.is_a?(::Hash) cur_tool.default_data.merge!(key) else cur_tool.default_data[key] = value end self end |
#set_context_directory(dir) ⇒ self
Set a custom context directory for this tool.
1881 1882 1883 1884 1885 1886 |
# File 'lib/toys/dsl/tool.rb', line 1881 def set_context_directory(dir) # rubocop:disable Naming/AccessorMethodName cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.custom_context_directory = dir self end |
#source_info ⇒ Toys::SourceInfo
Return the current source info object.
1815 1816 1817 |
# File 'lib/toys/dsl/tool.rb', line 1815 def source_info DSL::Internal.current_load_state(self).source end |
#static(key, value) ⇒ self #static(hash) ⇒ self
Set option values statically and create helper methods.
A helper method will be defined to retrieve the value based on the same logic governing flag and positional argument directives. That is, if the key is a symbol representing a legal method name that starts with a letter and does not override any public method in the Ruby Object class or collide with any method directly defined in the tool class. Otherwise, the value can be retrieved by calling Context#get.
Example
tool "hello" do
static :greeting, "Hi there"
def run
puts "#{greeting}, world!"
end
end
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 |
# File 'lib/toys/dsl/tool.rb', line 1384 def static(key, value = nil) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? if key.is_a?(::Hash) cur_tool.default_data.merge!(key) key.each_key do |k| DSL::Internal.maybe_add_getter(self, k, nil) end else cur_tool.default_data[key] = value DSL::Internal.maybe_add_getter(self, key, nil) end self end |
#subtool_apply(&block) ⇒ Object
Applies the given block to all subtools, recursively. Effectively, the given block is run at the end of every tool block. This can be used, for example, to provide some shared configuration for all tools.
The block is applied only to subtools defined after the block appears. Subtools defined before the block appears are not affected.
A subtool_apply block cannot create or modify subtools of the subtool
being applied to. (This is because the same block could be expected to
apply to that subtool as well, and the semantics of the resulting
recursion would be messy and ambiguous.) Thus, within the block:
- You cannot use the
tooldirective. - You cannot create a
Toys::Toolsubclass. - You cannot use a nested
subtool_applydirective. - You cannot pass the
as:parameter to anyloador related directive. - You cannot use any
loador related directive that references a directory. (You can, however, load a file directly, as long as it does not use theas:parameter, and the file's contents do not violate any of these rules.)
Example
It is common for tools to use the :exec mixin to invoke external
programs. This example automatically includes the exec mixin in all
subtools, recursively, so you do not have to repeat the include
directive in every tool.
# .toys.rb
subtool_apply do
# Include the mixin only if the tool hasn't already done so
unless include?(:exec)
include :exec, exit_on_nonzero_status: true
end
end
tool "foo" do
def run
# This tool has access to methods defined by the :exec mixin
# because the above block is applied to the tool.
sh "echo hello"
end
end
1935 1936 1937 1938 1939 1940 |
# File 'lib/toys/dsl/tool.rb', line 1935 def subtool_apply(&block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.check_definition_state(is_descending: true) cur_tool.subtool_middleware_stack.add(:apply_config, parent_source: source_info, &block) self end |
#template(name, template_class = nil, &block) ⇒ self
Create a named template that can be expanded by name from this tool or its subtools.
A template is an object that generates DSL directives. You can use it to build "prefabricated" tools, and then instantiate them in your Toys files.
A template is an object that defines an expansion procedure. This
procedure generates the DSL directives implemented by the template. The
template object typically also includes attributes that are used to
configure the expansion.
The simplest way to define a template is to pass a block to the
#template directive. In the block, define an initialize method that
accepts any arguments that may be passed to the template when it is
instantiated and are used to configure the template. Define
attr_readers or other methods to make this configuration accessible
from the object. Then define an on_expand block that implements the
template's expansion. The template object is passed as an object to the
on_expand block.
Alternately, you can create a template class separately and pass it directly. See Template for details on creating a template class.
Example
The following example creates and uses a simple template. The template defines a tool, with a configurable name, that simply prints out a configurable message.
template "hello-generator" do
def initialize(name, )
@name = name
@message =
end
attr_reader :name, :message
do |template|
tool template.name do
to_run do
puts template.
end
end
end
end
"hello-generator", "mytool", "mytool is running!"
211 212 213 214 215 |
# File 'lib/toys/dsl/tool.rb', line 211 def template(name, template_class = nil, &block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.add_template(name, template_class, &block) self end |
#to_run(handler = nil, &block) ⇒ self Also known as: on_run
Specify how to run this tool.
Typically the entrypoint for a tool is a method named run. However,
you can change this by passing a different method name, as a symbol, to
#to_run.
You can also alternatively pass a block to #to_run. You might do this if your method needs access to local variables in the lexical scope. However, it is often more convenient to use #static to set those values in the context.
Examples
# Set a different method name as the entrypoint:
tool "foo" do
to_run :foo
def foo
puts "The foo tool ran!"
end
end
# Use a block to retain access to the enclosing lexical scope from
# the run method:
tool "foo" do
cur_time = Time.now
to_run do
puts "The time at tool definition was #{cur_time}"
end
end
# But the following is approximately equivalent:
tool "foo" do
static :cur_time, Time.now
def run
puts "The time at tool definition was #{cur_time}"
end
end
1651 1652 1653 1654 1655 1656 |
# File 'lib/toys/dsl/tool.rb', line 1651 def to_run(handler = nil, &block) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.run_handler = handler || block self end |
#tool(words, if_defined: :combine, delegate_to: nil, delegate_relative: nil, &block) ⇒ self
Create a subtool. You must provide a block defining the subtool.
Note that this cannot be called from within #subtool_apply or from a middleware config method.
Example
The following example defines a tool and two subtools within it.
tool "build" do
tool "staging" do
def run
puts "Building staging"
end
end
tool "production" do
def run
puts "Building production"
end
end
end
The following example uses delegate_to to define a tool that runs one
of its subtools.
tool "test", delegate_to: ["test", "unit"] do
tool "unit" do
def run
puts "Running unit tests"
end
end
end
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/toys/dsl/tool.rb', line 315 def tool(words, if_defined: :combine, delegate_to: nil, delegate_relative: nil, &block) cur_tool = DSL::Internal.current_tool(self, false) cur_tool.check_definition_state(is_descending: true) state = DSL::Internal.current_load_state(self) if delegate_to || delegate_relative delegate_to2 = state.canonical_relative_tool_name(delegate_relative) if delegate_relative orig_block = block block = proc do self.delegate_to(delegate_to) if delegate_to self.delegate_to(delegate_to2) if delegate_to2 instance_eval(&orig_block) if orig_block end end state.eval_tool_block(block, words, if_defined) self end |
#toys_version!(*requirements) ⇒ self
Asserts that the current Toys version against the given requirements, raising an exception if not.
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 |
# File 'lib/toys/dsl/tool.rb', line 1992 def toys_version!(*requirements) require "rubygems" version = ::Gem::Version.new(Core::VERSION) requirement = ::Gem::Requirement.new(*requirements) unless requirement.satisfied_by?(version) raise Toys::ToolDefinitionError, "Toys version requirements #{requirement} not satisfied by #{version}" end self end |
#toys_version?(*requirements) ⇒ boolean
Determines whether the current Toys version satisfies the given requirements.
1976 1977 1978 1979 1980 1981 |
# File 'lib/toys/dsl/tool.rb', line 1976 def toys_version?(*requirements) require "rubygems" version = ::Gem::Version.new(Core::VERSION) requirement = ::Gem::Requirement.new(*requirements) requirement.satisfied_by?(version) end |
#treat_unknown_flags_as_args(state = true) ⇒ self
Treat unknown flags as positional arguments. That is, if an argument looks like a flag but does not match any flag defined for this tool, it is passed to the tool's positional arguments instead of reporting a usage error.
An argument is redirected in its entirety. Thus, an argument of the
form --foo=bar is treated as a single positional argument, and a
cluster of single-character flags such as -abc is treated as a
single positional argument if any of its characters is unknown. (In
particular, none of the flags in such a cluster are set.)
This directive does not affect ambiguous flags. If an argument matches a prefix of multiple flags, it is still reported as a usage error.
Issuing this directive by itself turns on the behavior. You may turn
it off by passing false as the parameter.
Example
tool "mytool" do
treat_unknown_flags_as_args
flag :verbose, "--verbose"
remaining_args :command
def run
# Invoking `mytool --verbose ls -l` sets verbose to true and
# command to ["ls", "-l"].
end
end
1503 1504 1505 1506 1507 1508 |
# File 'lib/toys/dsl/tool.rb', line 1503 def treat_unknown_flags_as_args(state = true) cur_tool = DSL::Internal.current_tool(self, true) return self if cur_tool.nil? cur_tool.treat_unknown_flags_as_args(state) self end |
#truncate_load_path! ⇒ Object
Remove lower-priority sources from the load path. This prevents lower- priority sources (such as Toys files from parent or global directories) from executing or defining tools.
This works only if no such sources have already loaded yet.
1952 1953 1954 |
# File 'lib/toys/dsl/tool.rb', line 1952 def truncate_load_path! DSL::Internal.current_load_state(self).stop_loading_at_current_priority end |