toys-core 0.11.2 → 0.12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -1
- data/README.md +1 -1
- data/lib/toys-core.rb +4 -1
- data/lib/toys/acceptor.rb +3 -3
- data/lib/toys/arg_parser.rb +6 -7
- data/lib/toys/cli.rb +44 -14
- data/lib/toys/compat.rb +19 -22
- data/lib/toys/completion.rb +3 -1
- data/lib/toys/context.rb +2 -2
- data/lib/toys/core.rb +1 -1
- data/lib/toys/dsl/base.rb +85 -0
- data/lib/toys/dsl/flag.rb +3 -3
- data/lib/toys/dsl/flag_group.rb +7 -7
- data/lib/toys/dsl/internal.rb +206 -0
- data/lib/toys/dsl/positional_arg.rb +3 -3
- data/lib/toys/dsl/tool.rb +174 -216
- data/lib/toys/errors.rb +1 -0
- data/lib/toys/flag.rb +15 -18
- data/lib/toys/flag_group.rb +5 -4
- data/lib/toys/input_file.rb +4 -4
- data/lib/toys/loader.rb +189 -50
- data/lib/toys/middleware.rb +1 -1
- data/lib/toys/mixin.rb +2 -2
- data/lib/toys/positional_arg.rb +3 -3
- data/lib/toys/settings.rb +900 -0
- data/lib/toys/source_info.rb +121 -18
- data/lib/toys/standard_middleware/apply_config.rb +5 -4
- data/lib/toys/standard_middleware/set_default_descriptions.rb +18 -18
- data/lib/toys/standard_middleware/show_help.rb +17 -5
- data/lib/toys/standard_mixins/bundler.rb +5 -1
- data/lib/toys/standard_mixins/exec.rb +22 -15
- data/lib/toys/standard_mixins/git_cache.rb +48 -0
- data/lib/toys/standard_mixins/xdg.rb +56 -0
- data/lib/toys/template.rb +2 -2
- data/lib/toys/{tool.rb → tool_definition.rb} +100 -41
- data/lib/toys/utils/exec.rb +37 -16
- data/lib/toys/utils/gems.rb +48 -14
- data/lib/toys/utils/git_cache.rb +184 -0
- data/lib/toys/utils/help_text.rb +90 -34
- data/lib/toys/utils/terminal.rb +1 -1
- data/lib/toys/utils/xdg.rb +293 -0
- metadata +15 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e6f3ce99b43220466c4b43842c1fa78d3cfca815ecc559be749518d26156be9
|
4
|
+
data.tar.gz: 8a3dbb068001b3a52d5b070ae0f8652aeea5f1763ae19a938aa84da693023c2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de8dc024af7e706749b65a8e2b4fe9430e380b58add4bc9b643bc357dce7d5a5109057a2aaccdbfb657410def1372494b020cab59b1ebd03de83d2359a0746ab
|
7
|
+
data.tar.gz: 96b6ca463c27eff9fe403d365afe15a6d4c75bed057b8dc162b40c696b0f31606738197c5bdb68ed759d9c0a0f29af0e4ddd4aed929e41649cb6a46b67909ea8
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,53 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### v0.12.0 / 2021-08-05
|
4
|
+
|
5
|
+
Toys-Core 0.12.0 is a major release with significant new features and bug fixes, and a few breaking interface changes. Additionally, this release now requires Ruby 2.4 or later.
|
6
|
+
|
7
|
+
Breaking interface changes:
|
8
|
+
|
9
|
+
* The Toys::Tool class has been renamed Toys::ToolDefinition so that the old name can be used for class-based tool definition.
|
10
|
+
* Tool definition now raises ToolDefinitionError if whitespace, control characters, or certain punctuation are used in a tool name.
|
11
|
+
* Toys::Loader#add_path no longer supports multiple paths. Use add_path_set instead.
|
12
|
+
* The "name" argument was renamed to "source_name" in Toys::Loader#add_block and Toys::CLI#add_config_block
|
13
|
+
|
14
|
+
New functionality:
|
15
|
+
|
16
|
+
* The DSL now supports a class-based tool definition syntax (in addition to the existing block-based syntax). Some users may prefer this new class-based style as more Ruby-like.
|
17
|
+
* You can now load tools from a remote git repository using the load_git directive.
|
18
|
+
* Whitespace is now automatically considered a name delimiter when defining tools.
|
19
|
+
* There is now an extensible settings mechanism to activate less-common tool behavior. Currently there is one setting, which causes subtools to inherit their parent's methods by default.
|
20
|
+
* The load directive can load into a new tool.
|
21
|
+
* Added a new utility class and mixin that provides XDG Base Directory information.
|
22
|
+
* Added a new utility class and mixin that provides cached access to remote git repos.
|
23
|
+
* The help text generator now supports splitting the subtool list by source.
|
24
|
+
* Loader and CLI methods that add tool configs now uniformly provide optional source_name and context_directory arguments.
|
25
|
+
* Toys::SourceInfo now supports getting the root ancestor and priority of a source.
|
26
|
+
* Toys::ToolDefinition now has a direct accessor for the source root. This is always set for a tool, even if it isn't marked as finished.
|
27
|
+
|
28
|
+
Fixes:
|
29
|
+
|
30
|
+
* Fixed some bundler integration issues that occurred when the bundle is being installed in a separate path such as a vendor directory.
|
31
|
+
* Toys::ContextualError now includes the full backtrace of the cause.
|
32
|
+
* Cleaned up some unused memory objects during tool loading and lookup.
|
33
|
+
|
34
|
+
### v0.11.5 / 2021-03-28
|
35
|
+
|
36
|
+
* BREAKING CHANGE: The exit_on_nonzero_status option to exec now exits on signals and failures to spawn, in addition to error codes.
|
37
|
+
* ADDED: Support retries in the bundler integration.
|
38
|
+
* FIXED: Fix a bundler 2.2 integration issue that fails install in certain cases when an update is needed.
|
39
|
+
|
40
|
+
### v0.11.4 / 2020-10-11
|
41
|
+
|
42
|
+
* FIXED: Doesn't modify bundler lockfiles when adding Toys to a bundle
|
43
|
+
|
44
|
+
### v0.11.3 / 2020-09-13
|
45
|
+
|
46
|
+
* FIXED: The Exec library recognizes the argv0 option, and logs it appropriately
|
47
|
+
|
3
48
|
### v0.11.2 / 2020-09-06
|
4
49
|
|
5
|
-
* FIXED: Fix a JRuby-specific race condition when capturing exec streams
|
50
|
+
* FIXED: Fix a JRuby-specific race condition when capturing exec streams
|
6
51
|
|
7
52
|
### v0.11.1 / 2020-08-24
|
8
53
|
|
data/README.md
CHANGED
@@ -34,7 +34,7 @@ Install the **toys-core** gem using:
|
|
34
34
|
You may also install the **toys** gem, which brings in **toys-core** as a
|
35
35
|
dependency.
|
36
36
|
|
37
|
-
Toys-Core requires Ruby 2.
|
37
|
+
Toys-Core requires Ruby 2.4 or later.
|
38
38
|
|
39
39
|
Most parts of Toys-Core work on JRuby. However, JRuby is not recommended
|
40
40
|
because of JVM boot latency, lack of support for Kernel#fork, and other issues.
|
data/lib/toys-core.rb
CHANGED
@@ -70,8 +70,10 @@ require "toys/compat"
|
|
70
70
|
require "toys/completion"
|
71
71
|
require "toys/context"
|
72
72
|
require "toys/core"
|
73
|
+
require "toys/dsl/base"
|
73
74
|
require "toys/dsl/flag"
|
74
75
|
require "toys/dsl/flag_group"
|
76
|
+
require "toys/dsl/internal"
|
75
77
|
require "toys/dsl/positional_arg"
|
76
78
|
require "toys/dsl/tool"
|
77
79
|
require "toys/errors"
|
@@ -83,7 +85,8 @@ require "toys/middleware"
|
|
83
85
|
require "toys/mixin"
|
84
86
|
require "toys/module_lookup"
|
85
87
|
require "toys/positional_arg"
|
88
|
+
require "toys/settings"
|
86
89
|
require "toys/source_info"
|
87
90
|
require "toys/template"
|
88
|
-
require "toys/
|
91
|
+
require "toys/tool_definition"
|
89
92
|
require "toys/wrappable_string"
|
data/lib/toys/acceptor.rb
CHANGED
@@ -602,11 +602,11 @@ module Toys
|
|
602
602
|
Simple.new(type_desc: "boolean", well_known_spec: spec) do |s|
|
603
603
|
if s.nil?
|
604
604
|
default
|
605
|
+
elsif s.empty?
|
606
|
+
REJECT
|
605
607
|
else
|
606
608
|
s = s.downcase
|
607
|
-
if
|
608
|
-
REJECT
|
609
|
-
elsif TRUE_STRINGS.any? { |t| t.start_with?(s) }
|
609
|
+
if TRUE_STRINGS.any? { |t| t.start_with?(s) }
|
610
610
|
true
|
611
611
|
elsif FALSE_STRINGS.any? { |f| f.start_with?(s) }
|
612
612
|
false
|
data/lib/toys/arg_parser.rb
CHANGED
@@ -261,7 +261,7 @@ module Toys
|
|
261
261
|
# @param message [String] The message. Required.
|
262
262
|
#
|
263
263
|
def initialize(message)
|
264
|
-
super(message)
|
264
|
+
super(message, name: nil)
|
265
265
|
end
|
266
266
|
end
|
267
267
|
|
@@ -269,7 +269,7 @@ module Toys
|
|
269
269
|
# Create an argument parser for a particular tool.
|
270
270
|
#
|
271
271
|
# @param cli [Toys::CLI] The CLI in effect.
|
272
|
-
# @param tool [Toys::
|
272
|
+
# @param tool [Toys::ToolDefinition] The tool defining the argument format.
|
273
273
|
# @param default_data [Hash] Additional initial data (such as verbosity).
|
274
274
|
# @param require_exact_flag_match [Boolean] Whether to require flag matches
|
275
275
|
# be exact (not partial). Default is false.
|
@@ -295,7 +295,7 @@ module Toys
|
|
295
295
|
|
296
296
|
##
|
297
297
|
# The tool definition governing this parser.
|
298
|
-
# @return [Toys::
|
298
|
+
# @return [Toys::ToolDefinition]
|
299
299
|
#
|
300
300
|
attr_reader :tool
|
301
301
|
|
@@ -429,7 +429,7 @@ module Toys
|
|
429
429
|
Context::Key::TOOL_NAME => tool.full_name,
|
430
430
|
Context::Key::USAGE_ERRORS => [],
|
431
431
|
}
|
432
|
-
|
432
|
+
tool.default_data.each { |k, v| data[k] = v.clone }
|
433
433
|
default_data.each { |k, v| data[k] ||= v }
|
434
434
|
data
|
435
435
|
end
|
@@ -450,7 +450,7 @@ module Toys
|
|
450
450
|
case arg
|
451
451
|
when "--"
|
452
452
|
@flags_allowed = false
|
453
|
-
when /\A(--\w[
|
453
|
+
when /\A(--\w[?\w-]*)=(.*)\z/
|
454
454
|
handle_valued_flag(::Regexp.last_match(1), ::Regexp.last_match(2))
|
455
455
|
when /\A--.+\z/
|
456
456
|
handle_plain_flag(arg)
|
@@ -474,8 +474,7 @@ module Toys
|
|
474
474
|
return "" unless flag_def
|
475
475
|
@seen_flag_keys << flag_def.key
|
476
476
|
if flag_def.flag_type == :boolean
|
477
|
-
add_data(flag_def.key, flag_def.handler, nil, !flag_result.unique_flag_negative?,
|
478
|
-
:flag, name)
|
477
|
+
add_data(flag_def.key, flag_def.handler, nil, !flag_result.unique_flag_negative?, :flag, name)
|
479
478
|
elsif following.empty?
|
480
479
|
if flag_def.value_type == :required || flag_result.unique_flag_syntax.value_delim == " "
|
481
480
|
@active_flag_def = flag_def
|
data/lib/toys/cli.rb
CHANGED
@@ -78,8 +78,8 @@ module Toys
|
|
78
78
|
# with different verbosity settings (since the logger cannot have
|
79
79
|
# multiple level settings simultaneously). In that case, do not set a
|
80
80
|
# global logger, but use the `logger_factory` parameter instead.
|
81
|
-
# @param logger_factory [Proc] A proc that takes a {Toys::
|
82
|
-
# argument, and returns a `Logger` to use when running that tool.
|
81
|
+
# @param logger_factory [Proc] A proc that takes a {Toys::ToolDefinition}
|
82
|
+
# as an argument, and returns a `Logger` to use when running that tool.
|
83
83
|
# Optional. If not provided (and no global logger is set), CLI will use
|
84
84
|
# a default factory that writes generates loggers writing formatted
|
85
85
|
# output to `STDERR`, as defined by {Toys::CLI.default_logger_factory}.
|
@@ -321,10 +321,22 @@ module Toys
|
|
321
321
|
# a Toys directory.
|
322
322
|
# @param high_priority [Boolean] Add the config at the head of the priority
|
323
323
|
# list rather than the tail.
|
324
|
+
# @param source_name [String] A custom name for the root source. Optional.
|
325
|
+
# @param context_directory [String,nil,:path,:parent] The context directory
|
326
|
+
# for tools loaded from this path. You can pass a directory path as a
|
327
|
+
# string, `:path` to denote the given path, `:parent` to denote the
|
328
|
+
# given path's parent directory, or `nil` to denote no context.
|
329
|
+
# Defaults to `:parent`.
|
324
330
|
# @return [self]
|
325
331
|
#
|
326
|
-
def add_config_path(path,
|
327
|
-
|
332
|
+
def add_config_path(path,
|
333
|
+
high_priority: false,
|
334
|
+
source_name: nil,
|
335
|
+
context_directory: :parent)
|
336
|
+
@loader.add_path(path,
|
337
|
+
high_priority: high_priority,
|
338
|
+
source_name: source_name,
|
339
|
+
context_directory: context_directory)
|
328
340
|
self
|
329
341
|
end
|
330
342
|
|
@@ -336,15 +348,24 @@ module Toys
|
|
336
348
|
#
|
337
349
|
# @param high_priority [Boolean] Add the config at the head of the priority
|
338
350
|
# list rather than the tail.
|
339
|
-
# @param
|
340
|
-
# for tools defined in this block. If omitted, a default
|
341
|
-
# will be generated.
|
351
|
+
# @param source_name [String] The source name that will be shown in
|
352
|
+
# documentation for tools defined in this block. If omitted, a default
|
353
|
+
# unique string will be generated.
|
342
354
|
# @param block [Proc] The block of configuration, executed in the context
|
343
355
|
# of the tool DSL {Toys::DSL::Tool}.
|
356
|
+
# @param context_directory [String,nil] The context directory for tools
|
357
|
+
# loaded from this block. You can pass a directory path as a string, or
|
358
|
+
# `nil` to denote no context. Defaults to `nil`.
|
344
359
|
# @return [self]
|
345
360
|
#
|
346
|
-
def add_config_block(high_priority: false,
|
347
|
-
|
361
|
+
def add_config_block(high_priority: false,
|
362
|
+
source_name: nil,
|
363
|
+
context_directory: nil,
|
364
|
+
&block)
|
365
|
+
@loader.add_block(high_priority: high_priority,
|
366
|
+
source_name: source_name,
|
367
|
+
context_directory: context_directory,
|
368
|
+
&block)
|
348
369
|
self
|
349
370
|
end
|
350
371
|
|
@@ -358,19 +379,28 @@ module Toys
|
|
358
379
|
# @param search_path [String] A path to search for configs.
|
359
380
|
# @param high_priority [Boolean] Add the configs at the head of the
|
360
381
|
# priority list rather than the tail.
|
382
|
+
# @param context_directory [String,nil,:path,:parent] The context directory
|
383
|
+
# for tools loaded from this path. You can pass a directory path as a
|
384
|
+
# string, `:path` to denote the given path, `:parent` to denote the
|
385
|
+
# given path's parent directory, or `nil` to denote no context.
|
386
|
+
# Defaults to `:path`.
|
361
387
|
# @return [self]
|
362
388
|
#
|
363
|
-
def add_search_path(search_path,
|
389
|
+
def add_search_path(search_path,
|
390
|
+
high_priority: false,
|
391
|
+
context_directory: :path)
|
364
392
|
paths = []
|
365
393
|
if @config_file_name
|
366
394
|
file_path = ::File.join(search_path, @config_file_name)
|
367
|
-
paths <<
|
395
|
+
paths << @config_file_name if !::File.directory?(file_path) && ::File.readable?(file_path)
|
368
396
|
end
|
369
397
|
if @config_dir_name
|
370
398
|
dir_path = ::File.join(search_path, @config_dir_name)
|
371
|
-
paths <<
|
399
|
+
paths << @config_dir_name if ::File.directory?(dir_path) && ::File.readable?(dir_path)
|
372
400
|
end
|
373
|
-
@loader.
|
401
|
+
@loader.add_path_set(search_path, paths,
|
402
|
+
high_priority: high_priority,
|
403
|
+
context_directory: context_directory)
|
374
404
|
self
|
375
405
|
end
|
376
406
|
|
@@ -443,7 +473,7 @@ module Toys
|
|
443
473
|
# Run the given tool with the given arguments.
|
444
474
|
# Does not handle exceptions.
|
445
475
|
#
|
446
|
-
# @param tool [Toys::
|
476
|
+
# @param tool [Toys::ToolDefinition] The tool to run.
|
447
477
|
# @param args [Array<String>] Command line arguments passed to the tool.
|
448
478
|
# @param default_data [Hash] Initial tool context data.
|
449
479
|
# @return [Integer] The resulting status code
|
data/lib/toys/compat.rb
CHANGED
@@ -53,28 +53,6 @@ module Toys
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
# In Ruby < 2.4, some objects such as nil cannot be cloned.
|
57
|
-
if ruby_version >= 20400
|
58
|
-
# @private
|
59
|
-
def self.merge_clones(hash, orig)
|
60
|
-
orig.each { |k, v| hash[k] = v.clone }
|
61
|
-
hash
|
62
|
-
end
|
63
|
-
else
|
64
|
-
# @private
|
65
|
-
def self.merge_clones(hash, orig)
|
66
|
-
orig.each do |k, v|
|
67
|
-
hash[k] =
|
68
|
-
begin
|
69
|
-
v.clone
|
70
|
-
rescue ::TypeError
|
71
|
-
v
|
72
|
-
end
|
73
|
-
end
|
74
|
-
hash
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
56
|
# The :base argument to Dir.glob requires Ruby 2.5 or later.
|
79
57
|
if ruby_version >= 20500
|
80
58
|
# @private
|
@@ -106,5 +84,24 @@ module Toys
|
|
106
84
|
end
|
107
85
|
end
|
108
86
|
end
|
87
|
+
|
88
|
+
# File.absolute_path? requires Ruby 2.7 or later. For earlier Rubies, use
|
89
|
+
# an ad-hoc mechanism.
|
90
|
+
if ruby_version >= 20700
|
91
|
+
# @private
|
92
|
+
def self.absolute_path?(path)
|
93
|
+
::File.absolute_path?(path)
|
94
|
+
end
|
95
|
+
elsif ::Dir.getwd =~ /^[a-zA-Z]:/
|
96
|
+
# @private
|
97
|
+
def self.absolute_path?(path)
|
98
|
+
/^[a-zA-Z]:/.match?(path)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
# @private
|
102
|
+
def self.absolute_path?(path)
|
103
|
+
path.start_with?("/")
|
104
|
+
end
|
105
|
+
end
|
109
106
|
end
|
110
107
|
end
|
data/lib/toys/completion.rb
CHANGED
@@ -88,7 +88,7 @@ module Toys
|
|
88
88
|
|
89
89
|
##
|
90
90
|
# The tool being invoked, which should control the completion.
|
91
|
-
# @return [Toys::
|
91
|
+
# @return [Toys::ToolDefinition]
|
92
92
|
#
|
93
93
|
def tool
|
94
94
|
lookup_tool
|
@@ -236,6 +236,7 @@ module Toys
|
|
236
236
|
# prefix. Defaults to requiring the prefix be empty.
|
237
237
|
#
|
238
238
|
def initialize(cwd: nil, omit_files: false, omit_directories: false, prefix_constraint: "")
|
239
|
+
super()
|
239
240
|
@cwd = cwd || ::Dir.pwd
|
240
241
|
@include_files = !omit_files
|
241
242
|
@include_directories = !omit_directories
|
@@ -328,6 +329,7 @@ module Toys
|
|
328
329
|
# prefix. Defaults to requiring the prefix be empty.
|
329
330
|
#
|
330
331
|
def initialize(values, prefix_constraint: "")
|
332
|
+
super()
|
331
333
|
@values = values.flatten.map { |v| Candidate.new(v) }.sort
|
332
334
|
@prefix_constraint = prefix_constraint
|
333
335
|
end
|
data/lib/toys/context.rb
CHANGED
@@ -33,7 +33,7 @@ module Toys
|
|
33
33
|
# This module is mixed into the runtime context. This means you can
|
34
34
|
# reference any of these constants directly from your run method.
|
35
35
|
#
|
36
|
-
#
|
36
|
+
# ### Example
|
37
37
|
#
|
38
38
|
# tool "my-name" do
|
39
39
|
# def run
|
@@ -78,7 +78,7 @@ module Toys
|
|
78
78
|
LOGGER = ::Object.new.freeze
|
79
79
|
|
80
80
|
##
|
81
|
-
# Context key for the {Toys::
|
81
|
+
# Context key for the {Toys::ToolDefinition} object being executed.
|
82
82
|
# @return [Object]
|
83
83
|
#
|
84
84
|
TOOL = ::Object.new.freeze
|
data/lib/toys/core.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Create a base class for defining a tool with a given name.
|
5
|
+
#
|
6
|
+
# This method returns a base class for defining a tool with a given name.
|
7
|
+
# This is useful if the naming behavior of {Toys::Tool} is not adequate for
|
8
|
+
# your tool.
|
9
|
+
#
|
10
|
+
# ### Example
|
11
|
+
#
|
12
|
+
# class FooBar < Toys.Tool("Foo_Bar")
|
13
|
+
# desc "This is a tool called Foo_Bar"
|
14
|
+
#
|
15
|
+
# def run
|
16
|
+
# puts "Foo_Bar called"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @param name [String] Name of the tool. Defaults to a name inferred from the
|
21
|
+
# class name. (See {Toys::Tool}.)
|
22
|
+
# @param base [Class] Use this tool class as the base class, and inherit helper
|
23
|
+
# methods from it.
|
24
|
+
# @param args [String,Class] Any string-valued positional argument is
|
25
|
+
# interpreted as the name. Any class-valued positional argument is
|
26
|
+
# interpreted as the base class.
|
27
|
+
#
|
28
|
+
def Toys.Tool(*args, name: nil, base: nil) # rubocop:disable Naming/MethodName
|
29
|
+
args.each do |arg|
|
30
|
+
case arg
|
31
|
+
when ::Class
|
32
|
+
raise ::ArgumentError, "Both base keyword argument and class-valud argument received" if base
|
33
|
+
base = arg
|
34
|
+
when ::String, ::Symbol
|
35
|
+
raise ::ArgumentError, "Both name keyword argument and string-valud argument received" if name
|
36
|
+
name = arg
|
37
|
+
else
|
38
|
+
raise ::ArgumentError, "Unrecognized argument: #{arg}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
if base && !base.ancestors.include?(::Toys::Context)
|
42
|
+
raise ::ArgumentError, "Base class must itself be a tool"
|
43
|
+
end
|
44
|
+
return base || ::Toys::Tool if name.nil?
|
45
|
+
::Class.new(base || ::Toys::Context) do
|
46
|
+
base_class = self
|
47
|
+
define_singleton_method(:inherited) do |tool_class|
|
48
|
+
::Toys::DSL::Internal.configure_class(tool_class, base_class == self ? name.to_s : nil)
|
49
|
+
super(tool_class)
|
50
|
+
::Toys::DSL::Internal.setup_class_dsl(tool_class)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Toys
|
56
|
+
##
|
57
|
+
# Base class for defining tools
|
58
|
+
#
|
59
|
+
# This base class provides an alternative to the {Toys::DSL::Tool#tool}
|
60
|
+
# directive for defining tools in the Toys DSL. Creating a subclass of
|
61
|
+
# `Toys::Tool` will create a tool whose name is the "kebab-case" of the class
|
62
|
+
# name. Subclasses can be created only in the context of a tool configuration
|
63
|
+
# DSL. Furthermore, a class-defined tool can be created only at the top level
|
64
|
+
# of a configuration file, or within another class-defined tool. It cannot
|
65
|
+
# be a subtool of a tool block.
|
66
|
+
#
|
67
|
+
# ### Example
|
68
|
+
#
|
69
|
+
# class FooBar < Toys::Tool
|
70
|
+
# desc "This is a tool called foo-bar"
|
71
|
+
#
|
72
|
+
# def run
|
73
|
+
# puts "foo-bar called"
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
class Tool < Context
|
78
|
+
# @private
|
79
|
+
def self.inherited(tool_class)
|
80
|
+
DSL::Internal.configure_class(tool_class)
|
81
|
+
super
|
82
|
+
DSL::Internal.setup_class_dsl(tool_class)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|