toys-core 0.3.9.1 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ddc8eac1d584a35898abadd2c8ef601c6fa4c98fc6854e0bd5578e47f46b6ae
4
- data.tar.gz: e15d35d38f56128bb8d5cdef467db338b6e813f88df5be5cbe4a44b9698703fd
3
+ metadata.gz: 7bfede9155648ae5e0b3766dfad5b5165f80fa865eca0e91d390706616372c6e
4
+ data.tar.gz: 78ba80645b891e5382049153d47168ef69f18e7e762efe553a0f77ad14aa178a
5
5
  SHA512:
6
- metadata.gz: 0ff220cbdc9fca5b657d7f4924ad5ac263984ece39be6ed267c2d1f1989004ebcba2cb00f69c3427c890c45341fe0829852987ff324e02d2915abe9a58b4d380
7
- data.tar.gz: 20bc712ca5414341e309178d7367f7d4bdc506a8bd1d7f0fda3fa01f4f9f4d64e8c733f0879060d610626a760b6f5db3bb8279ffe096bc50b35f79d99f1a0f29
6
+ metadata.gz: f0f9533b044b056ea6ea46d121a18fd0a9966b1aadacc845c36651c258bf7bdf8ba8851ccd0f00770a27da67697dcf1fe003804e94b720f87efab4a348cb9cab
7
+ data.tar.gz: c010707f7452adf31bdbe1d4bd692f39a285091e899c46d6cd964c686ba1aa3df7e119df3888da0f2f660732409c96b1768604f0af48768efa90c188c8497d22
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Release History
2
2
 
3
+ ### 0.3.10 / 2018-06-30
4
+
5
+ * CHANGED: Dropped Tool#option. Use Tool#get instead.
6
+ * CHANGED: "run" directive renamed to "to_run"
7
+ * CHANGED: Highline mixin now uses Highline 2.0
8
+ * CHANGED: Middleware-added keys no longer show up in the options hash
9
+ * ADDED: Mixins can provide initializers
10
+ * ADDED: Loader can load an inline block
11
+
3
12
  ### 0.3.9.1 / 2018-06-24
4
13
 
5
14
  * FIXED: Built-in flags were interfering with disable_argument_parsing
data/lib/toys/cli.rb CHANGED
@@ -151,6 +151,20 @@ module Toys
151
151
  self
152
152
  end
153
153
 
154
+ ##
155
+ # Add a configuration block to the loader.
156
+ #
157
+ # @param [Boolean] high_priority Add the config at the head of the priority
158
+ # list rather than the tail.
159
+ # @param [String] path The "path" that will be shown in documentation for
160
+ # tools defined in this block. If omitted, a default unique string will
161
+ # be generated.
162
+ #
163
+ def add_config_block(high_priority: false, path: nil, &block)
164
+ @loader.add_block(high_priority: high_priority, path: path, &block)
165
+ self
166
+ end
167
+
154
168
  ##
155
169
  # Searches the given directory for a well-known config directory and/or
156
170
  # config file. If found, these are added to the loader.
@@ -32,5 +32,5 @@ module Toys
32
32
  # Current version of Toys core
33
33
  # @return [String]
34
34
  #
35
- CORE_VERSION = "0.3.9.1".freeze
35
+ CORE_VERSION = "0.3.10".freeze
36
36
  end
@@ -39,7 +39,7 @@ module Toys
39
39
  # Create an Arg definition
40
40
  # @private
41
41
  #
42
- def initialize(key, type, accept, default, desc, long_desc, display_name)
42
+ def initialize(key, type, accept, default, desc, long_desc, display_name = nil)
43
43
  @key = key
44
44
  @type = type
45
45
  @accept = accept
@@ -103,7 +103,7 @@ module Toys
103
103
  result = input
104
104
  optparse = ::OptionParser.new
105
105
  optparse.accept(accept) if accept.is_a?(Acceptor)
106
- optparse.on("--abc=VALUE", accept) { |v| result = v }
106
+ optparse.on("--abc VALUE", accept) { |v| result = v }
107
107
  optparse.parse(["--abc", input])
108
108
  result
109
109
  end
@@ -43,6 +43,8 @@ module Toys
43
43
  setup(str, [$1], $1, "-", nil, nil, nil, nil)
44
44
  when /^(-[\?\w])( ?)\[(\w+)\]$/
45
45
  setup(str, [$1], $1, "-", :value, :optional, $2, $3)
46
+ when /^(-[\?\w])\[( )(\w+)\]$/
47
+ setup(str, [$1], $1, "-", :value, :optional, $2, $3)
46
48
  when /^(-[\?\w])( ?)(\w+)$/
47
49
  setup(str, [$1], $1, "-", :value, :required, $2, $3)
48
50
  when /^--\[no-\](\w[\?\w-]*)$/
@@ -305,6 +307,7 @@ module Toys
305
307
  analyze_flag_syntax(flag)
306
308
  end
307
309
  @flag_type ||= :boolean
310
+ @value_type ||= :required if @flag_type == :value
308
311
  flag_syntax.each do |flag|
309
312
  flag.configure_canonical(@flag_type, @value_type, @value_label, @value_delim)
310
313
  end
@@ -82,6 +82,7 @@ module Toys
82
82
 
83
83
  @default_data = {}
84
84
  @used_flags = []
85
+ @initializers = []
85
86
 
86
87
  @acceptors = {}
87
88
  @mixins = {}
@@ -381,6 +382,20 @@ module Toys
381
382
  @long_desc = Utils::WrappableString.make_array(long_desc)
382
383
  end
383
384
 
385
+ ##
386
+ # Append long description strings.
387
+ #
388
+ # Each string may be provided as a {Toys::Utils::WrappableString}, a single
389
+ # string (which will be wrapped), or an array of strings, which will be
390
+ # interpreted as string fragments that will be concatenated and wrapped.
391
+ #
392
+ # @param [Array<Toys::Utils::WrappableString,String,Array<String>>] long_desc
393
+ #
394
+ def append_long_desc(long_desc)
395
+ check_definition_state
396
+ @long_desc += Utils::WrappableString.make_array(long_desc)
397
+ end
398
+
384
399
  ##
385
400
  # Add an acceptor to the tool. This acceptor may be refereneced by name
386
401
  # when adding a flag or an arg.
@@ -615,7 +630,19 @@ module Toys
615
630
  # @param [Proc] proc The runnable block
616
631
  #
617
632
  def runnable=(proc)
618
- @tool_class.run(&proc)
633
+ @tool_class.to_run(&proc)
634
+ end
635
+
636
+ ##
637
+ # Add an initializer.
638
+ #
639
+ # @param [Proc] proc The initializer block
640
+ # @param [Object...] args Arguments to pass to the initializer
641
+ #
642
+ def add_initializer(proc, *args)
643
+ check_definition_state
644
+ @initializers << [proc, args]
645
+ self
619
646
  end
620
647
 
621
648
  ##
@@ -647,6 +674,17 @@ module Toys
647
674
  self
648
675
  end
649
676
 
677
+ ##
678
+ # Run all initializers against a tool. Should be called from the Runner
679
+ # only.
680
+ # @private
681
+ #
682
+ def run_initializers(tool)
683
+ @initializers.each do |func, args|
684
+ tool.instance_exec(*args, &func)
685
+ end
686
+ end
687
+
650
688
  private
651
689
 
652
690
  def make_config_proc(middleware, loader, next_config)
data/lib/toys/dsl/arg.rb CHANGED
@@ -44,7 +44,7 @@ module Toys
44
44
  @default = default
45
45
  @display_name = display_name
46
46
  @desc = desc
47
- @long_desc = long_desc
47
+ @long_desc = long_desc || []
48
48
  end
49
49
 
50
50
  ##
@@ -70,7 +70,7 @@ module Toys
70
70
  # @param [String] display_name
71
71
  #
72
72
  def display_name(display_name)
73
- @handler = display_name
73
+ @display_name = display_name
74
74
  self
75
75
  end
76
76
 
data/lib/toys/dsl/flag.rb CHANGED
@@ -45,7 +45,7 @@ module Toys
45
45
  @handler = handler
46
46
  @report_collisions = report_collisions
47
47
  @desc = desc
48
- @long_desc = long_desc
48
+ @long_desc = long_desc || []
49
49
  end
50
50
 
51
51
  ##
data/lib/toys/dsl/tool.rb CHANGED
@@ -48,7 +48,7 @@ module Toys
48
48
  # optional_arg :recipient, default: "world"
49
49
  #
50
50
  # def run
51
- # puts "Hello, #{option(:recipient)}!"
51
+ # puts "Hello, #{get(:recipient)}!"
52
52
  # end
53
53
  # end
54
54
  #
@@ -63,7 +63,7 @@ module Toys
63
63
  module Tool
64
64
  ## @private
65
65
  def method_added(meth)
66
- cur_tool = DSL::Tool.activate_tool(self)
66
+ cur_tool = DSL::Tool.current_tool(self, true)
67
67
  cur_tool.mark_runnable if cur_tool && meth == :run
68
68
  end
69
69
 
@@ -108,7 +108,7 @@ module Toys
108
108
  # @param [Proc,nil] converter The validator.
109
109
  #
110
110
  def acceptor(name, validator = nil, converter = nil, &block)
111
- cur_tool = DSL::Tool.activate_tool(self)
111
+ cur_tool = DSL::Tool.current_tool(self, false)
112
112
  return self if cur_tool.nil?
113
113
  accept =
114
114
  case validator
@@ -134,8 +134,14 @@ module Toys
134
134
  # @param [String] name Name of the mixin
135
135
  #
136
136
  def mixin(name, &block)
137
- cur_tool = DSL::Tool.activate_tool(self)
138
- cur_tool.add_mixin(name, ::Module.new(&block)) if cur_tool
137
+ cur_tool = DSL::Tool.current_tool(self, false)
138
+ if cur_tool
139
+ mixin_mod = ::Module.new do
140
+ include ::Toys::Mixin
141
+ end
142
+ mixin_mod.module_eval(&block)
143
+ cur_tool.add_mixin(name, mixin_mod)
144
+ end
139
145
  self
140
146
  end
141
147
 
@@ -152,7 +158,7 @@ module Toys
152
158
  # @param [String] name Name of the template
153
159
  #
154
160
  def template(name, &block)
155
- cur_tool = DSL::Tool.activate_tool(self)
161
+ cur_tool = DSL::Tool.current_tool(self, false)
156
162
  if cur_tool
157
163
  template_class = ::Class.new do
158
164
  include ::Toys::Template
@@ -200,7 +206,7 @@ module Toys
200
206
  # @param [String] path The file or directory to include.
201
207
  #
202
208
  def load(path)
203
- @__loader.include_path(path, @__words, @__remaining_words, @__priority)
209
+ @__loader.load_path(path, @__words, @__remaining_words, @__priority)
204
210
  self
205
211
  end
206
212
 
@@ -215,6 +221,8 @@ module Toys
215
221
  # @param [Object...] args Template arguments
216
222
  #
217
223
  def expand(template_class, *args)
224
+ cur_tool = DSL::Tool.current_tool(self, true)
225
+ return self if cur_tool.nil?
218
226
  name = template_class.to_s
219
227
  if template_class.is_a?(::String)
220
228
  template_class = cur_tool.resolve_template(template_class)
@@ -260,7 +268,7 @@ module Toys
260
268
  # @param [Toys::Utils::WrappableString,String,Array<String>] str
261
269
  #
262
270
  def desc(str)
263
- cur_tool = DSL::Tool.activate_tool(self)
271
+ cur_tool = DSL::Tool.current_tool(self, true)
264
272
  cur_tool.desc = str if cur_tool
265
273
  self
266
274
  end
@@ -286,8 +294,8 @@ module Toys
286
294
  # @param [Toys::Utils::WrappableString,String,Array<String>...] strs
287
295
  #
288
296
  def long_desc(*strs)
289
- cur_tool = DSL::Tool.activate_tool(self)
290
- cur_tool.long_desc = strs if cur_tool
297
+ cur_tool = DSL::Tool.current_tool(self, true)
298
+ cur_tool.append_long_desc(strs) if cur_tool
291
299
  self
292
300
  end
293
301
 
@@ -333,7 +341,7 @@ module Toys
333
341
  report_collisions: true,
334
342
  desc: nil, long_desc: nil,
335
343
  &block)
336
- cur_tool = DSL::Tool.activate_tool(self)
344
+ cur_tool = DSL::Tool.current_tool(self, true)
337
345
  return self if cur_tool.nil?
338
346
  flag_dsl = DSL::Flag.new(flags, accept, default, handler, report_collisions,
339
347
  desc, long_desc)
@@ -369,7 +377,7 @@ module Toys
369
377
  def required_arg(key,
370
378
  accept: nil, display_name: nil, desc: nil, long_desc: nil,
371
379
  &block)
372
- cur_tool = DSL::Tool.activate_tool(self)
380
+ cur_tool = DSL::Tool.current_tool(self, true)
373
381
  return self if cur_tool.nil?
374
382
  arg_dsl = DSL::Arg.new(accept, nil, display_name, desc, long_desc)
375
383
  arg_dsl.instance_exec(arg_dsl, &block) if block
@@ -410,7 +418,7 @@ module Toys
410
418
  default: nil, accept: nil, display_name: nil,
411
419
  desc: nil, long_desc: nil,
412
420
  &block)
413
- cur_tool = DSL::Tool.activate_tool(self)
421
+ cur_tool = DSL::Tool.current_tool(self, true)
414
422
  return self if cur_tool.nil?
415
423
  arg_dsl = DSL::Arg.new(accept, default, display_name, desc, long_desc)
416
424
  arg_dsl.instance_exec(arg_dsl, &block) if block
@@ -450,7 +458,7 @@ module Toys
450
458
  default: [], accept: nil, display_name: nil,
451
459
  desc: nil, long_desc: nil,
452
460
  &block)
453
- cur_tool = DSL::Tool.activate_tool(self)
461
+ cur_tool = DSL::Tool.current_tool(self, true)
454
462
  return self if cur_tool.nil?
455
463
  arg_dsl = DSL::Arg.new(accept, default, display_name, desc, long_desc)
456
464
  arg_dsl.instance_exec(arg_dsl, &block) if block
@@ -466,10 +474,14 @@ module Toys
466
474
  # execution context.
467
475
  # @param [Object] value The value to set.
468
476
  #
469
- def set(key, value)
470
- cur_tool = DSL::Tool.activate_tool(self)
477
+ def set(key, value = nil)
478
+ cur_tool = DSL::Tool.current_tool(self, true)
471
479
  return self if cur_tool.nil?
472
- cur_tool.default_data[key] = value
480
+ if key.is_a?(::Hash)
481
+ cur_tool.default_data.merge!(key)
482
+ else
483
+ cur_tool.default_data[key] = value
484
+ end
473
485
  self
474
486
  end
475
487
 
@@ -482,29 +494,29 @@ module Toys
482
494
  # declare arguments or flags.
483
495
  #
484
496
  def disable_argument_parsing
485
- cur_tool = DSL::Tool.activate_tool(self)
497
+ cur_tool = DSL::Tool.current_tool(self, true)
486
498
  cur_tool.disable_argument_parsing unless cur_tool.nil?
487
499
  self
488
500
  end
489
501
 
490
502
  ##
491
503
  # Mark one or more flags as disabled, preventing their use by any
492
- # subsequent flag definition. This may be used to prevent middleware from
504
+ # subsequent flag definition. This can be used to prevent middleware from
493
505
  # defining a particular flag.
494
506
  #
495
507
  # @param [String...] flags The flags to disable
496
508
  #
497
509
  def disable_flag(*flags)
498
- cur_tool = DSL::Tool.activate_tool(self)
510
+ cur_tool = DSL::Tool.current_tool(self, true)
499
511
  cur_tool.disable_flag(*flags) unless cur_tool.nil?
500
512
  self
501
513
  end
502
514
 
503
515
  ##
504
- # Specify how to run this tool. You may do this by providing a block to
516
+ # Specify how to run this tool. You can do this by providing a block to
505
517
  # this directive, or by defining the `run` method in the tool.
506
518
  #
507
- def run(&block)
519
+ def to_run(&block)
508
520
  define_method(:run, &block)
509
521
  self
510
522
  end
@@ -518,9 +530,10 @@ module Toys
518
530
  # of a well-known mixin.
519
531
  #
520
532
  # @param [Module,Symbol,String] mod Module or module name.
533
+ # @param [Object...] args Arguments to pass to the initializer
521
534
  #
522
- def include(mod)
523
- cur_tool = DSL::Tool.activate_tool(self)
535
+ def include(mod, *args)
536
+ cur_tool = DSL::Tool.current_tool(self, true)
524
537
  return if cur_tool.nil?
525
538
  name = mod.to_s
526
539
  if mod.is_a?(::String)
@@ -531,6 +544,9 @@ module Toys
531
544
  if mod.nil?
532
545
  raise ToolDefinitionError, "Module not found: #{name.inspect}"
533
546
  end
547
+ if mod.respond_to?(:initializer)
548
+ cur_tool.add_initializer(mod.initializer, *args) if mod.initializer
549
+ end
534
550
  super(mod)
535
551
  end
536
552
 
@@ -558,24 +574,28 @@ module Toys
558
574
  end
559
575
 
560
576
  ## @private
561
- def self.activate_tool(tool_class)
577
+ def self.current_tool(tool_class, activate)
578
+ memoize_var = activate ? :@__active_tool : :@__cur_tool
562
579
  path = tool_class.instance_variable_get(:@__path)
563
- cur_tool =
564
- if tool_class.instance_variable_defined?(:@__cur_tool)
565
- tool_class.instance_variable_get(:@__cur_tool)
566
- else
567
- loader = tool_class.instance_variable_get(:@__loader)
568
- words = tool_class.instance_variable_get(:@__words)
569
- priority = tool_class.instance_variable_get(:@__priority)
570
- cur_tool = loader.activate_tool_definition(words, priority)
571
- if cur_tool.is_a?(Definition::Alias)
572
- raise ToolDefinitionError,
573
- "Cannot configure #{words.join(' ').inspect} because it is an alias"
580
+ if tool_class.instance_variable_defined?(memoize_var)
581
+ cur_tool = tool_class.instance_variable_get(memoize_var)
582
+ else
583
+ loader = tool_class.instance_variable_get(:@__loader)
584
+ words = tool_class.instance_variable_get(:@__words)
585
+ priority = tool_class.instance_variable_get(:@__priority)
586
+ cur_tool =
587
+ if activate
588
+ loader.activate_tool_definition(words, priority)
589
+ else
590
+ loader.get_tool_definition(words, priority)
574
591
  end
575
- tool_class.instance_variable_set(:@__cur_tool, cur_tool)
576
- cur_tool
592
+ if cur_tool.is_a?(Definition::Alias)
593
+ raise ToolDefinitionError,
594
+ "Cannot configure #{words.join(' ').inspect} because it is an alias"
577
595
  end
578
- cur_tool.lock_source_path(path) if cur_tool
596
+ tool_class.instance_variable_set(memoize_var, cur_tool)
597
+ end
598
+ cur_tool.lock_source_path(path) if cur_tool && activate
579
599
  cur_tool
580
600
  end
581
601
 
data/lib/toys/loader.rb CHANGED
@@ -44,6 +44,9 @@ module Toys
44
44
  end
45
45
  end
46
46
 
47
+ ## @private
48
+ LOW_PRIORITY = -999_999
49
+
47
50
  ##
48
51
  # Create a Loader
49
52
  #
@@ -80,7 +83,7 @@ module Toys
80
83
  @index_file_name = index_file_name
81
84
  @preload_file_name = preload_file_name
82
85
  @middleware_stack = middleware_stack
83
- @load_worklist = []
86
+ @worklist = []
84
87
  @tool_data = {}
85
88
  @max_priority = @min_priority = 0
86
89
  end
@@ -97,11 +100,28 @@ module Toys
97
100
  paths = Array(path)
98
101
  priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
99
102
  paths.each do |p|
100
- @load_worklist << [check_path(p), [], priority]
103
+ @worklist << [:file, check_path(p), [], priority]
101
104
  end
102
105
  self
103
106
  end
104
107
 
108
+ ##
109
+ # Add a configuration block to the loader.
110
+ #
111
+ # @param [Boolean] high_priority If true, add this block at the top of the
112
+ # priority list. Defaults to false, indicating the block should be at
113
+ # the bottom of the priority list.
114
+ # @param [String] path The "path" that will be shown in documentation for
115
+ # tools defined in this block. If omitted, a default unique string will
116
+ # be generated.
117
+ #
118
+ def add_block(high_priority: false, path: nil, &block)
119
+ path ||= "(Block #{block.object_id})"
120
+ priority = high_priority ? (@max_priority += 1) : (@min_priority -= 1)
121
+ @worklist << [block, path, [], priority]
122
+ self
123
+ end
124
+
105
125
  ##
106
126
  # Given a list of command line arguments, find the appropriate tool to
107
127
  # handle the command, loading it from the configuration if necessary, and
@@ -131,7 +151,7 @@ module Toys
131
151
  break if p.empty? || p.length <= cur_prefix.length
132
152
  p = p.slice(0..-2)
133
153
  end
134
- return nil if cur_prefix.empty?
154
+ return get_tool_definition([], LOW_PRIORITY) if cur_prefix.empty?
135
155
  cur_prefix = cur_prefix.slice(0..-2)
136
156
  end
137
157
  end
@@ -279,8 +299,26 @@ module Toys
279
299
  #
280
300
  # @private
281
301
  #
282
- def include_path(path, words, remaining_words, priority)
283
- handle_path(check_path(path), words, remaining_words, priority)
302
+ def load_path(path, words, remaining_words, priority)
303
+ load_validated_path(check_path(path), words, remaining_words, priority)
304
+ end
305
+
306
+ ##
307
+ # Load configuration from the given proc.
308
+ #
309
+ # @private
310
+ #
311
+ def load_proc(proc, words, remaining_words, priority, path)
312
+ if remaining_words
313
+ tool_class = get_tool_definition(words, priority).tool_class
314
+ ::Toys::DSL::Tool.prepare(tool_class, remaining_words, path) do
315
+ ::Toys::ContextualError.capture("Error while loading Toys config!") do
316
+ tool_class.class_eval(&proc)
317
+ end
318
+ end
319
+ else
320
+ @worklist << [proc, path, words, priority]
321
+ end
284
322
  end
285
323
 
286
324
  ##
@@ -365,22 +403,27 @@ module Toys
365
403
  end
366
404
 
367
405
  def load_for_prefix(prefix)
368
- cur_worklist = @load_worklist
369
- @load_worklist = []
370
- cur_worklist.each do |path, words, priority|
371
- handle_path(path, words, calc_remaining_words(prefix, words), priority)
406
+ cur_worklist = @worklist
407
+ @worklist = []
408
+ cur_worklist.each do |source, path, words, priority|
409
+ remaining_words = calc_remaining_words(prefix, words)
410
+ if source.respond_to?(:call)
411
+ load_proc(source, words, remaining_words, priority, path)
412
+ elsif source == :file
413
+ load_validated_path(path, words, remaining_words, priority)
414
+ end
372
415
  end
373
416
  end
374
417
 
375
- def handle_path(path, words, remaining_words, priority)
418
+ def load_validated_path(path, words, remaining_words, priority)
376
419
  if remaining_words
377
- load_path(path, words, remaining_words, priority)
420
+ load_relevant_path(path, words, remaining_words, priority)
378
421
  else
379
- @load_worklist << [path, words, priority]
422
+ @worklist << [:file, path, words, priority]
380
423
  end
381
424
  end
382
425
 
383
- def load_path(path, words, remaining_words, priority)
426
+ def load_relevant_path(path, words, remaining_words, priority)
384
427
  if ::File.extname(path) == ".rb"
385
428
  tool_class = get_tool_definition(words, priority).tool_class
386
429
  Toys::InputFile.evaluate(tool_class, remaining_words, path)
@@ -404,7 +447,7 @@ module Toys
404
447
  return unless @index_file_name
405
448
  index_path = ::File.join(path, @index_file_name)
406
449
  index_path = check_path(index_path, type: :file, lenient: true)
407
- load_path(index_path, words, remaining_words, priority) if index_path
450
+ load_relevant_path(index_path, words, remaining_words, priority) if index_path
408
451
  end
409
452
 
410
453
  def load_child_in(path, child, words, remaining_words, priority)
@@ -414,7 +457,7 @@ module Toys
414
457
  child_word = ::File.basename(child, ".rb")
415
458
  next_words = words + [child_word]
416
459
  next_remaining = Loader.next_remaining_words(remaining_words, child_word)
417
- handle_path(child_path, next_words, next_remaining, priority)
460
+ load_validated_path(child_path, next_words, next_remaining, priority)
418
461
  end
419
462
 
420
463
  def check_path(path, lenient: false, type: nil)
data/lib/toys/mixin.rb ADDED
@@ -0,0 +1,112 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ module Toys
31
+ ##
32
+ # A mixin definition. Mixin modules should include this module.
33
+ #
34
+ # A mixin is a collection of methods that are available to be called from a
35
+ # tool implementation (i.e. its run method). The mixin is added to the tool
36
+ # class, so it has access to the same methods that can be called by the tool,
37
+ # such as {Toys::Tool#option}.
38
+ #
39
+ # ## Usage
40
+ #
41
+ # To create a mixin, define a module, and include this module. Then define
42
+ # the methods you want to be available.
43
+ #
44
+ # If you want to perform some initialization specific to the mixin, use a
45
+ # `to_initialize` block. This block is passed any extra arguments that were
46
+ # passed to the `include` directive. It is called in the context of the tool,
47
+ # so it also has access to tool methods such as {Toys::Tool#option}. It can
48
+ # perform any setup required, which often involves initializing some
49
+ # persistent state and storing it in the tool using {Toys::Tool#set}.
50
+ #
51
+ # ## Example
52
+ #
53
+ # This is an example that implements a simple counter. Whenever the counter
54
+ # is incremented, a log message is emitted. The tool can also retrieve the
55
+ # final counter value.
56
+ #
57
+ # # Define a mixin by creating a module that includes Toys::Mixin
58
+ # module MyCounterMixin
59
+ # include Toys::Mixin
60
+ #
61
+ # # Initialize the counter. Called with self set to the tool so it can
62
+ # # affect the tool state.
63
+ # to_initialize do |start = 0|
64
+ # set(:counter_value, start)
65
+ # end
66
+ #
67
+ # # Mixin methods are called with self set to the tool and can affect
68
+ # # the tool state.
69
+ # def increment
70
+ # self[:counter_value] += 1
71
+ # logger.info("Incremented counter")
72
+ # end
73
+ # end
74
+ #
75
+ # Now we can use it from a tool:
76
+ #
77
+ # tool "count-up" do
78
+ # # Pass 1 as an extra argument to the mixin initializer
79
+ # include MyCounterMixin, 1
80
+ #
81
+ # def run
82
+ # 5.times { increment }
83
+ # puts "Final value is #{get(:counter_value)}"
84
+ # end
85
+ # end
86
+ #
87
+ module Mixin
88
+ ## @private
89
+ def self.included(mod)
90
+ return if mod.respond_to?(:to_initialize)
91
+ mod.extend(ClassMethods)
92
+ end
93
+
94
+ ##
95
+ # Class methods that will be added to a mixin module.
96
+ #
97
+ module ClassMethods
98
+ ##
99
+ # Provide the block that initializes this mixin.
100
+ #
101
+ def to_initialize(&block)
102
+ self.initializer = block
103
+ end
104
+
105
+ ##
106
+ # You may alternately set the initializer block using this accessor.
107
+ # @return [Proc]
108
+ #
109
+ attr_accessor :initializer
110
+ end
111
+ end
112
+ end
data/lib/toys/runner.rb CHANGED
@@ -61,6 +61,7 @@ module Toys
61
61
  data = create_data(args, verbosity)
62
62
  parse_args(args, data) unless @tool_definition.argument_parsing_disabled?
63
63
  tool = @tool_definition.tool_class.new(@cli, data)
64
+ @tool_definition.run_initializers(tool)
64
65
 
65
66
  original_level = @cli.logger.level
66
67
  @cli.logger.level = @cli.base_level - data[Tool::Keys::VERBOSITY]
@@ -66,6 +66,36 @@ module Toys
66
66
  #
67
67
  DEFAULT_SEARCH_FLAGS = ["-s WORD", "--search=WORD"].freeze
68
68
 
69
+ ##
70
+ # Key set when the show help flag is present
71
+ # @return [Object]
72
+ #
73
+ SHOW_HELP_KEY = Object.new.freeze
74
+
75
+ ##
76
+ # Key set when the show usage flag is present
77
+ # @return [Object]
78
+ #
79
+ SHOW_USAGE_KEY = Object.new.freeze
80
+
81
+ ##
82
+ # Key for the recursive setting
83
+ # @return [Object]
84
+ #
85
+ RECURSIVE_SUBTOOLS_KEY = Object.new.freeze
86
+
87
+ ##
88
+ # Key for the search string
89
+ # @return [Object]
90
+ #
91
+ SEARCH_STRING_KEY = Object.new.freeze
92
+
93
+ ##
94
+ # Key for the tool name
95
+ # @return [Object]
96
+ #
97
+ TOOL_NAME_KEY = Object.new.freeze
98
+
69
99
  ##
70
100
  # Create a ShowHelp middleware.
71
101
  #
@@ -155,7 +185,7 @@ module Toys
155
185
  usage_flags = add_usage_flags(tool_definition)
156
186
  if @allow_root_args && (!help_flags.empty? || !usage_flags.empty?)
157
187
  if tool_definition.root? && tool_definition.arg_definitions.empty?
158
- tool_definition.set_remaining_args(:_tool_name,
188
+ tool_definition.set_remaining_args(TOOL_NAME_KEY,
159
189
  display_name: "TOOL_NAME",
160
190
  desc: "The tool for which to display help")
161
191
  end
@@ -173,15 +203,15 @@ module Toys
173
203
  # Display help text if requested.
174
204
  #
175
205
  def run(tool)
176
- if tool[:_show_usage]
206
+ if tool[SHOW_USAGE_KEY]
177
207
  help_text = get_help_text(tool)
178
208
  str = help_text.usage_string(wrap_width: terminal.width)
179
209
  terminal.puts(str)
180
210
  elsif @fallback_execution && !tool[Tool::Keys::TOOL_DEFINITION].runnable? ||
181
- tool[:_show_help]
211
+ tool[SHOW_HELP_KEY]
182
212
  help_text = get_help_text(tool)
183
- str = help_text.help_string(recursive: tool[:_recursive_subtools],
184
- search: tool[:_search_subtools],
213
+ str = help_text.help_string(recursive: tool[RECURSIVE_SUBTOOLS_KEY],
214
+ search: tool[SEARCH_STRING_KEY],
185
215
  show_source_path: @show_source_path,
186
216
  wrap_width: terminal.width)
187
217
  output_help(str)
@@ -216,7 +246,7 @@ module Toys
216
246
  end
217
247
 
218
248
  def get_help_text(tool)
219
- tool_name = tool[:_tool_name]
249
+ tool_name = tool[TOOL_NAME_KEY]
220
250
  return Utils::HelpText.from_tool(tool) if tool_name.nil? || tool_name.empty?
221
251
  loader = tool[Tool::Keys::LOADER]
222
252
  tool_definition, rest = loader.lookup(tool_name)
@@ -236,7 +266,7 @@ module Toys
236
266
  help_flags = resolve_flags_spec(@help_flags, tool_definition, DEFAULT_HELP_FLAGS)
237
267
  unless help_flags.empty?
238
268
  tool_definition.add_flag(
239
- :_show_help, help_flags,
269
+ SHOW_HELP_KEY, help_flags,
240
270
  report_collisions: false,
241
271
  desc: "Display help for this tool"
242
272
  )
@@ -248,7 +278,7 @@ module Toys
248
278
  usage_flags = resolve_flags_spec(@usage_flags, tool_definition, DEFAULT_USAGE_FLAGS)
249
279
  unless usage_flags.empty?
250
280
  tool_definition.add_flag(
251
- :_show_usage, usage_flags,
281
+ SHOW_USAGE_KEY, usage_flags,
252
282
  report_collisions: false,
253
283
  desc: "Display a brief usage string for this tool"
254
284
  )
@@ -261,7 +291,7 @@ module Toys
261
291
  DEFAULT_RECURSIVE_FLAGS)
262
292
  unless recursive_flags.empty?
263
293
  tool_definition.add_flag(
264
- :_recursive_subtools, recursive_flags,
294
+ RECURSIVE_SUBTOOLS_KEY, recursive_flags,
265
295
  report_collisions: false, default: @default_recursive,
266
296
  desc: "Show all subtools recursively (default is #{@default_recursive})"
267
297
  )
@@ -272,7 +302,7 @@ module Toys
272
302
  search_flags = resolve_flags_spec(@search_flags, tool_definition, DEFAULT_SEARCH_FLAGS)
273
303
  unless search_flags.empty?
274
304
  tool_definition.add_flag(
275
- :_search_subtools, search_flags,
305
+ SEARCH_STRING_KEY, search_flags,
276
306
  report_collisions: false,
277
307
  desc: "Search subtools for the given regular expression"
278
308
  )
@@ -48,6 +48,12 @@ module Toys
48
48
  #
49
49
  DEFAULT_VERSION_FLAG_DESC = "Display the version".freeze
50
50
 
51
+ ##
52
+ # Key set when the version flag is present
53
+ # @return [Object]
54
+ #
55
+ SHOW_VERSION_KEY = Object.new.freeze
56
+
51
57
  ##
52
58
  # Create a ShowVersion middleware
53
59
  #
@@ -72,7 +78,7 @@ module Toys
72
78
  #
73
79
  def config(tool_definition, _loader)
74
80
  if @version_string && tool_definition.root?
75
- tool_definition.add_flag(:_show_version, @version_flags,
81
+ tool_definition.add_flag(SHOW_VERSION_KEY, @version_flags,
76
82
  report_collisions: false, desc: @version_flag_desc)
77
83
  end
78
84
  yield
@@ -82,7 +88,7 @@ module Toys
82
88
  # This middleware displays the version.
83
89
  #
84
90
  def run(tool)
85
- if tool[:_show_version]
91
+ if tool[SHOW_VERSION_KEY]
86
92
  @terminal.puts(@version_string)
87
93
  else
88
94
  yield
@@ -44,6 +44,26 @@ module Toys
44
44
  # available in that class's documentation.
45
45
  #
46
46
  module Exec
47
+ include Mixin
48
+
49
+ ##
50
+ # Context key for the executor object.
51
+ # @return [Object]
52
+ #
53
+ KEY = ::Object.new.freeze
54
+
55
+ to_initialize do |opts = {}|
56
+ tool = self
57
+ tool[KEY] = Utils::Exec.new(opts) do |k|
58
+ case k
59
+ when :logger
60
+ tool[Tool::Keys::LOGGER]
61
+ when :cli
62
+ tool[Tool::Keys::CLI]
63
+ end
64
+ end
65
+ end
66
+
47
67
  ##
48
68
  # Set default configuration keys.
49
69
  #
@@ -51,7 +71,7 @@ module Toys
51
71
  # configuration options in the {Toys::Utils::Exec} docs.
52
72
  #
53
73
  def configure_exec(opts = {})
54
- Exec._exec(self).configure_defaults(Exec._setup_exec_opts(opts, self))
74
+ self[KEY].configure_defaults(Exec._setup_exec_opts(opts, self))
55
75
  end
56
76
 
57
77
  ##
@@ -71,7 +91,7 @@ module Toys
71
91
  # the exit code and any captured output.
72
92
  #
73
93
  def exec(cmd, opts = {}, &block)
74
- Exec._exec(self).exec(cmd, Exec._setup_exec_opts(opts, self), &block)
94
+ self[KEY].exec(cmd, Exec._setup_exec_opts(opts, self), &block)
75
95
  end
76
96
 
77
97
  ##
@@ -90,7 +110,7 @@ module Toys
90
110
  # the exit code and any captured output.
91
111
  #
92
112
  def exec_ruby(args, opts = {}, &block)
93
- Exec._exec(self).exec_ruby(args, Exec._setup_exec_opts(opts, self), &block)
113
+ self[KEY].exec_ruby(args, Exec._setup_exec_opts(opts, self), &block)
94
114
  end
95
115
  alias ruby exec_ruby
96
116
 
@@ -110,7 +130,7 @@ module Toys
110
130
  # exit code and any captured output.
111
131
  #
112
132
  def exec_proc(func, opts = {}, &block)
113
- Exec._exec(self).exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
133
+ self[KEY].exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
114
134
  end
115
135
 
116
136
  ##
@@ -131,7 +151,7 @@ module Toys
131
151
  #
132
152
  def exec_tool(cmd, opts = {}, &block)
133
153
  func = Exec._make_tool_caller(cmd)
134
- Exec._exec(self).exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
154
+ self[KEY].exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
135
155
  end
136
156
 
137
157
  ##
@@ -147,7 +167,7 @@ module Toys
147
167
  # @return [String] What was written to standard out.
148
168
  #
149
169
  def capture(cmd, opts = {})
150
- Exec._exec(self).capture(cmd, Exec._setup_exec_opts(opts, self))
170
+ self[KEY].capture(cmd, Exec._setup_exec_opts(opts, self))
151
171
  end
152
172
 
153
173
  ##
@@ -162,7 +182,7 @@ module Toys
162
182
  # @return [String] What was written to standard out.
163
183
  #
164
184
  def capture_ruby(args, opts = {})
165
- Exec._exec(self).capture_ruby(args, Exec._setup_exec_opts(opts, self))
185
+ self[KEY].capture_ruby(args, Exec._setup_exec_opts(opts, self))
166
186
  end
167
187
 
168
188
  ##
@@ -177,7 +197,7 @@ module Toys
177
197
  # @return [String] What was written to standard out.
178
198
  #
179
199
  def capture_proc(func, opts = {})
180
- Exec._exec(self).capture_proc(func, Exec._setup_exec_opts(opts, self))
200
+ self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self))
181
201
  end
182
202
 
183
203
  ##
@@ -194,7 +214,7 @@ module Toys
194
214
  #
195
215
  def capture_tool(cmd, opts = {})
196
216
  func = Exec._make_tool_caller(cmd)
197
- Exec._exec(self).capture_proc(func, Exec._setup_exec_opts(opts, self))
217
+ self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self))
198
218
  end
199
219
 
200
220
  ##
@@ -207,7 +227,7 @@ module Toys
207
227
  # @return [Integer] The exit code
208
228
  #
209
229
  def sh(cmd, opts = {})
210
- Exec._exec(self).sh(cmd, Exec._setup_exec_opts(opts, self))
230
+ self[KEY].sh(cmd, Exec._setup_exec_opts(opts, self))
211
231
  end
212
232
 
213
233
  ##
@@ -222,18 +242,6 @@ module Toys
222
242
  0
223
243
  end
224
244
 
225
- ## @private
226
- def self._exec(tool)
227
- tool[Exec] ||= Utils::Exec.new do |k|
228
- case k
229
- when :logger
230
- tool[Tool::Keys::LOGGER]
231
- when :cli
232
- tool[Tool::Keys::CLI]
233
- end
234
- end
235
- end
236
-
237
245
  ## @private
238
246
  def self._make_tool_caller(cmd)
239
247
  cmd = ::Shellwords.split(cmd) if cmd.is_a?(::String)
@@ -41,6 +41,8 @@ module Toys
41
41
  # include :fileutils
42
42
  #
43
43
  module Fileutils
44
+ include Mixin
45
+
44
46
  ## @private
45
47
  def self.included(mod)
46
48
  mod.include(::FileUtils)
@@ -27,7 +27,7 @@
27
27
  # POSSIBILITY OF SUCH DAMAGE.
28
28
  ;
29
29
 
30
- Toys::Utils::Gems.activate("highline", "~> 1.7")
30
+ Toys::Utils::Gems.activate("highline", "~> 2.0")
31
31
  require "highline"
32
32
 
33
33
  module Toys
@@ -41,15 +41,25 @@ module Toys
41
41
  # include :highline
42
42
  #
43
43
  module Highline
44
+ include Mixin
45
+
46
+ ##
47
+ # Context key for the executor object.
48
+ # @return [Object]
49
+ #
50
+ KEY = ::Object.new.freeze
51
+
52
+ to_initialize do |*args|
53
+ self[KEY] = ::HighLine.new(*args)
54
+ self[KEY].use_color = $stdout.tty?
55
+ end
56
+
44
57
  ##
45
58
  # Returns a global highline instance
46
59
  # @return [::HighLine]
47
60
  #
48
61
  def highline
49
- self[Highline] ||= begin
50
- ::HighLine.use_color = $stdout.tty?
51
- ::HighLine.new
52
- end
62
+ self[KEY]
53
63
  end
54
64
 
55
65
  ##
@@ -88,38 +98,52 @@ module Toys
88
98
  end
89
99
 
90
100
  ##
91
- # @see https://www.rubydoc.info/gems/highline/HighLine.color HighLine.color
101
+ # @see https://www.rubydoc.info/gems/highline/HighLine:indent HighLine#indent
92
102
  #
93
- def color(*args, &block)
94
- ::HighLine.color(*args, &block)
103
+ def indent(*args, &block)
104
+ highline.indent(*args, &block)
95
105
  end
96
106
 
97
107
  ##
98
- # @see https://www.rubydoc.info/gems/highline/HighLine.color_code HighLine.color_code
108
+ # @see https://www.rubydoc.info/gems/highline/HighLine:newline HighLine#newline
99
109
  #
100
- def color_code(*args, &block)
101
- ::HighLine.color_code(*args, &block)
110
+ def newline
111
+ highline.newline
102
112
  end
103
113
 
104
114
  ##
105
- # @see https://www.rubydoc.info/gems/highline/HighLine.uncolor HighLine.uncolor
115
+ # @see https://www.rubydoc.info/gems/highline/HighLine:puts HighLine#puts
106
116
  #
107
- def uncolor(*args, &block)
108
- ::HighLine.uncolor(*args, &block)
117
+ def puts(*args)
118
+ highline.puts(*args)
109
119
  end
110
120
 
111
121
  ##
112
- # @see https://www.rubydoc.info/gems/highline/HighLine:indent HighLine#indent
122
+ # @see https://www.rubydoc.info/gems/highline/HighLine:color HighLine#color
113
123
  #
114
- def indent(*args, &block)
115
- highline.indent(*args, &block)
124
+ def color(*args)
125
+ highline.color(*args)
116
126
  end
117
127
 
118
128
  ##
119
- # @see https://www.rubydoc.info/gems/highline/HighLine:newline HighLine#newline
129
+ # @see https://www.rubydoc.info/gems/highline/HighLine:color_code HighLine#color_code
130
+ #
131
+ def color_code(*args)
132
+ highline.color_code(*args)
133
+ end
134
+
135
+ ##
136
+ # @see https://www.rubydoc.info/gems/highline/HighLine:uncolor HighLine#uncolor
137
+ #
138
+ def uncolor(*args)
139
+ highline.uncolor(*args)
140
+ end
141
+
142
+ ##
143
+ # @see https://www.rubydoc.info/gems/highline/HighLine:new_scope HighLine#new_scope
120
144
  #
121
- def newline(*args, &block)
122
- highline.newline(*args, &block)
145
+ def new_scope
146
+ highline.new_scope
123
147
  end
124
148
  end
125
149
  end
@@ -32,7 +32,9 @@ module Toys
32
32
  ##
33
33
  # A mixin that provides a simple terminal. It includes a set of methods
34
34
  # that produce styled output, get user input, and otherwise interact with
35
- # the user's terminal.
35
+ # the user's terminal. This mixin is not as richly featured as other mixins
36
+ # such as Highline, but it has no gem dependencies so is ideal for basic
37
+ # cases.
36
38
  #
37
39
  # You may make these methods available to your tool by including the
38
40
  # following directive in your tool configuration:
@@ -40,12 +42,24 @@ module Toys
40
42
  # include :terminal
41
43
  #
42
44
  module Terminal
45
+ include Mixin
46
+
47
+ ##
48
+ # Context key for the terminal object.
49
+ # @return [Object]
50
+ #
51
+ KEY = ::Object.new.freeze
52
+
53
+ to_initialize do |opts = {}|
54
+ self[KEY] = Utils::Terminal.new(opts)
55
+ end
56
+
43
57
  ##
44
58
  # Returns a global terminal instance
45
59
  # @return [Toys::Utils::Terminal]
46
60
  #
47
61
  def terminal
48
- self[Terminal] ||= Utils::Terminal.new
62
+ self[KEY]
49
63
  end
50
64
 
51
65
  ##
data/lib/toys/template.rb CHANGED
@@ -77,7 +77,7 @@ module Toys
77
77
  # to_expand do |template|
78
78
  # desc "Prints a greeting to #{template.name}"
79
79
  # tool "templated-greeting" do
80
- # run do
80
+ # to_run do
81
81
  # puts "Hello, #{template.name}!"
82
82
  # end
83
83
  # end
@@ -112,7 +112,7 @@ module Toys
112
112
  # Provide the block that implements the template.
113
113
  #
114
114
  def to_expand(&block)
115
- @expander = block
115
+ self.expander = block
116
116
  end
117
117
 
118
118
  ##
data/lib/toys/tool.rb CHANGED
@@ -257,18 +257,6 @@ module Toys
257
257
  end
258
258
  end
259
259
 
260
- ##
261
- # Returns the value of the given option. Returns only options with string
262
- # or symbol keys; returns `nil` if passed other well-known context keys
263
- # such as verbosity.
264
- #
265
- # @param [String,Symbol] key
266
- # @return [Object]
267
- #
268
- def option(key)
269
- key.is_a?(::Symbol) || key.is_a?(::String) ? @__data[key] : nil
270
- end
271
-
272
260
  ##
273
261
  # Activate the given gem. If it is not present, attempt to install it (or
274
262
  # inform the user to update the bundle).
data/lib/toys-core.rb CHANGED
@@ -75,6 +75,7 @@ require "toys/errors"
75
75
  require "toys/input_file"
76
76
  require "toys/loader"
77
77
  require "toys/middleware"
78
+ require "toys/mixin"
78
79
  require "toys/runner"
79
80
  require "toys/template"
80
81
  require "toys/tool"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9.1
4
+ version: 0.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-25 00:00:00.000000000 Z
11
+ date: 2018-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -108,6 +108,7 @@ files:
108
108
  - lib/toys/input_file.rb
109
109
  - lib/toys/loader.rb
110
110
  - lib/toys/middleware.rb
111
+ - lib/toys/mixin.rb
111
112
  - lib/toys/runner.rb
112
113
  - lib/toys/standard_middleware/add_verbosity_flags.rb
113
114
  - lib/toys/standard_middleware/handle_usage_errors.rb