toys-core 0.9.4 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -1
- data/CHANGELOG.md +30 -0
- data/LICENSE.md +1 -1
- data/README.md +3 -3
- data/lib/toys-core.rb +11 -21
- data/lib/toys/acceptor.rb +0 -21
- data/lib/toys/arg_parser.rb +1 -22
- data/lib/toys/cli.rb +102 -70
- data/lib/toys/compat.rb +49 -41
- data/lib/toys/completion.rb +0 -21
- data/lib/toys/context.rb +0 -23
- data/lib/toys/core.rb +1 -22
- data/lib/toys/dsl/flag.rb +0 -21
- data/lib/toys/dsl/flag_group.rb +0 -21
- data/lib/toys/dsl/positional_arg.rb +0 -21
- data/lib/toys/dsl/tool.rb +135 -51
- data/lib/toys/errors.rb +0 -21
- data/lib/toys/flag.rb +0 -21
- data/lib/toys/flag_group.rb +0 -21
- data/lib/toys/input_file.rb +0 -21
- data/lib/toys/loader.rb +41 -78
- data/lib/toys/middleware.rb +146 -77
- data/lib/toys/mixin.rb +0 -21
- data/lib/toys/module_lookup.rb +3 -26
- data/lib/toys/positional_arg.rb +0 -21
- data/lib/toys/source_info.rb +49 -38
- data/lib/toys/standard_middleware/add_verbosity_flags.rb +0 -23
- data/lib/toys/standard_middleware/apply_config.rb +42 -0
- data/lib/toys/standard_middleware/handle_usage_errors.rb +7 -28
- data/lib/toys/standard_middleware/set_default_descriptions.rb +0 -23
- data/lib/toys/standard_middleware/show_help.rb +0 -23
- data/lib/toys/standard_middleware/show_root_version.rb +0 -23
- data/lib/toys/standard_mixins/bundler.rb +89 -0
- data/lib/toys/standard_mixins/exec.rb +124 -35
- data/lib/toys/standard_mixins/fileutils.rb +0 -21
- data/lib/toys/standard_mixins/gems.rb +2 -24
- data/lib/toys/standard_mixins/highline.rb +0 -21
- data/lib/toys/standard_mixins/terminal.rb +0 -21
- data/lib/toys/template.rb +0 -21
- data/lib/toys/tool.rb +22 -34
- data/lib/toys/utils/completion_engine.rb +0 -21
- data/lib/toys/utils/exec.rb +1 -21
- data/lib/toys/utils/gems.rb +174 -63
- data/lib/toys/utils/help_text.rb +0 -21
- data/lib/toys/utils/terminal.rb +46 -37
- data/lib/toys/wrappable_string.rb +0 -21
- metadata +25 -9
data/lib/toys/compat.rb
CHANGED
@@ -1,25 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
3
|
+
require "rbconfig"
|
23
4
|
|
24
5
|
module Toys
|
25
6
|
##
|
@@ -27,44 +8,51 @@ module Toys
|
|
27
8
|
# @private
|
28
9
|
#
|
29
10
|
module Compat
|
30
|
-
|
31
|
-
|
11
|
+
parts = ::RUBY_VERSION.split(".")
|
12
|
+
ruby_version = parts[0].to_i * 10000 + parts[1].to_i * 100 + parts[2].to_i
|
32
13
|
|
33
|
-
|
14
|
+
# @private
|
34
15
|
def self.jruby?
|
35
16
|
::RUBY_PLATFORM == "java"
|
36
17
|
end
|
37
18
|
|
38
|
-
|
19
|
+
# @private
|
39
20
|
def self.allow_fork?
|
40
|
-
!jruby? && RbConfig::CONFIG["host_os"] !~ /mswin/
|
21
|
+
!jruby? && ::RbConfig::CONFIG["host_os"] !~ /mswin/
|
41
22
|
end
|
42
23
|
|
43
|
-
|
44
|
-
def self.
|
45
|
-
|
24
|
+
# @private
|
25
|
+
def self.supports_suggestions?
|
26
|
+
unless defined?(@supports_suggestions)
|
27
|
+
require "rubygems"
|
28
|
+
begin
|
29
|
+
require "did_you_mean"
|
30
|
+
@supports_suggestions = defined?(::DidYouMean::SpellChecker)
|
31
|
+
rescue ::LoadError
|
32
|
+
@supports_suggestions = false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@supports_suggestions
|
46
36
|
end
|
47
37
|
|
48
|
-
|
49
|
-
|
50
|
-
|
38
|
+
# @private
|
39
|
+
def self.suggestions(word, list)
|
40
|
+
if supports_suggestions?
|
51
41
|
::DidYouMean::SpellChecker.new(dictionary: list).correct(word)
|
52
|
-
|
53
|
-
else
|
54
|
-
## @private
|
55
|
-
def self.suggestions(_word, _list)
|
42
|
+
else
|
56
43
|
[]
|
57
44
|
end
|
58
45
|
end
|
59
46
|
|
60
|
-
|
61
|
-
|
47
|
+
# In Ruby < 2.4, some objects such as nil cannot be cloned.
|
48
|
+
if ruby_version >= 20400
|
49
|
+
# @private
|
62
50
|
def self.merge_clones(hash, orig)
|
63
51
|
orig.each { |k, v| hash[k] = v.clone }
|
64
52
|
hash
|
65
53
|
end
|
66
54
|
else
|
67
|
-
|
55
|
+
# @private
|
68
56
|
def self.merge_clones(hash, orig)
|
69
57
|
orig.each do |k, v|
|
70
58
|
hash[k] =
|
@@ -78,16 +66,36 @@ module Toys
|
|
78
66
|
end
|
79
67
|
end
|
80
68
|
|
81
|
-
|
82
|
-
|
69
|
+
# The :base argument to Dir.glob requires Ruby 2.5 or later.
|
70
|
+
if ruby_version >= 20500
|
71
|
+
# @private
|
83
72
|
def self.glob_in_dir(glob, dir)
|
84
73
|
::Dir.glob(glob, base: dir)
|
85
74
|
end
|
86
75
|
else
|
87
|
-
|
76
|
+
# @private
|
88
77
|
def self.glob_in_dir(glob, dir)
|
89
78
|
::Dir.chdir(dir) { ::Dir.glob(glob) }
|
90
79
|
end
|
91
80
|
end
|
81
|
+
|
82
|
+
# Due to a bug in Ruby < 2.7, passing an empty **kwargs splat to
|
83
|
+
# initialize will fail if there are no formal keyword args.
|
84
|
+
if ruby_version >= 20700
|
85
|
+
# @private
|
86
|
+
def self.instantiate(klass, args, kwargs, block)
|
87
|
+
klass.new(*args, **kwargs, &block)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
# @private
|
91
|
+
def self.instantiate(klass, args, kwargs, block)
|
92
|
+
formals = klass.instance_method(:initialize).parameters
|
93
|
+
if kwargs.empty? && formals.all? { |arg| arg.first != :key && arg.first != :keyrest }
|
94
|
+
klass.new(*args, &block)
|
95
|
+
else
|
96
|
+
klass.new(*args, **kwargs, &block)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
92
100
|
end
|
93
101
|
end
|
data/lib/toys/completion.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
##
|
26
5
|
# A Completion is a callable Proc that determines candidates for shell tab
|
data/lib/toys/context.rb
CHANGED
@@ -1,28 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
|
-
require "logger"
|
25
|
-
|
26
3
|
module Toys
|
27
4
|
##
|
28
5
|
# This is the base class for tool execution. It represents `self` when your
|
data/lib/toys/core.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
##
|
26
5
|
# The core Toys classes.
|
@@ -30,7 +9,7 @@ module Toys
|
|
30
9
|
# Current version of Toys core.
|
31
10
|
# @return [String]
|
32
11
|
#
|
33
|
-
VERSION = "0.
|
12
|
+
VERSION = "0.10.0"
|
34
13
|
end
|
35
14
|
|
36
15
|
## @private deprecated
|
data/lib/toys/dsl/flag.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
module DSL
|
26
5
|
##
|
data/lib/toys/dsl/flag_group.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
module DSL
|
26
5
|
##
|
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
module DSL
|
26
5
|
##
|
data/lib/toys/dsl/tool.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
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:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
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.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
module DSL
|
26
5
|
##
|
@@ -226,7 +205,8 @@ module Toys
|
|
226
205
|
#
|
227
206
|
def template(name, template_class = nil, &block)
|
228
207
|
cur_tool = DSL::Tool.current_tool(self, false)
|
229
|
-
|
208
|
+
return self if cur_tool.nil?
|
209
|
+
cur_tool.add_template(name, template_class, &block)
|
230
210
|
self
|
231
211
|
end
|
232
212
|
|
@@ -273,7 +253,8 @@ module Toys
|
|
273
253
|
#
|
274
254
|
def completion(name, spec = nil, **options, &block)
|
275
255
|
cur_tool = DSL::Tool.current_tool(self, false)
|
276
|
-
|
256
|
+
return self if cur_tool.nil?
|
257
|
+
cur_tool.add_completion(name, spec, **options, &block)
|
277
258
|
self
|
278
259
|
end
|
279
260
|
|
@@ -322,11 +303,11 @@ module Toys
|
|
322
303
|
# @return [self]
|
323
304
|
#
|
324
305
|
def tool(words, if_defined: :combine, delegate_to: nil, &block)
|
325
|
-
subtool_words = @__words
|
306
|
+
subtool_words = @__words.dup
|
326
307
|
next_remaining = @__remaining_words
|
327
|
-
|
308
|
+
@__loader.split_path(words).each do |word|
|
328
309
|
word = word.to_s
|
329
|
-
subtool_words
|
310
|
+
subtool_words << word
|
330
311
|
next_remaining = Loader.next_remaining_words(next_remaining, word)
|
331
312
|
end
|
332
313
|
subtool = @__loader.get_tool(subtool_words, @__priority)
|
@@ -338,10 +319,12 @@ module Toys
|
|
338
319
|
subtool.reset_definition(@__loader)
|
339
320
|
end
|
340
321
|
end
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
322
|
+
if delegate_to
|
323
|
+
delegator = proc { self.delegate_to(delegate_to) }
|
324
|
+
@__loader.load_block(source_info, delegator, subtool_words, next_remaining, @__priority)
|
325
|
+
end
|
326
|
+
if block
|
327
|
+
@__loader.load_block(source_info, block, subtool_words, next_remaining, @__priority)
|
345
328
|
end
|
346
329
|
self
|
347
330
|
end
|
@@ -455,6 +438,7 @@ module Toys
|
|
455
438
|
#
|
456
439
|
def expand(template_class, *args, **kwargs)
|
457
440
|
cur_tool = DSL::Tool.current_tool(self, false)
|
441
|
+
return self if cur_tool.nil?
|
458
442
|
name = template_class.to_s
|
459
443
|
if template_class.is_a?(::String)
|
460
444
|
template_class = cur_tool.lookup_template(template_class)
|
@@ -464,15 +448,7 @@ module Toys
|
|
464
448
|
if template_class.nil?
|
465
449
|
raise ToolDefinitionError, "Template not found: #{name.inspect}"
|
466
450
|
end
|
467
|
-
|
468
|
-
# initialize will fail if there are no formal keyword args.
|
469
|
-
formals = template_class.instance_method(:initialize).parameters
|
470
|
-
template =
|
471
|
-
if kwargs.empty? && formals.all? { |(type, _name)| type != :key && type != :keyrest }
|
472
|
-
template_class.new(*args)
|
473
|
-
else
|
474
|
-
template_class.new(*args, **kwargs)
|
475
|
-
end
|
451
|
+
template = Compat.instantiate(template_class, args, kwargs, nil)
|
476
452
|
yield template if block_given?
|
477
453
|
class_exec(template, &template_class.expansion)
|
478
454
|
self
|
@@ -513,7 +489,8 @@ module Toys
|
|
513
489
|
#
|
514
490
|
def desc(str)
|
515
491
|
cur_tool = DSL::Tool.current_tool(self, true)
|
516
|
-
|
492
|
+
return self if cur_tool.nil?
|
493
|
+
cur_tool.desc = str
|
517
494
|
self
|
518
495
|
end
|
519
496
|
alias short_desc desc
|
@@ -539,10 +516,27 @@ module Toys
|
|
539
516
|
# long_desc "This line is appended to the description."
|
540
517
|
#
|
541
518
|
# @param strs [Toys::WrappableString,String,Array<String>...]
|
519
|
+
# @param file [String] Optional. Read the description from the given file
|
520
|
+
# provided relative to the current toys file. The file must be a
|
521
|
+
# plain text file whose suffix is `.txt`.
|
522
|
+
# @param data [String] Optional. Read the description from the given data
|
523
|
+
# file. The file must be a plain text file whose suffix is `.txt`.
|
542
524
|
# @return [self]
|
543
525
|
#
|
544
|
-
def long_desc(*strs)
|
545
|
-
DSL::Tool.current_tool(self, true)
|
526
|
+
def long_desc(*strs, file: nil, data: nil)
|
527
|
+
cur_tool = DSL::Tool.current_tool(self, true)
|
528
|
+
return self if cur_tool.nil?
|
529
|
+
if file
|
530
|
+
unless source_info.source_path
|
531
|
+
raise ::Toys::ToolDefinitionError,
|
532
|
+
"Cannot set long_desc from a file because the tool is not defined in a file"
|
533
|
+
end
|
534
|
+
file = ::File.join(::File.dirname(source_info.source_path), file)
|
535
|
+
elsif data
|
536
|
+
file = source_info.find_data(data, type: :file)
|
537
|
+
end
|
538
|
+
strs += DSL::Tool.load_long_desc_file(file) if file
|
539
|
+
cur_tool.append_long_desc(strs)
|
546
540
|
self
|
547
541
|
end
|
548
542
|
|
@@ -1405,7 +1399,8 @@ module Toys
|
|
1405
1399
|
#
|
1406
1400
|
def on_interrupt(handler = nil, &block)
|
1407
1401
|
cur_tool = DSL::Tool.current_tool(self, true)
|
1408
|
-
|
1402
|
+
return self if cur_tool.nil?
|
1403
|
+
cur_tool.interrupt_handler = handler || block
|
1409
1404
|
self
|
1410
1405
|
end
|
1411
1406
|
|
@@ -1436,7 +1431,8 @@ module Toys
|
|
1436
1431
|
#
|
1437
1432
|
def on_usage_error(handler = nil, &block)
|
1438
1433
|
cur_tool = DSL::Tool.current_tool(self, true)
|
1439
|
-
|
1434
|
+
return self if cur_tool.nil?
|
1435
|
+
cur_tool.usage_error_handler = handler || block
|
1440
1436
|
self
|
1441
1437
|
end
|
1442
1438
|
|
@@ -1578,11 +1574,84 @@ module Toys
|
|
1578
1574
|
#
|
1579
1575
|
def set_context_directory(dir) # rubocop:disable Naming/AccessorMethodName
|
1580
1576
|
cur_tool = DSL::Tool.current_tool(self, false)
|
1581
|
-
return if cur_tool.nil?
|
1577
|
+
return self if cur_tool.nil?
|
1582
1578
|
cur_tool.custom_context_directory = dir
|
1583
1579
|
self
|
1584
1580
|
end
|
1585
1581
|
|
1582
|
+
##
|
1583
|
+
# Applies the given block to all subtools, recursively. Effectively, the
|
1584
|
+
# given block is run at the *end* of every tool block. This can be used,
|
1585
|
+
# for example, to provide some shared configuration for all tools.
|
1586
|
+
#
|
1587
|
+
# The block is applied only to subtools defined *after* the block
|
1588
|
+
# appears. Subtools defined before the block appears are not affected.
|
1589
|
+
#
|
1590
|
+
# ## Example
|
1591
|
+
#
|
1592
|
+
# It is common for tools to use the `:exec` mixin to invoke external
|
1593
|
+
# programs. This example automatically includes the exec mixin in all
|
1594
|
+
# subtools, recursively, so you do not have to repeat the `include`
|
1595
|
+
# directive in every tool.
|
1596
|
+
#
|
1597
|
+
# # .toys.rb
|
1598
|
+
#
|
1599
|
+
# subtool_apply do
|
1600
|
+
# # Include the mixin only if the tool hasn't already done so
|
1601
|
+
# unless include?(:exec)
|
1602
|
+
# include :exec, exit_on_nonzero_status: true
|
1603
|
+
# end
|
1604
|
+
# end
|
1605
|
+
#
|
1606
|
+
# tool "foo" do
|
1607
|
+
# def run
|
1608
|
+
# # This tool has access to methods defined by the :exec mixin
|
1609
|
+
# # because the above block is applied to the tool.
|
1610
|
+
# sh "echo hello"
|
1611
|
+
# end
|
1612
|
+
# end
|
1613
|
+
#
|
1614
|
+
def subtool_apply(&block)
|
1615
|
+
cur_tool = DSL::Tool.current_tool(self, false)
|
1616
|
+
return self if cur_tool.nil?
|
1617
|
+
cur_tool.subtool_middleware_stack.add(:apply_config,
|
1618
|
+
parent_source: source_info, &block)
|
1619
|
+
self
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
##
|
1623
|
+
# Determines whether the current Toys version satisfies the given
|
1624
|
+
# requirements.
|
1625
|
+
#
|
1626
|
+
# @return [Boolean] whether or not the requirements are satisfied
|
1627
|
+
#
|
1628
|
+
def toys_version?(*requirements)
|
1629
|
+
require "rubygems"
|
1630
|
+
version = ::Gem::Version.new(Core::VERSION)
|
1631
|
+
requirement = ::Gem::Requirement.new(*requirements)
|
1632
|
+
requirement.satisfied_by?(version)
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
##
|
1636
|
+
# Asserts that the current Toys version against the given requirements,
|
1637
|
+
# raising an exception if not.
|
1638
|
+
#
|
1639
|
+
# @return [self]
|
1640
|
+
#
|
1641
|
+
# @raise [Toys::ToolDefinitionError] if the current Toys version does not
|
1642
|
+
# satisfy the requirements.
|
1643
|
+
#
|
1644
|
+
def toys_version!(*requirements)
|
1645
|
+
require "rubygems"
|
1646
|
+
version = ::Gem::Version.new(Core::VERSION)
|
1647
|
+
requirement = ::Gem::Requirement.new(*requirements)
|
1648
|
+
unless requirement.satisfied_by?(version)
|
1649
|
+
raise Toys::ToolDefinitionError,
|
1650
|
+
"Toys version requirements #{requirement} not satisfied by {version}"
|
1651
|
+
end
|
1652
|
+
self
|
1653
|
+
end
|
1654
|
+
|
1586
1655
|
## @private
|
1587
1656
|
def self.new_class(words, priority, loader)
|
1588
1657
|
tool_class = ::Class.new(::Toys::Context)
|
@@ -1599,7 +1668,7 @@ module Toys
|
|
1599
1668
|
def self.current_tool(tool_class, activate)
|
1600
1669
|
memoize_var = activate ? :@__active_tool : :@__cur_tool
|
1601
1670
|
if tool_class.instance_variable_defined?(memoize_var)
|
1602
|
-
|
1671
|
+
tool_class.instance_variable_get(memoize_var)
|
1603
1672
|
else
|
1604
1673
|
loader = tool_class.instance_variable_get(:@__loader)
|
1605
1674
|
words = tool_class.instance_variable_get(:@__words)
|
@@ -1610,13 +1679,12 @@ module Toys
|
|
1610
1679
|
else
|
1611
1680
|
loader.get_tool(words, priority)
|
1612
1681
|
end
|
1682
|
+
if cur_tool && activate
|
1683
|
+
source = tool_class.instance_variable_get(:@__source).last
|
1684
|
+
cur_tool.lock_source(source)
|
1685
|
+
end
|
1613
1686
|
tool_class.instance_variable_set(memoize_var, cur_tool)
|
1614
1687
|
end
|
1615
|
-
if cur_tool && activate
|
1616
|
-
source = tool_class.instance_variable_get(:@__source).last
|
1617
|
-
cur_tool.lock_source(source)
|
1618
|
-
end
|
1619
|
-
cur_tool
|
1620
1688
|
end
|
1621
1689
|
|
1622
1690
|
## @private
|
@@ -1654,6 +1722,22 @@ module Toys
|
|
1654
1722
|
end
|
1655
1723
|
mod
|
1656
1724
|
end
|
1725
|
+
|
1726
|
+
## @private
|
1727
|
+
def self.load_long_desc_file(path)
|
1728
|
+
if ::File.extname(path) == ".txt"
|
1729
|
+
begin
|
1730
|
+
::File.readlines(path).map do |line|
|
1731
|
+
line = line.chomp
|
1732
|
+
line =~ /^\s/ ? [line] : line
|
1733
|
+
end
|
1734
|
+
rescue ::SystemCallError => e
|
1735
|
+
raise Toys::ToolDefinitionError, e.to_s
|
1736
|
+
end
|
1737
|
+
else
|
1738
|
+
raise Toys::ToolDefinitionError, "Cannot load long desc from file type: #{path}"
|
1739
|
+
end
|
1740
|
+
end
|
1657
1741
|
end
|
1658
1742
|
end
|
1659
1743
|
end
|