toys-core 0.3.7.1 → 0.3.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|