toys-core 0.7.0 → 0.8.0

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/LICENSE.md +16 -24
  4. data/README.md +307 -59
  5. data/docs/guide.md +44 -4
  6. data/lib/toys-core.rb +58 -49
  7. data/lib/toys/acceptor.rb +672 -0
  8. data/lib/toys/alias.rb +106 -0
  9. data/lib/toys/arg_parser.rb +624 -0
  10. data/lib/toys/cli.rb +422 -181
  11. data/lib/toys/compat.rb +83 -0
  12. data/lib/toys/completion.rb +442 -0
  13. data/lib/toys/context.rb +354 -0
  14. data/lib/toys/core_version.rb +18 -26
  15. data/lib/toys/dsl/flag.rb +213 -56
  16. data/lib/toys/dsl/flag_group.rb +237 -51
  17. data/lib/toys/dsl/positional_arg.rb +210 -0
  18. data/lib/toys/dsl/tool.rb +968 -317
  19. data/lib/toys/errors.rb +46 -28
  20. data/lib/toys/flag.rb +821 -0
  21. data/lib/toys/flag_group.rb +282 -0
  22. data/lib/toys/input_file.rb +18 -26
  23. data/lib/toys/loader.rb +110 -100
  24. data/lib/toys/middleware.rb +24 -31
  25. data/lib/toys/mixin.rb +90 -59
  26. data/lib/toys/module_lookup.rb +125 -0
  27. data/lib/toys/positional_arg.rb +184 -0
  28. data/lib/toys/source_info.rb +192 -0
  29. data/lib/toys/standard_middleware/add_verbosity_flags.rb +38 -43
  30. data/lib/toys/standard_middleware/handle_usage_errors.rb +39 -40
  31. data/lib/toys/standard_middleware/set_default_descriptions.rb +111 -89
  32. data/lib/toys/standard_middleware/show_help.rb +130 -113
  33. data/lib/toys/standard_middleware/show_root_version.rb +29 -35
  34. data/lib/toys/standard_mixins/exec.rb +116 -78
  35. data/lib/toys/standard_mixins/fileutils.rb +16 -24
  36. data/lib/toys/standard_mixins/gems.rb +29 -30
  37. data/lib/toys/standard_mixins/highline.rb +34 -41
  38. data/lib/toys/standard_mixins/terminal.rb +72 -26
  39. data/lib/toys/template.rb +51 -35
  40. data/lib/toys/tool.rb +1161 -206
  41. data/lib/toys/utils/completion_engine.rb +171 -0
  42. data/lib/toys/utils/exec.rb +279 -182
  43. data/lib/toys/utils/gems.rb +58 -49
  44. data/lib/toys/utils/help_text.rb +117 -111
  45. data/lib/toys/utils/terminal.rb +69 -62
  46. data/lib/toys/wrappable_string.rb +162 -0
  47. metadata +24 -22
  48. data/lib/toys/definition/acceptor.rb +0 -191
  49. data/lib/toys/definition/alias.rb +0 -112
  50. data/lib/toys/definition/arg.rb +0 -140
  51. data/lib/toys/definition/flag.rb +0 -370
  52. data/lib/toys/definition/flag_group.rb +0 -205
  53. data/lib/toys/definition/source_info.rb +0 -190
  54. data/lib/toys/definition/tool.rb +0 -842
  55. data/lib/toys/dsl/arg.rb +0 -132
  56. data/lib/toys/runner.rb +0 -188
  57. data/lib/toys/standard_middleware.rb +0 -47
  58. data/lib/toys/utils/module_lookup.rb +0 -135
  59. data/lib/toys/utils/wrappable_string.rb +0 -165
@@ -1,32 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2018 Daniel Azuma
3
+ # Copyright 2019 Daniel Azuma
4
4
  #
5
- # All rights reserved.
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
6
11
  #
7
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
9
14
  #
10
- # * Redistributions of source code must retain the above copyright notice,
11
- # this list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the copyright holder, nor the names of any other
16
- # contributors to this software, may be used to endorse or promote products
17
- # derived from this software without specific prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- # POSSIBILITY OF SUCH DAMAGE.
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ # IN THE SOFTWARE.
30
22
  ;
31
23
 
32
24
  module Toys
@@ -52,15 +44,43 @@ module Toys
52
44
  # by `Process#spawn`, and some options supported by {Toys::Utils::Exec}
53
45
  # itself.
54
46
  #
55
- # In addition, this mixin supports one more option,
56
- # `exit_on_nonzero_status`. When set to true, if any subprocess returns a
57
- # nonzero result code, the tool will immediately exit with that same code,
58
- # similar to `set -e` in a bash script.
47
+ # You can set default configuration by passing options to the `include`
48
+ # directive. For example, to log commands at the debug level for all
49
+ # subprocesses spawned by this tool:
50
+ #
51
+ # include :exec, log_level: Logger::DEBUG
52
+ #
53
+ # Two special options are also recognized by the mixin.
54
+ #
55
+ # * A **:result_callback** proc may take a second argument. If it does,
56
+ # the context object is passed as the second argument. This is useful
57
+ # if a `:result_callback` is applied to the entire tool by passing it
58
+ # to the `include` directive. In that case, `self` is not set to the
59
+ # context object as it normally would be in a tool's `run` method, so
60
+ # you cannot access it otherwise. For example, here is how to log the
61
+ # exit code for every subcommand:
62
+ #
63
+ # tool "mytool" do
64
+ # callback = proc do |result, context|
65
+ # context.logger.info "Exit code: #{result.exit_code}"
66
+ # end
67
+ # include :exec, result_callback: callback
68
+ # # ...
69
+ # end
59
70
  #
60
- # You can set initial configuration by passing options to the `include`
61
- # directive. For example:
71
+ # You may also pass a symbol as the `:result_callback`. The method with
72
+ # that name is then called as the callback. The method must take one
73
+ # argument, the result object.
62
74
  #
63
- # include :exec, exit_on_nonzero_status: true
75
+ # * If **:exit_on_nonzero_status** is set to true, a nonzero exit code
76
+ # returned by the subprocess will also cause the tool to exit
77
+ # immediately with that same code.
78
+ #
79
+ # This is particularly useful as an option to the `include` directive,
80
+ # where it causes any subprocess failure to abort the tool, similar to
81
+ # setting `set -e` in a bash script.
82
+ #
83
+ # include :exec, exit_on_nonzero_status: true
64
84
  #
65
85
  module Exec
66
86
  include Mixin
@@ -71,15 +91,16 @@ module Toys
71
91
  #
72
92
  KEY = ::Object.new.freeze
73
93
 
74
- to_initialize do |opts = {}|
75
- tool = self
76
- opts = Exec._setup_exec_opts(opts, tool)
77
- tool[KEY] = Utils::Exec.new(opts) do |k|
94
+ on_initialize do |opts = {}|
95
+ require "toys/utils/exec"
96
+ context = self
97
+ opts = Exec._setup_exec_opts(opts, context)
98
+ context[KEY] = Utils::Exec.new(opts) do |k|
78
99
  case k
79
100
  when :logger
80
- tool[Tool::Keys::LOGGER]
101
+ context[Context::Key::LOGGER]
81
102
  when :cli
82
- tool[Tool::Keys::CLI]
103
+ context[Context::Key::CLI]
83
104
  end
84
105
  end
85
106
  end
@@ -90,10 +111,12 @@ module Toys
90
111
  # All options listed in the {Toys::Utils::Exec} documentation are
91
112
  # supported, plus the `exit_on_nonzero_status` option.
92
113
  #
93
- # @param [Hash] opts The default options.
114
+ # @param opts [Hash] The default options.
115
+ # @return [self]
94
116
  #
95
117
  def configure_exec(opts = {})
96
118
  self[KEY].configure_defaults(Exec._setup_exec_opts(opts, self))
119
+ self
97
120
  end
98
121
 
99
122
  ##
@@ -103,16 +126,17 @@ module Toys
103
126
  # If the process is not set to run in the background, and a block is
104
127
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
105
128
  #
106
- # @param [String,Array<String>] cmd The command to execute.
107
- # @param [Hash] opts The command options. All options listed in the
129
+ # @param cmd [String,Array<String>] The command to execute.
130
+ # @param opts [Hash] The command options. All options listed in the
108
131
  # {Toys::Utils::Exec} documentation are supported, plus the
109
132
  # `exit_on_nonzero_status` option.
110
133
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller for
111
134
  # the subprocess streams.
112
135
  #
113
- # @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
114
- # subprocess controller or result, depending on whether the process
115
- # is running in the background or foreground.
136
+ # @return [Toys::Utils::Exec::Controller] The subprocess controller, if
137
+ # the process is running in the background.
138
+ # @return [Toys::Utils::Exec::Result] The result, if the process ran in
139
+ # the foreground.
116
140
  #
117
141
  def exec(cmd, opts = {}, &block)
118
142
  self[KEY].exec(cmd, Exec._setup_exec_opts(opts, self), &block)
@@ -124,16 +148,17 @@ module Toys
124
148
  # If the process is not set to run in the background, and a block is
125
149
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
126
150
  #
127
- # @param [String,Array<String>] args The arguments to ruby.
128
- # @param [Hash] opts The command options. All options listed in the
151
+ # @param args [String,Array<String>] The arguments to ruby.
152
+ # @param opts [Hash] The command options. All options listed in the
129
153
  # {Toys::Utils::Exec} documentation are supported, plus the
130
154
  # `exit_on_nonzero_status` option.
131
155
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller for
132
156
  # for the subprocess streams.
133
157
  #
134
- # @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
135
- # subprocess controller or result, depending on whether the process
136
- # is running in the background or foreground.
158
+ # @return [Toys::Utils::Exec::Controller] The subprocess controller, if
159
+ # the process is running in the background.
160
+ # @return [Toys::Utils::Exec::Result] The result, if the process ran in
161
+ # the foreground.
137
162
  #
138
163
  def exec_ruby(args, opts = {}, &block)
139
164
  self[KEY].exec_ruby(args, Exec._setup_exec_opts(opts, self), &block)
@@ -146,16 +171,17 @@ module Toys
146
171
  # If the process is not set to run in the background, and a block is
147
172
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
148
173
  #
149
- # @param [Proc] func The proc to call.
150
- # @param [Hash] opts The command options. Most options listed in the
174
+ # @param func [Proc] The proc to call.
175
+ # @param opts [Hash] The command options. Most options listed in the
151
176
  # {Toys::Utils::Exec} documentation are supported, plus the
152
177
  # `exit_on_nonzero_status` option.
153
178
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
154
179
  # for the subprocess streams.
155
180
  #
156
- # @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
157
- # subprocess controller or result, depending on whether the process
158
- # is running in the background or foreground.
181
+ # @return [Toys::Utils::Exec::Controller] The subprocess controller, if
182
+ # the process is running in the background.
183
+ # @return [Toys::Utils::Exec::Result] The result, if the process ran in
184
+ # the foreground.
159
185
  #
160
186
  def exec_proc(func, opts = {}, &block)
161
187
  self[KEY].exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
@@ -168,16 +194,17 @@ module Toys
168
194
  # If the process is not set to run in the background, and a block is
169
195
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
170
196
  #
171
- # @param [String,Array<String>] cmd The tool to execute.
172
- # @param [Hash] opts The command options. Most options listed in the
197
+ # @param cmd [String,Array<String>] The tool to execute.
198
+ # @param opts [Hash] The command options. Most options listed in the
173
199
  # {Toys::Utils::Exec} documentation are supported, plus the
174
200
  # `exit_on_nonzero_status` option.
175
201
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
176
202
  # for the subprocess streams.
177
203
  #
178
- # @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
179
- # subprocess controller or result, depending on whether the process
180
- # is running in the background or foreground.
204
+ # @return [Toys::Utils::Exec::Controller] The subprocess controller, if
205
+ # the process is running in the background.
206
+ # @return [Toys::Utils::Exec::Result] The result, if the process ran in
207
+ # the foreground.
181
208
  #
182
209
  def exec_tool(cmd, opts = {}, &block)
183
210
  func = Exec._make_tool_caller(cmd)
@@ -194,8 +221,8 @@ module Toys
194
221
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
195
222
  # yielded to it.
196
223
  #
197
- # @param [String,Array<String>] cmd The command to execute.
198
- # @param [Hash] opts The command options. All options listed in the
224
+ # @param cmd [String,Array<String>] The command to execute.
225
+ # @param opts [Hash] The command options. All options listed in the
199
226
  # {Toys::Utils::Exec} documentation are supported, plus the
200
227
  # `exit_on_nonzero_status` option.
201
228
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
@@ -216,8 +243,8 @@ module Toys
216
243
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
217
244
  # yielded to it.
218
245
  #
219
- # @param [String,Array<String>] args The arguments to ruby.
220
- # @param [Hash] opts The command options. All options listed in the
246
+ # @param args [String,Array<String>] The arguments to ruby.
247
+ # @param opts [Hash] The command options. All options listed in the
221
248
  # {Toys::Utils::Exec} documentation are supported, plus the
222
249
  # `exit_on_nonzero_status` option.
223
250
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
@@ -238,8 +265,8 @@ module Toys
238
265
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
239
266
  # yielded to it.
240
267
  #
241
- # @param [Proc] func The proc to call.
242
- # @param [Hash] opts The command options. Most options listed in the
268
+ # @param func [Proc] The proc to call.
269
+ # @param opts [Hash] The command options. Most options listed in the
243
270
  # {Toys::Utils::Exec} documentation are supported, plus the
244
271
  # `exit_on_nonzero_status` option.
245
272
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
@@ -261,8 +288,8 @@ module Toys
261
288
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
262
289
  # yielded to it.
263
290
  #
264
- # @param [String,Array<String>] cmd The tool to execute.
265
- # @param [Hash] opts The command options. Most options listed in the
291
+ # @param cmd [String,Array<String>] The tool to execute.
292
+ # @param opts [Hash] The command options. Most options listed in the
266
293
  # {Toys::Utils::Exec} documentation are supported, plus the
267
294
  # `exit_on_nonzero_status` option.
268
295
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
@@ -282,8 +309,8 @@ module Toys
282
309
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
283
310
  # yielded to it.
284
311
  #
285
- # @param [String] cmd The shell command to execute.
286
- # @param [Hash] opts The command options. All options listed in the
312
+ # @param cmd [String] The shell command to execute.
313
+ # @param opts [Hash] The command options. All options listed in the
287
314
  # {Toys::Utils::Exec} documentation are supported, plus the
288
315
  # `exit_on_nonzero_status` option.
289
316
  # @yieldparam controller [Toys::Utils::Exec::Controller] A controller
@@ -298,12 +325,13 @@ module Toys
298
325
  ##
299
326
  # Exit if the given status code is nonzero. Otherwise, returns 0.
300
327
  #
301
- # @param [Integer,Process::Status,Toys::Utils::Exec::Result] status
328
+ # @param status [Integer,Process::Status,Toys::Utils::Exec::Result]
329
+ # @return [Integer]
302
330
  #
303
331
  def exit_on_nonzero_status(status)
304
332
  status = status.exit_code if status.respond_to?(:exit_code)
305
333
  status = status.exitstatus if status.respond_to?(:exitstatus)
306
- Tool.exit(status) unless status.zero?
334
+ Context.exit(status) unless status.zero?
307
335
  0
308
336
  end
309
337
 
@@ -314,14 +342,24 @@ module Toys
314
342
  end
315
343
 
316
344
  ## @private
317
- def self._setup_exec_opts(opts, tool)
318
- return opts unless opts.key?(:exit_on_nonzero_status)
319
- nonzero_status_handler =
320
- if opts[:exit_on_nonzero_status]
321
- proc { |s| tool.exit(s.exitstatus) }
322
- end
323
- opts = opts.merge(nonzero_status_handler: nonzero_status_handler)
324
- opts.delete(:exit_on_nonzero_status)
345
+ def self._setup_exec_opts(opts, context)
346
+ if opts.key?(:exit_on_nonzero_status)
347
+ result_callback =
348
+ if opts[:exit_on_nonzero_status]
349
+ proc { |r| context.exit(r.exit_code) if r.error? }
350
+ end
351
+ opts = opts.merge(result_callback: result_callback)
352
+ opts.delete(:exit_on_nonzero_status)
353
+ elsif opts.key?(:result_callback)
354
+ orig_callback = opts[:result_callback]
355
+ result_callback =
356
+ if orig_callback.is_a?(::Symbol)
357
+ context.method(orig_callback)
358
+ elsif orig_callback.respond_to?(:call)
359
+ proc { |r| orig_callback.call(r, context) }
360
+ end
361
+ opts = opts.merge(result_callback: result_callback)
362
+ end
325
363
  opts
326
364
  end
327
365
  end
@@ -1,32 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2018 Daniel Azuma
3
+ # Copyright 2019 Daniel Azuma
4
4
  #
5
- # All rights reserved.
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
6
11
  #
7
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
9
14
  #
10
- # * Redistributions of source code must retain the above copyright notice,
11
- # this list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the copyright holder, nor the names of any other
16
- # contributors to this software, may be used to endorse or promote products
17
- # derived from this software without specific prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- # POSSIBILITY OF SUCH DAMAGE.
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ # IN THE SOFTWARE.
30
22
  ;
31
23
 
32
24
  require "fileutils"
@@ -1,32 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2018 Daniel Azuma
3
+ # Copyright 2019 Daniel Azuma
4
4
  #
5
- # All rights reserved.
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
6
11
  #
7
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
9
14
  #
10
- # * Redistributions of source code must retain the above copyright notice,
11
- # this list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the copyright holder, nor the names of any other
16
- # contributors to this software, may be used to endorse or promote products
17
- # derived from this software without specific prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- # POSSIBILITY OF SUCH DAMAGE.
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ # IN THE SOFTWARE.
30
22
  ;
31
23
 
32
24
  module Toys
@@ -55,20 +47,26 @@ module Toys
55
47
  module Gems
56
48
  include Mixin
57
49
 
58
- to_include do |opts = {}|
59
- @__gems = Utils::Gems.new(opts)
50
+ on_include do |opts = {}|
51
+ @__gems_opts = opts
60
52
 
53
+ ## @private
61
54
  def self.gems
62
- @__gems
55
+ require "toys/utils/gems"
56
+ # rubocop:disable Naming/MemoizedInstanceVariableName
57
+ @__gems ||= Utils::Gems.new(@__gems_opts)
58
+ # rubocop:enable Naming/MemoizedInstanceVariableName
63
59
  end
64
60
 
61
+ ## @private
65
62
  def self.gem(name, *requirements)
66
63
  gems.activate(name, *requirements)
67
64
  end
68
65
  end
69
66
 
70
67
  ##
71
- # Returns a tool-wide instance of {Toys::Utils::Gems}.
68
+ # A tool-wide instance of {Toys::Utils::Gems}.
69
+ # @return [Toys::Utils::Gems]
72
70
  #
73
71
  def gems
74
72
  self.class.gems
@@ -77,8 +75,9 @@ module Toys
77
75
  ##
78
76
  # Activate the given gem.
79
77
  #
80
- # @param [String] name Name of the gem
81
- # @param [String...] requirements Version requirements
78
+ # @param name [String] Name of the gem
79
+ # @param requirements [String...] Version requirements
80
+ # @return [void]
82
81
  #
83
82
  def gem(name, *requirements)
84
83
  self.class.gems.activate(name, *requirements)