toys 0.14.7 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
data/docs/guide.md CHANGED
@@ -399,10 +399,11 @@ argument is omitted, e.g.
399
399
 
400
400
  Then the option `:whom` is set to the default value `"world"`.
401
401
 
402
- If the option name is a valid method name, Toys will provide a method that you
403
- can use to retrieve the value. In the above example, we retrieve the value for
404
- the option `:whom` by calling the method `whom`. If the option name cannot be
405
- made into a method, you can retrieve the value by calling {Toys::Context#get}.
402
+ If the option name is symbol representing a valid method name (that doesn't
403
+ collide with a method already present), Toys will provide a method that you can
404
+ use to retrieve the value. In the above example, we retrieve the value for the
405
+ option `:whom` by calling the method `whom`. If the option name cannot be made
406
+ into a method, you can retrieve the value by calling {Toys::Context#get}.
406
407
 
407
408
  An argument can also be **required**, which means it must be provided on the
408
409
  command line; otherwise the tool will report a usage error. You can declare a
@@ -418,7 +419,7 @@ first, in order, followed by the optional arguments. For example:
418
419
  required_arg :arg1
419
420
 
420
421
  def run
421
- puts "options data is #{options.inspect}"
422
+ puts "Options data is #{options.inspect}"
422
423
  end
423
424
  end
424
425
 
@@ -457,7 +458,7 @@ not provided on the command line. For example:
457
458
  optional_arg :arg2, default: "the-default"
458
459
 
459
460
  def run
460
- puts "options data is #{options.inspect}"
461
+ puts "Options data is #{options.inspect}"
461
462
  end
462
463
  end
463
464
 
@@ -594,10 +595,12 @@ arguments passed to the tool. In the case above, the `:shout` option is set to
594
595
  it remains falsy. The two flags `-s` and `--shout` are effectively synonyms and
595
596
  have the same effect. A flag declaration can include any number of synonyms.
596
597
 
597
- As with arguments, Toys will provide a method that you can call to retrieve the
598
- option value set by a flag. In this case, a method called `shout` will be
599
- available, and will return either true or false. If the option name cannot be
600
- made into a method, you can retrieve the value by calling {Toys::Context#get}.
598
+ As with arguments, Toys can provide a method that you can call to retrieve the
599
+ option value set by a flag. This method is provided if the flag name is a
600
+ symbol representing a valid method name that does not collide with a method
601
+ already present. In our example, Toys provides a method called `shout` that
602
+ returns either true or false. If the option name cannot be made into a method,
603
+ you can retrieve the value by calling {Toys::Context#get}.
601
604
 
602
605
  #### Flag types
603
606
 
@@ -820,10 +823,11 @@ like this:
820
823
  default: 0,
821
824
  handler: proc { |_val, prev| prev - 1 }
822
825
 
823
- Note that both flags affect the same option name, `VERBOSITY`. The first
824
- increments it each time it appears, and the second decrements it. A tool can
825
- query this option and get an integer telling the requested verbosity level, as
826
- you will see [below](#Logging_and_verbosity).
826
+ Note that both flags affect the same option name,
827
+ {Toys::Context::Key::VERBOSITY}. The first increments it each time it appears,
828
+ and the second decrements it. A tool can query this option and get an integer
829
+ telling the requested verbosity level, as you will see
830
+ [below](#Logging_and_verbosity).
827
831
 
828
832
  Toys provides a few built-in handlers that can be specified by name. We already
829
833
  discussed the default handler that can be specified by its name `:set` or by
@@ -1400,6 +1404,10 @@ chance of problems, if you need to use `truncate_load_path!`, locate it as
1400
1404
  early as possible in your Toys files, typically at the top of the
1401
1405
  [index file](#Index_files).
1402
1406
 
1407
+ ### Loading remote files
1408
+
1409
+ (TODO)
1410
+
1403
1411
  ## The execution environment
1404
1412
 
1405
1413
  This section describes the context and resources available to your tool when it
@@ -1871,8 +1879,11 @@ Following is a simple template example:
1871
1879
  on_expand do |template|
1872
1880
  tool template.name do
1873
1881
  desc "A greeting tool generated from a template"
1874
- to_run do
1875
- puts "Hello, #{template.whom}!"
1882
+
1883
+ static :whom, template.whom
1884
+
1885
+ def run
1886
+ puts "Hello, #{whom}!"
1876
1887
  end
1877
1888
  end
1878
1889
  end
@@ -1893,15 +1904,12 @@ passed to the block, so it can access the template configuration when
1893
1904
  generating directives. The "greet" template in the above example generates a
1894
1905
  tool whose name is set by the template's `name` property.
1895
1906
 
1896
- Notice that in the above example, we used `to_run do`, providing a *block* for
1897
- the tool's execution, rather than `def run`, providing a method. Both forms are
1898
- valid and will work in a template (as well as in a normal Toys file), but the
1899
- block form is often useful in a template because you can access the `template`
1900
- variable inside the block, whereas it would not be accessible if you defined a
1901
- method. Similarly, if your template generates helper methods, and the body of
1902
- those methods need access to the `template` variable, you can use
1903
- [Module#define_method](http://ruby-doc.org/core/Module.html#method-i-define_method)
1904
- instead of `def`.
1907
+ Notice in the above example, we used the {Toys::DSL::Tool#static} directive to
1908
+ create a "static" option for `template.whom`. A "static" option is an option
1909
+ whose value is set directly in code rather than via a flag or argument. We use
1910
+ it here because we can't access the `template` local variable from within the
1911
+ `run` method. Static options are a common technique for accessing template
1912
+ configuration properties from inside tool methods.
1905
1913
 
1906
1914
  By convention, it is a good idea for configuration options for your template to
1907
1915
  be settable *both* as arguments to the constructor, *and* as `attr_accessor`
@@ -1927,8 +1935,9 @@ class by including the {Toys::Template} module in your class definition.
1927
1935
  on_expand do |template|
1928
1936
  tool template.name do
1929
1937
  desc "A greeting tool generated from a template"
1930
- to_run do
1931
- puts "Hello, #{template.whom}!"
1938
+ static :whom, template.whom
1939
+ def run
1940
+ puts "Hello, #{whom}!"
1932
1941
  end
1933
1942
  end
1934
1943
  end
@@ -3045,9 +3054,9 @@ themselves.
3045
3054
 
3046
3055
  # This file is .toys.rb
3047
3056
 
3048
- # A "clean" tool that cleans out gem builds (from the pkg directory), and
3049
- # documentation builds (from doc and .yardoc)
3050
- expand :clean, paths: ["pkg", "doc", ".yardoc"]
3057
+ # A "clean" tool that cleans out anything matched by the gitignore. You can
3058
+ # also configure it to clean specific files and directories.
3059
+ expand :clean, paths: :gitignore
3051
3060
 
3052
3061
  # This is the "test" tool.
3053
3062
  expand :minitest, libs: ["lib", "test"]
@@ -3397,44 +3406,49 @@ Here is an example that wraps calls to git:
3397
3406
  end
3398
3407
  end
3399
3408
 
3400
- ### Handling interrupts
3409
+ ### Handling signals
3401
3410
 
3402
- If you interrupt a running tool, say, by hitting `CTRL`-`C`, Toys will normally
3403
- terminate execution and display the message `INTERRUPTED` on the standard error
3404
- stream.
3411
+ If you interrupt a running tool by hitting `CTRL`-`C` or sending it a signal,
3412
+ Toys will normally terminate execution and display the message `INTERRUPTED` on
3413
+ the standard error stream.
3405
3414
 
3406
- If your tool needs to handle interrupts itself, you have several options. You
3407
- can rescue the `Interrupt` exception or call `Signal.trap`. Or you can provide
3408
- an *interrupt handler* in your tool using the `on_interrupt` directive. This
3409
- directive either provides a block to handle interrupts, or designates a named
3410
- method as the handler. If an interrupt handler is present, Toys will handle
3411
- interrupts as follows:
3415
+ If your tool needs to handle signals or inerrupts itself, you have several
3416
+ options. You can rescue the `SignalException` or call `Signal.trap`. Or you can
3417
+ provide a *signal handler* in your tool using the `on_signal` or `on_interrupt`
3418
+ directive. These directives either provide a block or designate a named method
3419
+ to handle a given signal received by the process. A separate handler must be
3420
+ provided for each signal type. (The `on_interrupt` directive is simply
3421
+ shorthand for registering a handler for `SIGINT`.)
3412
3422
 
3413
- 1. Toys will terminate the tool's `run` method by raising an `Interrupt`
3414
- exception. Any `ensure` blocks will be called.
3415
- 2. Toys will call the interrupt handler. If this method or block takes an
3416
- argument, Toys will pass it the `Interrupt` exception object.
3417
- 3. The interrupt handler is then responsible for tool execution from that
3423
+ If a signal or interrupt is received and is not caught via `Signal.trap`, the
3424
+ following takes place:
3425
+
3426
+ 1. Ruby will terminate the tool's `run` method by raising a `SignalException`
3427
+ Any `ensure` blocks in the tool will be called.
3428
+ 2. Toys will call the signal handler, either a method or a block. If the
3429
+ handler takes an argument, Toys will pass it the `SignalException` object.
3430
+ 3. The signal handler is then responsible for tool execution from that
3418
3431
  point. It can terminate execution by returning or calling `exit`, or it can
3419
3432
  restart or resume processing (perhaps by calling the `run` method again).
3420
- Or it can invoke the normal Toys interrupt handling (i.e. terminating
3421
- execution, displaying the message `INTERRUPTED`) by re-raising *the same*
3422
- interrupt exception object.
3423
- 4. If another interrupt takes place during the execution of the interrupt
3424
- handler, Toys will terminate it by raising a *second* `Interrupt` exception
3425
- (calling any `ensure` blocks). Then, the interrupt handler will be called
3426
- *again* and passed the new exception. Any additional interrupts will be
3427
- handled similarly.
3428
-
3429
- Because the interrupt handler is called again even if it is itself interrupted,
3430
- you might consider detecting this case if your interrupt handler might be
3431
- long-running. You can tell how many interrupts have taken place by looking at
3432
- the `Exception#cause` property of the exception. The first interrupt will have
3433
- a cause of `nil`. The second interrupt (i.e. the interrupt raised the first
3434
- time the interrupt handler is itself interrupted) will have its cause point to
3435
- the first interrupt (which in turn has a `nil` cause.) The third interrupt's
3436
- cause will point to the second interrupt, and so on. So you can determine the
3437
- interrupt "depth" by counting the length of the cause chain.
3433
+ Or it can invoke the normal Toys signal handling (i.e. terminating
3434
+ execution and displaying the message `INTERRUPTED` or `SIGNAL RECEIVED`) by
3435
+ re-raising *the same* `SignalException` object.
3436
+ 4. If another signal is received or interrupt takes place during the execution
3437
+ of the handler, Toys will terminate the handler by raising a *second*
3438
+ `SignalException` (again calling any `ensure` blocks). Then, any matching
3439
+ signal handler will be called *again* for the new signal and passed the new
3440
+ exception. Any further signals will be handled similarly.
3441
+
3442
+ It is possible for a signal handler itself to receive signals. For example, if
3443
+ you have a long-running `CTRL`-`C` interrupt handler, it itself could get
3444
+ interrupted. You can tell how many signals have taken place by looking at the
3445
+ `Exception#cause` property of the `SignalException`. The first signal will have
3446
+ a cause of `nil`. The second signal (i.e. the first time a signal handler
3447
+ itself receives a signal) will have a cause pointing to the first
3448
+ `SignalException` (which in turn has a `nil` cause). The third signal's cause
3449
+ points at the second, and so forth. Hence, you can determine the signal "depth"
3450
+ by counting the length of the cause chain, which could be important to prevent
3451
+ "infinite" signals.
3438
3452
 
3439
3453
  Here is an example that performs a long-running task. The first two times the
3440
3454
  task is interrupted, it is restarted. The third time, it is terminated.
@@ -3496,6 +3510,81 @@ failed.
3496
3510
  end
3497
3511
  end
3498
3512
 
3513
+ ### Changing the entrypoint
3514
+
3515
+ The normal entrypoint for a tool is the `run` method. However, you can change
3516
+ it using the {Toys::DSL::Tool#to_run} directive, providing either a different
3517
+ method name as a symbol, or a block that will be called instead of a method to
3518
+ run the tool.
3519
+
3520
+ One reason to change which method is called, is if you need to modify a tool
3521
+ that was already defined by some other means (like a template expansion). For
3522
+ example, the tests for the Toys gems include a number of longer-running
3523
+ "integration" tests that run only when the `TOYS_TEST_INTEGRATION` environment
3524
+ variable is set. The Toys gems provide standard `test` tools using the
3525
+ `:minitest` template, but then modify those tools to add an `--integration`
3526
+ flag. When this flag is set, the `TOYS_TEST_INTEGRATION` environment variable
3527
+ gets set, causing the integration tests to run. Here's what that looks like:
3528
+
3529
+ # Use the minitest template to generate the normal test tool with the
3530
+ # normal "run" method as the entrypoint
3531
+ expand :minitest, libs: ["lib", "test"], bundler: true
3532
+
3533
+ # Reopen the "test" tool generated above
3534
+ tool "test" do
3535
+ # Add a flag to the tool
3536
+ flag :integration
3537
+
3538
+ # Create a new run method that "wraps" the existing one
3539
+ def run_with_integration
3540
+ # First set the environment variable to activate integration tests
3541
+ # if requested
3542
+ ENV["TOYS_TEST_INTEGRATION"] = "true" if integration
3543
+
3544
+ # Invoke the original run method that was defined in the template
3545
+ run
3546
+ end
3547
+
3548
+ # Now set the entrypoint to our new method
3549
+ to_run :run_with_integration
3550
+ end
3551
+
3552
+ Passing a block to {Toys::DSL::Tool#to_run} is less common. One reason you
3553
+ might do it is if you need to access variables from an outer scope. (Normally,
3554
+ defining a method isolates your variables from any enclosing scopes.) Here is
3555
+ an example that prints out the time that the tool was *defined* (rather than
3556
+ executed).
3557
+
3558
+ tool "def-time" do
3559
+ # Grab the time during tool definition
3560
+ time = Time.now
3561
+
3562
+ # Define the entrypoint using a block rather than a method.
3563
+ # The block is still called in the same object context, but now has
3564
+ # access to variables from enclosing scopes.
3565
+ to_run do
3566
+ puts "Defined at #{time}"
3567
+ end
3568
+ end
3569
+
3570
+ The downside of this technique is that the entrypoint is not a method, and
3571
+ can't be called like one. Which means, among other things, you can't "wrap" it
3572
+ like we did with the test tool above.
3573
+
3574
+ If you need to access information from enclosing scopes, consider instead
3575
+ setting options using the {Toys::DSL::Tool#static} directive, as illustrated
3576
+ earlier when we discussed [defining templates](#Defining_templates).
3577
+
3578
+ tool "def-time" do
3579
+ # Grab the time during tool definition and set it as a static option.
3580
+ static :time, Time.now
3581
+
3582
+ # Now you can access it from a run method like any other option
3583
+ def run
3584
+ puts "Defined at #{time}"
3585
+ end
3586
+ end
3587
+
3499
3588
  ### Data files
3500
3589
 
3501
3590
  If your tools require images, archives, keys, or other such static data, Toys
@@ -3,7 +3,19 @@
3
3
  module Toys
4
4
  ##
5
5
  # Subclass of `Toys::CLI` configured for the behavior of the standard Toys
6
- # executable.
6
+ # executable. Specifically, this subclass:
7
+ #
8
+ # * Configures the standard names of files and directories, such as the
9
+ # `.toys.rb` file for an "index" tool, and the `.data` and `.lib` directory
10
+ # names.
11
+ # * Configures default descriptions for the root tool.
12
+ # * Configures a default error handler and logger that provide ANSI-colored
13
+ # formatted output.
14
+ # * Configures a set of middleware that implement online help, verbosity
15
+ # flags, and other features.
16
+ # * Provides a set of standard templates for typical project build and
17
+ # maintenance scripts (suh as clean, test, and rubocop).
18
+ # * Finds tool definitions in the standard Toys search path.
7
19
  #
8
20
  class StandardCLI < CLI
9
21
  ##
@@ -103,6 +115,8 @@ module Toys
103
115
  def initialize(custom_paths: nil,
104
116
  include_builtins: true,
105
117
  cur_dir: nil)
118
+ require "toys/utils/standard_ui"
119
+ ui = Toys::Utils::StandardUI.new
106
120
  super(
107
121
  executable_name: EXECUTABLE_NAME,
108
122
  config_dir_name: CONFIG_DIR_NAME,
@@ -114,7 +128,8 @@ module Toys
114
128
  lib_dir_name: LIB_DIR_NAME,
115
129
  extra_delimiters: EXTRA_DELIMITERS,
116
130
  middleware_stack: default_middleware_stack,
117
- template_lookup: default_template_lookup
131
+ template_lookup: default_template_lookup,
132
+ **ui.cli_args
118
133
  )
119
134
  if custom_paths
120
135
  Array(custom_paths).each { |path| add_config_path(path) }
@@ -237,15 +237,21 @@ module Toys
237
237
  end
238
238
  end
239
239
 
240
+ static :gem_name, template.gem_name(context_directory || ::Dir.getwd)
241
+ static :install_gem, template.install_gem
242
+ static :push_gem, template.push_gem
243
+ static :tag, template.tag
244
+ static :push_tag, template.push_tag
245
+
240
246
  include :exec, exit_on_nonzero_status: true
241
247
  include :fileutils
242
248
  include :terminal
243
249
 
244
- to_run do
250
+ # @private
251
+ def run # rubocop:disable all
245
252
  require "rubygems"
246
253
  require "rubygems/package"
247
254
  ::Dir.chdir(context_directory || ::Dir.getwd) do
248
- gem_name = template.gem_name
249
255
  gemspec = ::Gem::Specification.load("#{gem_name}.gemspec")
250
256
  ::Gem::Package.build(gemspec)
251
257
  version = gemspec.version
@@ -255,21 +261,21 @@ module Toys
255
261
  mkdir_p(::File.dirname(archive_path))
256
262
  mv(archive_name, archive_path)
257
263
  end
258
- if template.install_gem
264
+ if install_gem
259
265
  exit(1) unless yes || confirm("Install #{gem_name} #{version}? ", default: true)
260
266
  exec ["gem", "install", archive_path]
261
267
  end
262
- if template.push_gem
268
+ if push_gem
263
269
  if ::File.directory?(".git") && capture("git status -s").strip != ""
264
270
  logger.error "Cannot push the gem when there are uncommited changes"
265
271
  exit(1)
266
272
  end
267
273
  exit(1) unless yes || confirm("Release #{gem_name} #{version}? ", default: true)
268
274
  exec(["gem", "push", archive_path])
269
- if template.tag
275
+ if tag
270
276
  exec(["git", "tag", "v#{version}"])
271
- if template.push_tag
272
- exec(["git", "push", template.push_tag, "v#{version}"])
277
+ if push_tag
278
+ exec(["git", "push", push_tag, "v#{version}"])
273
279
  end
274
280
  end
275
281
  end
@@ -55,6 +55,10 @@ module Toys
55
55
  # enabled. See the documentation for the
56
56
  # [bundler mixin](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Bundler)
57
57
  # for information on available options.
58
+ # @param mt_compat [boolean] If set to `true` or `false`, sets the
59
+ # `MT_COMPAT` environment variable accordingly. This may be required
60
+ # for certain older Minitest plugins. Optional. If not present, keeps
61
+ # any current setting.
58
62
  # @param context_directory [String] A custom context directory to use
59
63
  # when executing this tool.
60
64
  #
@@ -66,6 +70,7 @@ module Toys
66
70
  verbose: false,
67
71
  warnings: true,
68
72
  bundler: false,
73
+ mt_compat: nil,
69
74
  context_directory: nil)
70
75
  @name = name
71
76
  @gem_version = gem_version
@@ -75,6 +80,7 @@ module Toys
75
80
  @verbose = verbose
76
81
  @warnings = warnings
77
82
  @bundler = bundler
83
+ @mt_compat = mt_compat
78
84
  @context_directory = context_directory
79
85
  end
80
86
 
@@ -160,6 +166,18 @@ module Toys
160
166
  #
161
167
  attr_writer :bundler
162
168
 
169
+ ##
170
+ # Adjust the `MT_COMPAT` environment variable when running tests. This
171
+ # setting may be necessary for certain older Minitest plugins.
172
+ #
173
+ # Pass `true` to enable compat mode, `false` to disable it, or `nil` to
174
+ # use any ambient setting from the current environment.
175
+ #
176
+ # @param value [true,false,nil]
177
+ # @return [true,false,nil]
178
+ #
179
+ attr_writer :mt_compat
180
+
163
181
  ##
164
182
  # Use bundler for this tool.
165
183
  #
@@ -195,6 +213,11 @@ module Toys
195
213
  #
196
214
  attr_reader :context_directory
197
215
 
216
+ ##
217
+ # @private
218
+ #
219
+ attr_reader :mt_compat
220
+
198
221
  ##
199
222
  # @private
200
223
  #
@@ -261,35 +284,42 @@ module Toys
261
284
  complete: :file_system,
262
285
  desc: "Paths to the tests to run (defaults to all tests)"
263
286
 
264
- to_run do
265
- gem "minitest", *template.gem_version
287
+ static :gem_version, template.gem_version
288
+ static :libs, template.libs
289
+ static :files, template.files
290
+ static :template_verbose, template.verbose
291
+ static :mt_compat, template.mt_compat
292
+
293
+ # @private
294
+ def run # rubocop:disable all
295
+ gem "minitest", *gem_version
266
296
 
267
297
  ::Dir.chdir(context_directory || ::Dir.getwd) do
268
298
  ruby_args = []
269
- libs = Array(template.libs)
270
299
  ruby_args << "-I#{libs.join(::File::PATH_SEPARATOR)}" unless libs.empty?
271
300
  ruby_args << "-w" if warnings
272
- ruby_args << "-"
273
- ruby_args << "--seed" << seed if seed
274
- vv = verbosity
275
- vv += 1 if template.verbose
276
- ruby_args << "--verbose" if vv.positive?
277
- ruby_args << "--name" << name if name
278
- ruby_args << "--exclude" << exclude if exclude
279
301
 
280
302
  if tests.empty?
281
- Array(template.files).each do |pattern|
303
+ files.each do |pattern|
282
304
  tests.concat(::Dir.glob(pattern))
283
305
  end
284
306
  tests.uniq!
285
307
  end
308
+ code = ["require 'minitest/autorun'"] + tests.map { |file| "load '#{file}'" }
309
+ ruby_args << "-e" << code.join("\n")
286
310
 
287
- result = exec_ruby(ruby_args, in: :controller) do |controller|
288
- controller.in.puts("require 'minitest/autorun'")
289
- tests.each do |file|
290
- controller.in.puts("load '#{file}'")
291
- end
292
- end
311
+ ruby_args << "--"
312
+ ruby_args << "--seed" << seed if seed
313
+ vv = verbosity
314
+ vv += 1 if template_verbose
315
+ ruby_args << "--verbose" if vv.positive?
316
+ ruby_args << "--name" << name if name
317
+ ruby_args << "--exclude" << exclude if exclude
318
+
319
+ env = {}
320
+ env["MT_COMPAT"] = mt_compat ? "true" : nil unless mt_compat.nil?
321
+
322
+ result = exec_ruby(ruby_args, env: env)
293
323
  if result.error?
294
324
  logger.error("Minitest failed!")
295
325
  exit(result.exit_code)
@@ -163,31 +163,41 @@ module Toys
163
163
  on_expand do |template|
164
164
  gem "rake", *template.gem_version
165
165
  require "rake"
166
- rakefile_path = Templates::Rake.find_rakefile(
166
+
167
+ rakefile_path = ::Toys::Templates::Rake.find_rakefile(
167
168
  template.rakefile_path, template.context_directory || context_directory
168
169
  )
169
170
  raise "Cannot find #{template.rakefile_path}" unless rakefile_path
170
- context_dir = ::File.dirname(rakefile_path)
171
- rake = Templates::Rake.prepare_rake(rakefile_path, context_dir)
171
+ rake_context_dir = ::File.dirname(rakefile_path)
172
+ rake = ::Toys::Templates::Rake.prepare_rake(rakefile_path, rake_context_dir)
173
+
172
174
  rake.tasks.each do |task|
173
175
  comments = task.full_comment.to_s.split("\n")
174
176
  next if comments.empty? && template.only_described
177
+
175
178
  tool(task.name.split(":"), if_defined: :ignore) do
179
+ static :task, task
180
+ static :rake_context_dir, rake_context_dir
181
+
176
182
  bundler_settings = template.bundler_settings
177
183
  include :bundler, **bundler_settings if bundler_settings
184
+
178
185
  unless comments.empty?
179
186
  desc(comments.first)
180
187
  comments << "" << "Defined as a Rake task in #{rakefile_path}"
181
188
  long_desc(*comments)
182
189
  end
190
+
183
191
  if template.use_flags
184
192
  task.arg_names.each do |arg|
185
- specs = Templates::Rake.flag_specs(arg)
193
+ specs = ::Toys::Templates::Rake.flag_specs(arg)
186
194
  flag(arg, *specs) unless specs.empty?
187
195
  end
188
- to_run do
196
+
197
+ # @private
198
+ def run
189
199
  args = task.arg_names.map { |arg| self[arg] }
190
- ::Dir.chdir(context_dir) do
200
+ ::Dir.chdir(rake_context_dir) do
191
201
  task.invoke(*args)
192
202
  end
193
203
  end
@@ -195,8 +205,10 @@ module Toys
195
205
  task.arg_names.each do |arg|
196
206
  optional_arg(arg)
197
207
  end
198
- to_run do
199
- ::Dir.chdir(context_dir) do
208
+
209
+ # @private
210
+ def run
211
+ ::Dir.chdir(rake_context_dir) do
200
212
  task.invoke(*args)
201
213
  end
202
214
  end
@@ -297,36 +297,47 @@ module Toys
297
297
 
298
298
  set_context_directory template.context_directory if template.context_directory
299
299
 
300
+ static :gem_version, template.gem_version
301
+ static :template_files, template.files
302
+ static :rdoc_options, template.options
303
+ static :output_dir, template.output_dir
304
+ static :rdoc_markup, template.markup
305
+ static :rdoc_main, template.main
306
+ static :rdoc_title, template.title
307
+ static :rdoc_template, template.template
308
+ static :rdoc_generator, template.generator
309
+
300
310
  include :exec, exit_on_nonzero_status: true
301
311
  include :gems
302
312
 
303
313
  bundler_settings = template.bundler_settings
304
314
  include :bundler, **bundler_settings if bundler_settings
305
315
 
306
- to_run do
307
- gem_requirements = template.gem_version
308
- gem "rdoc", *gem_requirements
316
+ # @private
317
+ def run # rubocop:disable all
318
+ gem "rdoc", *gem_version
309
319
 
310
320
  ::Dir.chdir(context_directory || ::Dir.getwd) do
311
321
  files = []
312
- template.files.each do |pattern|
322
+ template_files.each do |pattern|
313
323
  files.concat(::Dir.glob(pattern))
314
324
  end
315
325
  files.uniq!
316
326
 
317
- args = template.options.dup
318
- args << "-o" << template.output_dir
319
- args << "--markup" << template.markup if template.markup
320
- args << "--main" << template.main if template.main
321
- args << "--title" << template.title if template.title
322
- args << "-T" << template.template if template.template
323
- args << "-f" << template.generator if template.generator
324
-
325
- exec_ruby([], in: :controller) do |controller|
326
- controller.in.puts("gem 'rdoc', *#{gem_requirements.inspect}")
327
- controller.in.puts("require 'rdoc'")
328
- controller.in.puts("::RDoc::RDoc.new.document(#{(args + files).inspect})")
329
- end
327
+ args = rdoc_options.dup
328
+ args << "-o" << output_dir
329
+ args << "--markup" << rdoc_markup if rdoc_markup
330
+ args << "--main" << rdoc_main if rdoc_main
331
+ args << "--title" << rdoc_title if rdoc_title
332
+ args << "-T" << rdoc_template if rdoc_template
333
+ args << "-f" << rdoc_generator if rdoc_generator
334
+
335
+ code = <<~CODE
336
+ gem 'rdoc', *#{gem_version.inspect}
337
+ require 'rdoc'
338
+ ::RDoc::RDoc.new.document(#{(args + files).inspect})
339
+ CODE
340
+ exec_ruby(["-e", code])
330
341
  end
331
342
  end
332
343
  end