toys-core 0.3.7.1 → 0.3.8
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 +10 -0
- data/README.md +1 -2
- data/lib/toys-core.rb +23 -8
- data/lib/toys/cli.rb +62 -23
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/definition/arg.rb +0 -2
- data/lib/toys/definition/flag.rb +2 -4
- data/lib/toys/definition/tool.rb +38 -36
- data/lib/toys/dsl/arg.rb +4 -0
- data/lib/toys/dsl/flag.rb +9 -5
- data/lib/toys/dsl/tool.rb +35 -28
- data/lib/toys/input_file.rb +2 -1
- data/lib/toys/loader.rb +97 -51
- data/lib/toys/middleware.rb +61 -87
- data/lib/toys/runner.rb +19 -2
- data/lib/toys/{middleware → standard_middleware}/add_verbosity_flags.rb +24 -8
- data/lib/toys/{middleware → standard_middleware}/handle_usage_errors.rb +4 -6
- data/lib/toys/{middleware → standard_middleware}/set_default_descriptions.rb +4 -4
- data/lib/toys/{middleware → standard_middleware}/show_help.rb +32 -16
- data/lib/toys/{middleware → standard_middleware}/show_root_version.rb +4 -5
- data/lib/toys/{helpers → standard_mixins}/exec.rb +8 -8
- data/lib/toys/{helpers → standard_mixins}/fileutils.rb +1 -1
- data/lib/toys/{helpers → standard_mixins}/highline.rb +2 -3
- data/lib/toys/{helpers → standard_mixins}/terminal.rb +2 -4
- data/lib/toys/tool.rb +3 -2
- data/lib/toys/utils/exec.rb +255 -82
- data/lib/toys/utils/gems.rb +3 -3
- data/lib/toys/utils/help_text.rb +0 -2
- data/lib/toys/utils/module_lookup.rb +60 -40
- data/lib/toys/utils/wrappable_string.rb +0 -2
- metadata +11 -19
- data/lib/toys/helpers.rb +0 -54
- data/lib/toys/middleware/base.rb +0 -99
- data/lib/toys/templates.rb +0 -55
- data/lib/toys/templates/clean.rb +0 -85
- data/lib/toys/templates/gem_build.rb +0 -125
- data/lib/toys/templates/minitest.rb +0 -125
- data/lib/toys/templates/rubocop.rb +0 -86
- data/lib/toys/templates/yardoc.rb +0 -101
data/lib/toys/dsl/flag.rb
CHANGED
@@ -33,6 +33,9 @@ module Toys
|
|
33
33
|
# DSL for a flag definition block. Lets you set flag attributes in a block
|
34
34
|
# instead of a long series of keyword arguments.
|
35
35
|
#
|
36
|
+
# These directives are available inside a block passed to
|
37
|
+
# {Toys::DSL::Tool#flag}.
|
38
|
+
#
|
36
39
|
class Flag
|
37
40
|
## @private
|
38
41
|
def initialize(flags, accept, default, handler, report_collisions, desc, long_desc)
|
@@ -75,14 +78,15 @@ module Toys
|
|
75
78
|
|
76
79
|
##
|
77
80
|
# Set the optional handler for setting/updating the value when a flag is
|
78
|
-
# parsed.
|
79
|
-
# and the previous value, and it should return the new value that
|
80
|
-
# be set.
|
81
|
+
# parsed. A handler should be a Proc taking two arguments, the new given
|
82
|
+
# value and the previous value, and it should return the new value that
|
83
|
+
# should be set. You may pass the handler as a Proc (or an object
|
84
|
+
# responding to the `call` method) or you may pass a block.
|
81
85
|
#
|
82
86
|
# @param [Proc] handler
|
83
87
|
#
|
84
|
-
def handler(handler)
|
85
|
-
@handler = handler
|
88
|
+
def handler(handler = nil, &block)
|
89
|
+
@handler = handler || block
|
86
90
|
self
|
87
91
|
end
|
88
92
|
|
data/lib/toys/dsl/tool.rb
CHANGED
@@ -30,16 +30,13 @@
|
|
30
30
|
module Toys
|
31
31
|
module DSL
|
32
32
|
##
|
33
|
-
# This class defines the DSL for a
|
33
|
+
# This class defines the DSL for a Toys configuration file.
|
34
34
|
#
|
35
|
-
# A
|
35
|
+
# A Toys configuration defines one or more named tools. It provides syntax
|
36
36
|
# for setting the description, defining flags and arguments, specifying
|
37
|
-
# how to execute the tool, and requesting
|
37
|
+
# how to execute the tool, and requesting mixin modules and other services.
|
38
38
|
# It also lets you define subtools, nested arbitrarily deep, using blocks.
|
39
39
|
#
|
40
|
-
# Generally the DSL is invoked from the {Loader}. Applications should not
|
41
|
-
# need to create instances of DSL::Tool directly.
|
42
|
-
#
|
43
40
|
# ## Simple example
|
44
41
|
#
|
45
42
|
# Create a file called `.toys.rb` in the current directory, with the
|
@@ -50,8 +47,8 @@ module Toys
|
|
50
47
|
#
|
51
48
|
# optional_arg :recipient, default: "world"
|
52
49
|
#
|
53
|
-
#
|
54
|
-
# puts "Hello, #{
|
50
|
+
# def run
|
51
|
+
# puts "Hello, #{option(:recipient)}!"
|
55
52
|
# end
|
56
53
|
# end
|
57
54
|
#
|
@@ -129,16 +126,16 @@ module Toys
|
|
129
126
|
end
|
130
127
|
|
131
128
|
##
|
132
|
-
# Create a named
|
129
|
+
# Create a named mixin module.
|
133
130
|
# This module may be included by name in this tool or any subtool.
|
134
131
|
#
|
135
132
|
# You should pass a block and define methods in that block.
|
136
133
|
#
|
137
|
-
# @param [String] name Name of the
|
134
|
+
# @param [String] name Name of the mixin
|
138
135
|
#
|
139
|
-
def
|
136
|
+
def mixin(name, &block)
|
140
137
|
cur_tool = DSL::Tool.activate_tool(self)
|
141
|
-
cur_tool.
|
138
|
+
cur_tool.add_mixin(name, ::Module.new(&block)) if cur_tool
|
142
139
|
self
|
143
140
|
end
|
144
141
|
|
@@ -209,7 +206,10 @@ module Toys
|
|
209
206
|
def expand(template_class, *args)
|
210
207
|
unless template_class.is_a?(::Class)
|
211
208
|
name = template_class.to_s
|
212
|
-
template_class =
|
209
|
+
template_class = @__loader.resolve_standard_template(name)
|
210
|
+
if template_class.nil?
|
211
|
+
raise ToolDefinitionError, "Template name not found: #{name.inspect}"
|
212
|
+
end
|
213
213
|
end
|
214
214
|
template = template_class.new(*args)
|
215
215
|
yield template if block_given?
|
@@ -281,7 +281,7 @@ module Toys
|
|
281
281
|
##
|
282
282
|
# Add a flag to the current tool. Each flag must specify a key which
|
283
283
|
# the script may use to obtain the flag value from the context.
|
284
|
-
# You may then provide the flags themselves in
|
284
|
+
# You may then provide the flags themselves in OptionParser form.
|
285
285
|
#
|
286
286
|
# Attributes of the flag may be passed in as arguments to this method, or
|
287
287
|
# set in a block passed to this method.
|
@@ -318,12 +318,13 @@ module Toys
|
|
318
318
|
def flag(key, *flags,
|
319
319
|
accept: nil, default: nil, handler: nil,
|
320
320
|
report_collisions: true,
|
321
|
-
desc: nil, long_desc: nil
|
321
|
+
desc: nil, long_desc: nil,
|
322
|
+
&block)
|
322
323
|
cur_tool = DSL::Tool.activate_tool(self)
|
323
324
|
return self if cur_tool.nil?
|
324
325
|
flag_dsl = DSL::Flag.new(flags, accept, default, handler, report_collisions,
|
325
326
|
desc, long_desc)
|
326
|
-
|
327
|
+
flag_dsl.instance_exec(flag_dsl, &block) if block
|
327
328
|
flag_dsl._add_to(cur_tool, key)
|
328
329
|
self
|
329
330
|
end
|
@@ -352,11 +353,13 @@ module Toys
|
|
352
353
|
# @yieldparam arg_dsl [Toys::DSL::Arg] An object that lets you configure
|
353
354
|
# this argument in a block.
|
354
355
|
#
|
355
|
-
def required_arg(key,
|
356
|
+
def required_arg(key,
|
357
|
+
accept: nil, display_name: nil, desc: nil, long_desc: nil,
|
358
|
+
&block)
|
356
359
|
cur_tool = DSL::Tool.activate_tool(self)
|
357
360
|
return self if cur_tool.nil?
|
358
361
|
arg_dsl = DSL::Arg.new(accept, nil, display_name, desc, long_desc)
|
359
|
-
|
362
|
+
arg_dsl.instance_exec(arg_dsl, &block) if block
|
360
363
|
arg_dsl._add_required_to(cur_tool, key)
|
361
364
|
self
|
362
365
|
end
|
@@ -390,12 +393,14 @@ module Toys
|
|
390
393
|
# @yieldparam arg_dsl [Toys::DSL::Arg] An object that lets you configure
|
391
394
|
# this argument in a block.
|
392
395
|
#
|
393
|
-
def optional_arg(key,
|
394
|
-
|
396
|
+
def optional_arg(key,
|
397
|
+
default: nil, accept: nil, display_name: nil,
|
398
|
+
desc: nil, long_desc: nil,
|
399
|
+
&block)
|
395
400
|
cur_tool = DSL::Tool.activate_tool(self)
|
396
401
|
return self if cur_tool.nil?
|
397
402
|
arg_dsl = DSL::Arg.new(accept, default, display_name, desc, long_desc)
|
398
|
-
|
403
|
+
arg_dsl.instance_exec(arg_dsl, &block) if block
|
399
404
|
arg_dsl._add_optional_to(cur_tool, key)
|
400
405
|
self
|
401
406
|
end
|
@@ -428,12 +433,14 @@ module Toys
|
|
428
433
|
# @yieldparam arg_dsl [Toys::DSL::Arg] An object that lets you configure
|
429
434
|
# this argument in a block.
|
430
435
|
#
|
431
|
-
def remaining_args(key,
|
432
|
-
|
436
|
+
def remaining_args(key,
|
437
|
+
default: [], accept: nil, display_name: nil,
|
438
|
+
desc: nil, long_desc: nil,
|
439
|
+
&block)
|
433
440
|
cur_tool = DSL::Tool.activate_tool(self)
|
434
441
|
return self if cur_tool.nil?
|
435
442
|
arg_dsl = DSL::Arg.new(accept, default, display_name, desc, long_desc)
|
436
|
-
|
443
|
+
arg_dsl.instance_exec(arg_dsl, &block) if block
|
437
444
|
arg_dsl._set_remaining_on(cur_tool, key)
|
438
445
|
self
|
439
446
|
end
|
@@ -452,9 +459,9 @@ module Toys
|
|
452
459
|
# Specify that the given module should be mixed into this tool, and its
|
453
460
|
# methods made available when running the tool.
|
454
461
|
#
|
455
|
-
# You may provide either a module, the string name of a
|
462
|
+
# You may provide either a module, the string name of a mixin that you
|
456
463
|
# have defined in this tool or one of its ancestors, or the symbol name
|
457
|
-
# of a well-known
|
464
|
+
# of a well-known mixin.
|
458
465
|
#
|
459
466
|
# @param [Module,Symbol,String] mod Module or module name.
|
460
467
|
#
|
@@ -463,9 +470,9 @@ module Toys
|
|
463
470
|
return if cur_tool.nil?
|
464
471
|
name = mod.to_s
|
465
472
|
if mod.is_a?(::String)
|
466
|
-
mod = cur_tool.
|
473
|
+
mod = cur_tool.resolve_mixin(mod)
|
467
474
|
elsif mod.is_a?(::Symbol)
|
468
|
-
mod =
|
475
|
+
mod = @__loader.resolve_standard_mixin(name)
|
469
476
|
end
|
470
477
|
if mod.nil?
|
471
478
|
raise ToolDefinitionError, "Module not found: #{name.inspect}"
|
data/lib/toys/input_file.rb
CHANGED
@@ -28,7 +28,8 @@
|
|
28
28
|
;
|
29
29
|
|
30
30
|
##
|
31
|
-
#
|
31
|
+
# This module is a namespace for constant scopes. Whenever a configuration file
|
32
|
+
# is parsed, a module is created under this parent for that file's constants.
|
32
33
|
#
|
33
34
|
module Toys::InputFile # rubocop:disable Style/ClassAndModuleChildren
|
34
35
|
## @private
|
data/lib/toys/loader.rb
CHANGED
@@ -59,14 +59,24 @@ module Toys
|
|
59
59
|
# used by the tools defined in that directory.
|
60
60
|
# @param [Array] middleware_stack An array of middleware that will be used
|
61
61
|
# by default for all tools loaded by this loader.
|
62
|
-
#
|
63
|
-
|
62
|
+
# @param [Toys::Utils::ModuleLookup] mixin_lookup A lookup for well-known
|
63
|
+
# mixin modules. Defaults to an empty lookup.
|
64
|
+
# @param [Toys::Utils::ModuleLookup] middleware_lookup A lookup for
|
65
|
+
# well-known middleware classes. Defaults to an empty lookup.
|
66
|
+
# @param [Toys::Utils::ModuleLookup] template_lookup A lookup for
|
67
|
+
# well-known template classes. Defaults to an empty lookup.
|
68
|
+
#
|
69
|
+
def initialize(index_file_name: nil, preload_file_name: nil, middleware_stack: [],
|
70
|
+
mixin_lookup: nil, middleware_lookup: nil, template_lookup: nil)
|
64
71
|
if index_file_name && ::File.extname(index_file_name) != ".rb"
|
65
72
|
raise ::ArgumentError, "Illegal index file name #{index_file_name.inspect}"
|
66
73
|
end
|
67
74
|
if preload_file_name && ::File.extname(preload_file_name) != ".rb"
|
68
75
|
raise ::ArgumentError, "Illegal preload file name #{preload_file_name.inspect}"
|
69
76
|
end
|
77
|
+
@mixin_lookup = mixin_lookup || Utils::ModuleLookup.new
|
78
|
+
@middleware_lookup = middleware_lookup || Utils::ModuleLookup.new
|
79
|
+
@template_lookup = template_lookup || Utils::ModuleLookup.new
|
70
80
|
@index_file_name = index_file_name
|
71
81
|
@preload_file_name = preload_file_name
|
72
82
|
@middleware_stack = middleware_stack
|
@@ -133,7 +143,7 @@ module Toys
|
|
133
143
|
# @param [Array<String>] words The name of the parent tool
|
134
144
|
# @param [Boolean] recursive If true, return all subtools recursively
|
135
145
|
# rather than just the immediate children (the default)
|
136
|
-
# @return [Array<Toys::Definition::Tool,
|
146
|
+
# @return [Array<Toys::Definition::Tool,Toys::Definition::Alias>]
|
137
147
|
#
|
138
148
|
def list_subtools(words, recursive: false)
|
139
149
|
load_for_prefix(words)
|
@@ -168,23 +178,6 @@ module Toys
|
|
168
178
|
false
|
169
179
|
end
|
170
180
|
|
171
|
-
##
|
172
|
-
# Finishes all tool definitions under the given path. This generally means
|
173
|
-
# installing middleware.
|
174
|
-
#
|
175
|
-
# @param [Array<String>] words The path to the tool under which all
|
176
|
-
# definitions should be finished.
|
177
|
-
#
|
178
|
-
def finish_definitions_in_tree(words)
|
179
|
-
load_for_prefix(words)
|
180
|
-
len = words.length
|
181
|
-
@tool_data.each do |n, td|
|
182
|
-
next if n.length < len || n.slice(0, len) != words
|
183
|
-
tool = td.active_definition || td.top_definition
|
184
|
-
tool.finish_definition(self) if tool.is_a?(Definition::Tool)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
181
|
##
|
189
182
|
# Returns a tool specified by the given words, with the given priority.
|
190
183
|
# Does not do any loading. If the tool is not present, creates it.
|
@@ -241,36 +234,8 @@ module Toys
|
|
241
234
|
end
|
242
235
|
|
243
236
|
##
|
244
|
-
#
|
245
|
-
#
|
246
|
-
# @param [Array<String>] words Name of the tool
|
247
|
-
# @param [Array<Array<String>>] looked_up List of names that have already
|
248
|
-
# been traversed during alias resolution. Used to detect circular
|
249
|
-
# alias references.
|
250
|
-
# @return [Toys::Definition::Tool,nil] The tool, or `nil` if not found
|
251
|
-
#
|
252
|
-
# @private
|
253
|
-
#
|
254
|
-
def get_active_tool(words, looked_up = [])
|
255
|
-
tool_data = get_tool_data(words)
|
256
|
-
result = tool_data.active_definition
|
257
|
-
case result
|
258
|
-
when Definition::Alias
|
259
|
-
words = result.target_name
|
260
|
-
if looked_up.include?(words)
|
261
|
-
raise ToolDefinitionError, "Circular alias references: #{looked_up.inspect}"
|
262
|
-
end
|
263
|
-
looked_up << words
|
264
|
-
get_active_tool(words, looked_up)
|
265
|
-
when Definition::Tool
|
266
|
-
result
|
267
|
-
else
|
268
|
-
tool_data.top_definition
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
##
|
273
|
-
# Get the tool definition for the given name and priority.
|
237
|
+
# Get or create the tool definition for the given name and priority.
|
238
|
+
# May return either a tool or alias definition.
|
274
239
|
#
|
275
240
|
# @private
|
276
241
|
#
|
@@ -284,8 +249,29 @@ module Toys
|
|
284
249
|
if tool_data.top_priority.nil? || tool_data.top_priority < priority
|
285
250
|
tool_data.top_priority = priority
|
286
251
|
end
|
252
|
+
middlewares = @middleware_stack.map { |m| resolve_middleware(m) }
|
287
253
|
tool_data.definitions[priority] ||=
|
288
|
-
Definition::Tool.new(self, parent, words, priority,
|
254
|
+
Definition::Tool.new(self, parent, words, priority, middlewares)
|
255
|
+
end
|
256
|
+
|
257
|
+
##
|
258
|
+
# Attempt to get a well-known mixin module for the given symbolic name.
|
259
|
+
#
|
260
|
+
# @param [Symbol] name Mixin name
|
261
|
+
# @return [Module,nil] The mixin, or `nil` if not found.
|
262
|
+
#
|
263
|
+
def resolve_standard_mixin(name)
|
264
|
+
@mixin_lookup.lookup(name)
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# Attempt to get a well-known template class for the given symbolic name.
|
269
|
+
#
|
270
|
+
# @param [Symbol] name Template name
|
271
|
+
# @return [Class,nil] The template, or `nil` if not found.
|
272
|
+
#
|
273
|
+
def resolve_standard_template(name)
|
274
|
+
@template_lookup.lookup(name)
|
289
275
|
end
|
290
276
|
|
291
277
|
##
|
@@ -318,6 +304,66 @@ module Toys
|
|
318
304
|
@tool_data[words] ||= ToolData.new({}, nil, nil)
|
319
305
|
end
|
320
306
|
|
307
|
+
##
|
308
|
+
# Returns the current effective tool given a name. Resolves any aliases.
|
309
|
+
#
|
310
|
+
# If there is an active tool, returns it; otherwise, returns the highest
|
311
|
+
# priority tool that has been defined. If no tool has been defined with
|
312
|
+
# the given name, returns `nil`.
|
313
|
+
#
|
314
|
+
# @private
|
315
|
+
#
|
316
|
+
def get_active_tool(words, looked_up = [])
|
317
|
+
tool_data = get_tool_data(words)
|
318
|
+
result = tool_data.active_definition
|
319
|
+
case result
|
320
|
+
when Definition::Alias
|
321
|
+
words = result.target_name
|
322
|
+
if looked_up.include?(words)
|
323
|
+
raise ToolDefinitionError, "Circular alias references: #{looked_up.inspect}"
|
324
|
+
end
|
325
|
+
looked_up << words
|
326
|
+
get_active_tool(words, looked_up)
|
327
|
+
when Definition::Tool
|
328
|
+
result
|
329
|
+
else
|
330
|
+
tool_data.top_definition
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def resolve_middleware(input)
|
335
|
+
input = Array(input)
|
336
|
+
cls = input.first
|
337
|
+
args = input[1..-1]
|
338
|
+
if cls.is_a?(::String) || cls.is_a?(::Symbol)
|
339
|
+
cls = @middleware_lookup.lookup(cls)
|
340
|
+
if cls.nil?
|
341
|
+
raise ::ArgumentError, "Unrecognized middleware name #{input.first.inspect}"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
if cls.is_a?(::Class)
|
345
|
+
cls.new(*args)
|
346
|
+
elsif !args.empty?
|
347
|
+
raise ::ArgumentError, "Unrecognized middleware object of class #{cls.class}"
|
348
|
+
else
|
349
|
+
cls
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Finishes all tool definitions under the given path. This generally means
|
355
|
+
# installing middleware.
|
356
|
+
#
|
357
|
+
def finish_definitions_in_tree(words)
|
358
|
+
load_for_prefix(words)
|
359
|
+
len = words.length
|
360
|
+
@tool_data.each do |n, td|
|
361
|
+
next if n.length < len || n.slice(0, len) != words
|
362
|
+
tool = td.active_definition || td.top_definition
|
363
|
+
tool.finish_definition(self) if tool.is_a?(Definition::Tool)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
321
367
|
def load_for_prefix(prefix)
|
322
368
|
cur_worklist = @load_worklist
|
323
369
|
@load_worklist = []
|
data/lib/toys/middleware.rb
CHANGED
@@ -27,98 +27,72 @@
|
|
27
27
|
# POSSIBILITY OF SUCH DAMAGE.
|
28
28
|
;
|
29
29
|
|
30
|
-
require "toys/utils/module_lookup"
|
31
|
-
|
32
30
|
module Toys
|
33
31
|
##
|
34
|
-
#
|
32
|
+
# A middleware is an object that has the opportunity to alter the
|
33
|
+
# configuration and runtime behavior of each tool in a Toys CLI. A CLI
|
34
|
+
# contains an ordered list of middleware, known as the *middleware stack*,
|
35
|
+
# that together define the CLI's default behavior.
|
36
|
+
#
|
37
|
+
# Specifically, a middleware can perform two functions.
|
38
|
+
#
|
39
|
+
# First, it can modify the configuration of a tool. After tools are defined
|
40
|
+
# from configuration, the middleware stack can make modifications to each
|
41
|
+
# tool. A middleware can add flags and arguments to the tool, modify the
|
42
|
+
# description, or make any other changes to how the tool is set up.
|
43
|
+
#
|
44
|
+
# Second, a middleware can intercept and change tool execution. Like a Rack
|
45
|
+
# middleware, a Toys middleware can wrap execution with its own code,
|
46
|
+
# replace it outright, or leave it unmodified.
|
47
|
+
#
|
48
|
+
# Generally, a middleware is a class that implements the two methods defined
|
49
|
+
# in this module: {Toys::Middleware#config} and {Toys::Middleware#run}. A
|
50
|
+
# middleware can include this module to get default implementations that do
|
51
|
+
# nothing, but this is not required.
|
35
52
|
#
|
36
53
|
module Middleware
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
##
|
58
|
-
# Resolves a single middleware. You may pass an instance already
|
59
|
-
# constructed, a middleware class, the name of a well-known middleware
|
60
|
-
# class, or an array where the first element is the lookup name or class,
|
61
|
-
# and subsequent elements are arguments to be passed to the constructor.
|
62
|
-
#
|
63
|
-
# @param [String,Symbol,Array,Object] input The middleware spec
|
64
|
-
# @return [Object] Constructed middleware
|
65
|
-
#
|
66
|
-
def resolve(input)
|
67
|
-
input = Array(input)
|
68
|
-
raise "No middleware found" if input.empty?
|
69
|
-
cls = input.first
|
70
|
-
args = input[1..-1]
|
71
|
-
if cls.is_a?(::String) || cls.is_a?(::Symbol)
|
72
|
-
cls = lookup!(cls)
|
73
|
-
end
|
74
|
-
if cls.is_a?(::Class)
|
75
|
-
cls.new(*args)
|
76
|
-
else
|
77
|
-
raise "Unrecognized middleware class #{cls.class}" unless args.empty?
|
78
|
-
cls
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# Resolves an array of middleware specs. See {Toys::Middleware.resolve}.
|
84
|
-
#
|
85
|
-
# @param [Array] input An array of middleware specs
|
86
|
-
# @return [Array] An array of constructed middleware
|
87
|
-
#
|
88
|
-
def resolve_stack(input)
|
89
|
-
input.map { |e| resolve(e) }
|
90
|
-
end
|
54
|
+
##
|
55
|
+
# This method is called after a tool has been defined, and gives this
|
56
|
+
# middleware the opportunity to modify the tool definition. It is passed
|
57
|
+
# the tool definition object and the loader, and can make any changes to
|
58
|
+
# the tool definition. In most cases, this method should also call
|
59
|
+
# `yield`, which passes control to the next middleware in the stack. A
|
60
|
+
# middleware can disable modifications done by subsequent middleware by
|
61
|
+
# omitting the `yield` call, but this is uncommon.
|
62
|
+
#
|
63
|
+
# This basic implementation does nothing and simply yields to the next
|
64
|
+
# middleware.
|
65
|
+
#
|
66
|
+
# @param [Toys::Definition::Tool] _tool_definition The tool definition
|
67
|
+
# to modify.
|
68
|
+
# @param [Toys::Loader] _loader The loader that loaded this tool.
|
69
|
+
#
|
70
|
+
def config(_tool_definition, _loader)
|
71
|
+
yield
|
72
|
+
end
|
91
73
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
when ::String
|
115
|
-
[flags]
|
116
|
-
when ::Array
|
117
|
-
flags
|
118
|
-
else
|
119
|
-
[]
|
120
|
-
end
|
121
|
-
end
|
74
|
+
##
|
75
|
+
# This method is called when the tool is run. It gives the middleware an
|
76
|
+
# opportunity to modify the runtime behavior of the tool. It is passed
|
77
|
+
# the tool instance (i.e. the object that hosts a tool's `run` method),
|
78
|
+
# and you can use this object to access the tool's options and other
|
79
|
+
# context data. In most cases, this method should also call `yield`,
|
80
|
+
# which passes control to the next middleware in the stack. A middleware
|
81
|
+
# can "wrap" normal execution by calling `yield` somewhere in its
|
82
|
+
# implementation of this method, or it can completely replace the
|
83
|
+
# execution behavior by not calling `yield` at all.
|
84
|
+
#
|
85
|
+
# Like a tool's `run` method, this method's return value is unused. If
|
86
|
+
# you want to output from a tool, write to stdout or stderr. If you want
|
87
|
+
# to set the exit status code, call {Toys::Tool#exit} on the tool object.
|
88
|
+
#
|
89
|
+
# This basic implementation does nothing and simply yields to the next
|
90
|
+
# middleware.
|
91
|
+
#
|
92
|
+
# @param [Toys::Tool] _tool The tool execution instance.
|
93
|
+
#
|
94
|
+
def run(_tool)
|
95
|
+
yield
|
122
96
|
end
|
123
97
|
end
|
124
98
|
end
|