toys-core 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/toys-core.rb +20 -5
- data/lib/toys/cli.rb +39 -32
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/{tool → definition}/acceptor.rb +21 -15
- data/lib/toys/{utils/line_output.rb → definition/alias.rb} +47 -59
- data/lib/toys/{tool/arg_definition.rb → definition/arg.rb} +17 -7
- data/lib/toys/{tool/flag_definition.rb → definition/flag.rb} +19 -9
- data/lib/toys/definition/tool.rb +574 -0
- data/lib/toys/dsl/arg.rb +118 -0
- data/lib/toys/dsl/flag.rb +132 -0
- data/lib/toys/dsl/tool.rb +521 -0
- data/lib/toys/errors.rb +2 -2
- data/lib/toys/helpers.rb +3 -3
- data/lib/toys/helpers/exec.rb +31 -25
- data/lib/toys/helpers/fileutils.rb +8 -2
- data/lib/toys/helpers/highline.rb +8 -1
- data/lib/toys/{alias.rb → helpers/terminal.rb} +44 -53
- data/lib/toys/input_file.rb +61 -0
- data/lib/toys/loader.rb +87 -77
- data/lib/toys/middleware.rb +3 -3
- data/lib/toys/middleware/add_verbosity_flags.rb +22 -20
- data/lib/toys/middleware/base.rb +53 -5
- data/lib/toys/middleware/handle_usage_errors.rb +9 -12
- data/lib/toys/middleware/set_default_descriptions.rb +6 -7
- data/lib/toys/middleware/show_help.rb +71 -67
- data/lib/toys/middleware/show_root_version.rb +9 -9
- data/lib/toys/runner.rb +157 -0
- data/lib/toys/template.rb +4 -3
- data/lib/toys/templates.rb +2 -2
- data/lib/toys/templates/clean.rb +2 -2
- data/lib/toys/templates/gem_build.rb +5 -5
- data/lib/toys/templates/minitest.rb +2 -2
- data/lib/toys/templates/rubocop.rb +2 -2
- data/lib/toys/templates/yardoc.rb +2 -2
- data/lib/toys/tool.rb +168 -625
- data/lib/toys/utils/exec.rb +19 -18
- data/lib/toys/utils/gems.rb +140 -0
- data/lib/toys/utils/help_text.rb +25 -20
- data/lib/toys/utils/terminal.rb +412 -0
- data/lib/toys/utils/wrappable_string.rb +3 -1
- metadata +15 -24
- data/lib/toys/config_dsl.rb +0 -699
- data/lib/toys/context.rb +0 -290
- data/lib/toys/helpers/spinner.rb +0 -142
data/lib/toys/middleware.rb
CHANGED
@@ -50,8 +50,8 @@ module Toys
|
|
50
50
|
# @param [String,Symbol] name Name of the middleware class to return
|
51
51
|
# @return [Class,nil] The class, or `nil` if not found
|
52
52
|
#
|
53
|
-
def lookup(name)
|
54
|
-
Utils::ModuleLookup.lookup(:middleware, name)
|
53
|
+
def lookup!(name)
|
54
|
+
Utils::ModuleLookup.lookup!(:middleware, name)
|
55
55
|
end
|
56
56
|
|
57
57
|
##
|
@@ -69,7 +69,7 @@ module Toys
|
|
69
69
|
cls = input.first
|
70
70
|
args = input[1..-1]
|
71
71
|
if cls.is_a?(::String) || cls.is_a?(::Symbol)
|
72
|
-
cls = lookup(cls)
|
72
|
+
cls = lookup!(cls)
|
73
73
|
end
|
74
74
|
if cls.is_a?(::Class)
|
75
75
|
cls.new(*args)
|
@@ -36,7 +36,7 @@ module Toys
|
|
36
36
|
#
|
37
37
|
# This middleware adds `-v`, `--verbose`, `-q`, and `--quiet` flags, if
|
38
38
|
# not already defined by the tool. These flags affect the setting of
|
39
|
-
# {Toys::
|
39
|
+
# {Toys::Tool::Keys::VERBOSITY}, and, thus, the logger level.
|
40
40
|
#
|
41
41
|
class AddVerbosityFlags < Base
|
42
42
|
##
|
@@ -75,37 +75,39 @@ module Toys
|
|
75
75
|
##
|
76
76
|
# Configure the tool flags.
|
77
77
|
#
|
78
|
-
def config(
|
79
|
-
add_verbose_flags(
|
80
|
-
add_quiet_flags(
|
78
|
+
def config(tool_definition, _loader)
|
79
|
+
add_verbose_flags(tool_definition)
|
80
|
+
add_quiet_flags(tool_definition)
|
81
81
|
yield
|
82
82
|
end
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
-
def add_verbose_flags(
|
87
|
-
verbose_flags = Middleware.resolve_flags_spec(@verbose_flags,
|
86
|
+
def add_verbose_flags(tool_definition)
|
87
|
+
verbose_flags = Middleware.resolve_flags_spec(@verbose_flags, tool_definition,
|
88
88
|
DEFAULT_VERBOSE_FLAGS)
|
89
89
|
unless verbose_flags.empty?
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
tool_definition.add_flag(
|
91
|
+
Tool::Keys::VERBOSITY, verbose_flags,
|
92
|
+
report_collisions: false,
|
93
|
+
handler: ->(_val, cur) { cur + 1 },
|
94
|
+
desc: "Increase verbosity",
|
95
|
+
long_desc: "Increase verbosity, causing additional logging levels to display."
|
96
|
+
)
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
99
|
-
def add_quiet_flags(
|
100
|
-
quiet_flags = Middleware.resolve_flags_spec(@quiet_flags,
|
100
|
+
def add_quiet_flags(tool_definition)
|
101
|
+
quiet_flags = Middleware.resolve_flags_spec(@quiet_flags, tool_definition,
|
101
102
|
DEFAULT_QUIET_FLAGS)
|
102
103
|
unless quiet_flags.empty?
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
tool_definition.add_flag(
|
105
|
+
Tool::Keys::VERBOSITY, quiet_flags,
|
106
|
+
report_collisions: false,
|
107
|
+
handler: ->(_val, cur) { cur - 1 },
|
108
|
+
desc: "Decrease verbosity",
|
109
|
+
long_desc: "Decrease verbosity, causing fewer logging levels to display."
|
110
|
+
)
|
109
111
|
end
|
110
112
|
end
|
111
113
|
end
|
data/lib/toys/middleware/base.rb
CHANGED
@@ -30,20 +30,68 @@
|
|
30
30
|
module Toys
|
31
31
|
module Middleware
|
32
32
|
##
|
33
|
-
#
|
33
|
+
# This is a base middleware with a no-op implementation.
|
34
|
+
#
|
35
|
+
# A middleware is an object that has the opportunity to alter the
|
36
|
+
# configuration and runtime behavior of each tool in a Toys CLI. A CLI
|
37
|
+
# contains an ordered list of middleware, known as the *middleware stack*,
|
38
|
+
# that together define the CLI's default behavior.
|
39
|
+
#
|
40
|
+
# Specifically, a middleware can perform two functions.
|
41
|
+
#
|
42
|
+
# First, it can modify the configuration of a tool. After tools are defined
|
43
|
+
# from configuration, the middleware stack can make modifications to each
|
44
|
+
# tool. A middleware can add flags and arguments to the tool, modify the
|
45
|
+
# description, or make any other changes to how the tool is set up.
|
46
|
+
#
|
47
|
+
# Second, a middleware can intercept and change tool execution. Like a Rack
|
48
|
+
# middleware, a Toys middleware can wrap execution with its own code,
|
49
|
+
# replace it outright, or leave it unmodified.
|
34
50
|
#
|
35
51
|
class Base
|
36
52
|
##
|
37
|
-
#
|
53
|
+
# This method is called after a tool has been defined, and gives this
|
54
|
+
# middleware the opportunity to modify the tool definition. It is passed
|
55
|
+
# the tool definition object and the loader, and can make any changes to
|
56
|
+
# the tool definition. In most cases, this method should also call
|
57
|
+
# `yield`, which passes control to the next middleware in the stack. A
|
58
|
+
# middleware can disable modifications done by subsequent middleware by
|
59
|
+
# omitting the `yield` call, but this is uncommon.
|
60
|
+
#
|
61
|
+
# The base middleware implementation does nothing and simply yields to
|
62
|
+
# the next middleware. Subclasses should override this if they want to
|
63
|
+
# alter the tool definition.
|
38
64
|
#
|
39
|
-
|
65
|
+
# @param [Toys::Definition::Tool] _tool_definition The tool definition
|
66
|
+
# to modify.
|
67
|
+
# @param [Toys::Loader] _loader The loader that loaded this tool.
|
68
|
+
#
|
69
|
+
def config(_tool_definition, _loader)
|
40
70
|
yield
|
41
71
|
end
|
42
72
|
|
43
73
|
##
|
44
|
-
#
|
74
|
+
# This method is called when the tool is run. It gives the middleware an
|
75
|
+
# opportunity to modify the runtime behavior of the tool. It is passed
|
76
|
+
# the tool instance (i.e. the object that hosts a tool's `run` method),
|
77
|
+
# and you can use this object to access the tool's options and other
|
78
|
+
# context data. In most cases, this method should also call `yield`,
|
79
|
+
# which passes control to the next middleware in the stack. A middleware
|
80
|
+
# can "wrap" normal execution by calling `yield` somewhere in its
|
81
|
+
# implementation of this method, or it can completely replace the
|
82
|
+
# execution behavior by not calling `yield` at all.
|
83
|
+
#
|
84
|
+
# Like a tool's `run` method, this method's return value is unused. If
|
85
|
+
# you want to output from a tool, write to stdout or stderr. If you want
|
86
|
+
# to set the exit status code, call {Toys::Tool#exit} on the tool object.
|
87
|
+
#
|
88
|
+
# The base middleware implementation does nothing and simply yields to
|
89
|
+
# the next middleware. Subclasses should override this if they want to
|
90
|
+
# alter the tool execution.
|
91
|
+
#
|
92
|
+
# @param [Toys::Tool] _tool The tool execution instance.
|
45
93
|
#
|
46
|
-
def
|
94
|
+
def run(_tool)
|
47
95
|
yield
|
48
96
|
end
|
49
97
|
end
|
@@ -27,11 +27,9 @@
|
|
27
27
|
# POSSIBILITY OF SUCH DAMAGE.
|
28
28
|
;
|
29
29
|
|
30
|
-
require "highline"
|
31
|
-
|
32
30
|
require "toys/middleware/base"
|
33
31
|
require "toys/utils/help_text"
|
34
|
-
require "toys/utils/
|
32
|
+
require "toys/utils/terminal"
|
35
33
|
|
36
34
|
module Toys
|
37
35
|
module Middleware
|
@@ -54,20 +52,19 @@ module Toys
|
|
54
52
|
#
|
55
53
|
def initialize(exit_code: -1, stream: $stderr, styled_output: nil)
|
56
54
|
@exit_code = exit_code
|
57
|
-
@
|
55
|
+
@terminal = Utils::Terminal.new(output: stream, styled: styled_output)
|
58
56
|
end
|
59
57
|
|
60
58
|
##
|
61
59
|
# Intercept and handle usage errors during execution.
|
62
60
|
#
|
63
|
-
def
|
64
|
-
if
|
65
|
-
|
66
|
-
|
67
|
-
@
|
68
|
-
@
|
69
|
-
|
70
|
-
context.exit(@exit_code)
|
61
|
+
def run(tool)
|
62
|
+
if tool[Tool::Keys::USAGE_ERROR]
|
63
|
+
help_text = Utils::HelpText.from_tool(tool)
|
64
|
+
@terminal.puts(tool[Tool::Keys::USAGE_ERROR], :bright_red, :bold)
|
65
|
+
@terminal.puts("")
|
66
|
+
@terminal.puts(help_text.usage_string(wrap_width: @terminal.width))
|
67
|
+
tool.exit(@exit_code)
|
71
68
|
else
|
72
69
|
yield
|
73
70
|
end
|
@@ -86,16 +86,15 @@ module Toys
|
|
86
86
|
# Create a SetDefaultDescriptions middleware given default descriptions.
|
87
87
|
#
|
88
88
|
# @param [String,nil] default_tool_desc The default short description for
|
89
|
-
# tools
|
89
|
+
# runnable tools, or `nil` not to set one. Defaults to
|
90
90
|
# {DEFAULT_TOOL_DESC}.
|
91
91
|
# @param [String,nil] default_tool_long_desc The default long description
|
92
|
-
# for tools
|
93
|
-
# `nil`.
|
92
|
+
# for runnable tools, or `nil` not to set one. Defaults to `nil`.
|
94
93
|
# @param [String,nil] default_namespace_desc The default short
|
95
|
-
# description for tools
|
94
|
+
# description for non-runnable tools, or `nil` not to set one.
|
96
95
|
# Defaults to {DEFAULT_TOOL_DESC}.
|
97
96
|
# @param [String,nil] default_namespace_long_desc The default long
|
98
|
-
# description for tools
|
97
|
+
# description for non-runnable tools, or `nil` not to set one.
|
99
98
|
# Defaults to `nil`.
|
100
99
|
# @param [String,nil] default_root_desc The default short description for
|
101
100
|
# the root tool, or `nil` not to set one. Defaults to
|
@@ -151,7 +150,7 @@ module Toys
|
|
151
150
|
def generate_tool_desc(tool, data)
|
152
151
|
if tool.root?
|
153
152
|
@default_root_desc
|
154
|
-
elsif !tool.
|
153
|
+
elsif !tool.runnable? && data[:loader].has_subtools?(tool.full_name)
|
155
154
|
@default_namespace_desc
|
156
155
|
else
|
157
156
|
@default_tool_desc
|
@@ -174,7 +173,7 @@ module Toys
|
|
174
173
|
def generate_tool_long_desc(tool, data)
|
175
174
|
if tool.root?
|
176
175
|
@default_root_long_desc
|
177
|
-
elsif !tool.
|
176
|
+
elsif !tool.runnable? && data[:loader].has_subtools?(tool.full_name)
|
178
177
|
@default_namespace_long_desc
|
179
178
|
else
|
180
179
|
@default_tool_long_desc
|
@@ -27,21 +27,19 @@
|
|
27
27
|
# POSSIBILITY OF SUCH DAMAGE.
|
28
28
|
;
|
29
29
|
|
30
|
-
require "highline"
|
31
|
-
|
32
30
|
require "toys/middleware/base"
|
33
31
|
require "toys/utils/exec"
|
34
32
|
require "toys/utils/help_text"
|
35
|
-
require "toys/utils/
|
33
|
+
require "toys/utils/terminal"
|
36
34
|
|
37
35
|
module Toys
|
38
36
|
module Middleware
|
39
37
|
##
|
40
38
|
# A middleware that shows help text for the tool when a flag (typically
|
41
39
|
# `--help`) is provided. It can also be configured to show help by
|
42
|
-
# default if the tool is a namespace
|
40
|
+
# default if the tool is a namespace that is not runnable.
|
43
41
|
#
|
44
|
-
# If a tool
|
42
|
+
# If a tool is not runnable, this middleware can also add a
|
45
43
|
# `--[no-]recursive` flag, which, when set to `true` (the default), shows
|
46
44
|
# all subtools recursively rather than only immediate subtools. This
|
47
45
|
# middleware can also search for keywords in its subtools.
|
@@ -103,9 +101,9 @@ module Toys
|
|
103
101
|
# @param [Boolean] default_recursive Whether to search recursively for
|
104
102
|
# subtools by default. Default is `false`.
|
105
103
|
# @param [Boolean] fallback_execution Cause the tool to display its own
|
106
|
-
# help text if it
|
107
|
-
#
|
108
|
-
#
|
104
|
+
# help text if it is not otherwise runnable. This is mostly useful
|
105
|
+
# for namespaces, which have children are not runnable. Default is
|
106
|
+
# `false`.
|
109
107
|
# @param [Boolean] allow_root_args If the root tool includes flags for
|
110
108
|
# help or usage, and doesn't otherwise use positional arguments,
|
111
109
|
# then a tool name can be passed as arguments to display help for
|
@@ -146,18 +144,20 @@ module Toys
|
|
146
144
|
##
|
147
145
|
# Configure flags and default data.
|
148
146
|
#
|
149
|
-
def config(
|
150
|
-
help_flags = add_help_flags(
|
151
|
-
usage_flags = add_usage_flags(
|
147
|
+
def config(tool_definition, loader)
|
148
|
+
help_flags = add_help_flags(tool_definition)
|
149
|
+
usage_flags = add_usage_flags(tool_definition)
|
152
150
|
if @allow_root_args && (!help_flags.empty? || !usage_flags.empty?)
|
153
|
-
if
|
154
|
-
|
155
|
-
|
151
|
+
if tool_definition.root? && tool_definition.arg_definitions.empty?
|
152
|
+
tool_definition.set_remaining_args(:_tool_name,
|
153
|
+
display_name: "TOOL_NAME",
|
154
|
+
desc: "The tool for which to display help")
|
156
155
|
end
|
157
156
|
end
|
158
|
-
if (!help_flags.empty? || @fallback_execution) &&
|
159
|
-
|
160
|
-
|
157
|
+
if (!help_flags.empty? || @fallback_execution) &&
|
158
|
+
loader.has_subtools?(tool_definition.full_name)
|
159
|
+
add_recursive_flags(tool_definition)
|
160
|
+
add_search_flags(tool_definition)
|
161
161
|
end
|
162
162
|
yield
|
163
163
|
end
|
@@ -165,18 +165,18 @@ module Toys
|
|
165
165
|
##
|
166
166
|
# Display help text if requested.
|
167
167
|
#
|
168
|
-
def
|
169
|
-
if
|
170
|
-
help_text = get_help_text(
|
171
|
-
str = help_text.usage_string(wrap_width:
|
172
|
-
|
173
|
-
elsif @fallback_execution && !
|
174
|
-
|
175
|
-
help_text = get_help_text(
|
176
|
-
str = help_text.help_string(recursive:
|
177
|
-
search:
|
168
|
+
def run(tool)
|
169
|
+
if tool[:_show_usage]
|
170
|
+
help_text = get_help_text(tool)
|
171
|
+
str = help_text.usage_string(wrap_width: terminal.width)
|
172
|
+
terminal.puts(str)
|
173
|
+
elsif @fallback_execution && !tool[Tool::Keys::TOOL_DEFINITION].runnable? ||
|
174
|
+
tool[:_show_help]
|
175
|
+
help_text = get_help_text(tool)
|
176
|
+
str = help_text.help_string(recursive: tool[:_recursive_subtools],
|
177
|
+
search: tool[:_search_subtools],
|
178
178
|
show_source_path: @show_source_path,
|
179
|
-
wrap_width:
|
179
|
+
wrap_width: terminal.width)
|
180
180
|
output_help(str)
|
181
181
|
else
|
182
182
|
yield
|
@@ -185,19 +185,15 @@ module Toys
|
|
185
185
|
|
186
186
|
private
|
187
187
|
|
188
|
-
def
|
189
|
-
@
|
190
|
-
end
|
191
|
-
|
192
|
-
def output
|
193
|
-
@output ||= Utils::LineOutput.new(@stream, styled: @styled_output)
|
188
|
+
def terminal
|
189
|
+
@terminal ||= Utils::Terminal.new(output: @stream, styled: @styled_output)
|
194
190
|
end
|
195
191
|
|
196
192
|
def output_help(str)
|
197
193
|
if less_path
|
198
194
|
Utils::Exec.new.exec([less_path, "-R"], in_from: str)
|
199
195
|
else
|
200
|
-
|
196
|
+
terminal.puts(str)
|
201
197
|
end
|
202
198
|
end
|
203
199
|
|
@@ -212,62 +208,70 @@ module Toys
|
|
212
208
|
@less_path
|
213
209
|
end
|
214
210
|
|
215
|
-
def get_help_text(
|
216
|
-
tool_name =
|
217
|
-
return Utils::HelpText.
|
218
|
-
loader =
|
219
|
-
|
220
|
-
help_text = Utils::HelpText.new(
|
221
|
-
report_usage_error(
|
211
|
+
def get_help_text(tool)
|
212
|
+
tool_name = tool[:_tool_name]
|
213
|
+
return Utils::HelpText.from_tool(tool) if tool_name.nil? || tool_name.empty?
|
214
|
+
loader = tool[Tool::Keys::LOADER]
|
215
|
+
tool_definition, rest = loader.lookup(tool_name)
|
216
|
+
help_text = Utils::HelpText.new(tool_definition, loader, tool[Tool::Keys::BINARY_NAME])
|
217
|
+
report_usage_error(tool, tool_name, help_text) unless rest.empty?
|
222
218
|
help_text
|
223
219
|
end
|
224
220
|
|
225
|
-
def report_usage_error(
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
221
|
+
def report_usage_error(tool, tool_name, help_text)
|
222
|
+
terminal.puts("Tool not found: #{tool_name.join(' ')}", :bright_red, :bold)
|
223
|
+
terminal.puts
|
224
|
+
terminal.puts help_text.usage_string(wrap_width: terminal.width)
|
225
|
+
tool.exit(1)
|
230
226
|
end
|
231
227
|
|
232
|
-
def add_help_flags(
|
233
|
-
help_flags = Middleware.resolve_flags_spec(@help_flags,
|
228
|
+
def add_help_flags(tool_definition)
|
229
|
+
help_flags = Middleware.resolve_flags_spec(@help_flags, tool_definition,
|
234
230
|
DEFAULT_HELP_FLAGS)
|
235
231
|
unless help_flags.empty?
|
236
|
-
|
237
|
-
|
232
|
+
tool_definition.add_flag(
|
233
|
+
:_show_help, help_flags,
|
234
|
+
report_collisions: false,
|
235
|
+
desc: "Display help for this tool"
|
236
|
+
)
|
238
237
|
end
|
239
238
|
help_flags
|
240
239
|
end
|
241
240
|
|
242
|
-
def add_usage_flags(
|
243
|
-
usage_flags = Middleware.resolve_flags_spec(@usage_flags,
|
241
|
+
def add_usage_flags(tool_definition)
|
242
|
+
usage_flags = Middleware.resolve_flags_spec(@usage_flags, tool_definition,
|
244
243
|
DEFAULT_USAGE_FLAGS)
|
245
244
|
unless usage_flags.empty?
|
246
|
-
|
247
|
-
|
248
|
-
|
245
|
+
tool_definition.add_flag(
|
246
|
+
:_show_usage, usage_flags,
|
247
|
+
report_collisions: false,
|
248
|
+
desc: "Display a brief usage string for this tool"
|
249
|
+
)
|
249
250
|
end
|
250
251
|
usage_flags
|
251
252
|
end
|
252
253
|
|
253
|
-
def add_recursive_flags(
|
254
|
-
recursive_flags = Middleware.resolve_flags_spec(@recursive_flags,
|
254
|
+
def add_recursive_flags(tool_definition)
|
255
|
+
recursive_flags = Middleware.resolve_flags_spec(@recursive_flags, tool_definition,
|
255
256
|
DEFAULT_RECURSIVE_FLAGS)
|
256
257
|
unless recursive_flags.empty?
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
258
|
+
tool_definition.add_flag(
|
259
|
+
:_recursive_subtools, recursive_flags,
|
260
|
+
report_collisions: false, default: @default_recursive,
|
261
|
+
desc: "Show all subtools recursively (default is #{@default_recursive})"
|
262
|
+
)
|
261
263
|
end
|
262
264
|
end
|
263
265
|
|
264
|
-
def add_search_flags(
|
265
|
-
search_flags = Middleware.resolve_flags_spec(@search_flags,
|
266
|
+
def add_search_flags(tool_definition)
|
267
|
+
search_flags = Middleware.resolve_flags_spec(@search_flags, tool_definition,
|
266
268
|
DEFAULT_SEARCH_FLAGS)
|
267
269
|
unless search_flags.empty?
|
268
|
-
|
269
|
-
|
270
|
-
|
270
|
+
tool_definition.add_flag(
|
271
|
+
:_search_subtools, search_flags,
|
272
|
+
report_collisions: false,
|
273
|
+
desc: "Search subtools for the given regular expression"
|
274
|
+
)
|
271
275
|
end
|
272
276
|
end
|
273
277
|
end
|