toys 0.11.5 → 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 +27 -0
- data/README.md +1 -1
- data/builtins/system/bash-completion.rb +89 -0
- data/builtins/system/test.rb +96 -0
- data/builtins/system/update.rb +48 -0
- data/docs/guide.md +91 -3
- data/lib/toys/standard_cli.rb +2 -5
- data/lib/toys/templates/clean.rb +17 -1
- data/lib/toys/templates/gem_build.rb +22 -4
- data/lib/toys/templates/minitest.rb +17 -1
- data/lib/toys/templates/rake.rb +18 -2
- data/lib/toys/templates/rdoc.rb +22 -3
- data/lib/toys/templates/rspec.rb +17 -1
- data/lib/toys/templates/rubocop.rb +22 -3
- data/lib/toys/templates/yardoc.rb +30 -10
- data/lib/toys/testing.rb +197 -0
- data/lib/toys/version.rb +1 -1
- metadata +12 -9
- data/builtins/system.rb +0 -152
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '091a51c34d19b918c203d88f0bbae74432343aae63a0ee7d62799fa30a1c8097'
|
4
|
+
data.tar.gz: 00e1a389cf5de2d5a85133a7ca148480e6885f2c80822fcfc4e9838d36d724a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93b41a0886856f9665f3650596dba6fa4cb9a13c0a1c3fa040aed3b669382b86373e38d57bf3ac8bc0f90ed33a5094e2bcd4c89ea974ff98fc7dd5aebff5cb88
|
7
|
+
data.tar.gz: c83a1aa39ba8e3be2246aaa4bd8f6003b6c10d52e91beeb04ecc9082403b19e64fd5af7c0a04a8bd10c21d0f731bd63a0d8f3c0649163027fdc78429760553ef
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### v0.12.0 / 2021-08-05
|
4
|
+
|
5
|
+
Toys 0.12.0 is a major release with significant new features and bug fixes, and a few minor breaking changes. Additionally, this release now requires Ruby 2.4 or later.
|
6
|
+
|
7
|
+
Breaking changes:
|
8
|
+
|
9
|
+
* Defining a tool with whitespace, control characters, or certain punctuation in the name, now raises ToolDefinitionError.
|
10
|
+
* The Toys::Tool class (for the object returned by the Toys::Context::Key::TOOL attribute) has been renamed to Toys::ToolDefinition so that the old name can be used for class-based tool definition.
|
11
|
+
|
12
|
+
New functionality:
|
13
|
+
|
14
|
+
* 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.
|
15
|
+
* The subtool list on help screens is now split into sections by source directory
|
16
|
+
* You can now load tools from a remote git repository using the load_git directive.
|
17
|
+
* Whitespace is now automatically considered a name delimiter when defining tools.
|
18
|
+
* There is experimental support for providing tests for 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
|
+
* You can now set the context directory individually for the standard build tools.
|
22
|
+
* Added a new standard mixin that provides XDG Base Directory information.
|
23
|
+
* Added a new standard mixin that provides cached access to remote git repos.
|
24
|
+
|
25
|
+
Fixes:
|
26
|
+
|
27
|
+
* Fixed some bundler integration issues that occurred when the bundle is being installed in a separate path such as a vendor directory.
|
28
|
+
* Exceptions raised from internal classes now include the full backtrace.
|
29
|
+
|
3
30
|
### v0.11.5 / 2021-03-28
|
4
31
|
|
5
32
|
* BREAKING CHANGE: The exit_on_nonzero_status option to exec now exits on signals and failures to spawn, in addition to error codes.
|
data/README.md
CHANGED
@@ -50,7 +50,7 @@ Toys does not yet specially implement tab completion for zsh or other shells.
|
|
50
50
|
However, if you are using zsh, installing bash completion using `bashcompinit`
|
51
51
|
*mostly* works.
|
52
52
|
|
53
|
-
Toys requires Ruby 2.
|
53
|
+
Toys requires Ruby 2.4 or later.
|
54
54
|
|
55
55
|
Most parts of Toys work on JRuby. However, JRuby is not recommended because of
|
56
56
|
JVM boot latency, lack of support for Kernel#fork, and other issues.
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Bash tab completion for Toys"
|
4
|
+
|
5
|
+
long_desc \
|
6
|
+
"Tools that manage tab completion for Toys in the bash shell.",
|
7
|
+
"",
|
8
|
+
"To install tab completion for Toys, execute the following line in a bash shell, or" \
|
9
|
+
" include it in an init file such as your .bashrc:",
|
10
|
+
[" $(toys system bash-completion install)"],
|
11
|
+
"",
|
12
|
+
"To remove tab completion, execute:",
|
13
|
+
[" $(toys system bash-completion remove)"],
|
14
|
+
"",
|
15
|
+
"It is also possible to install completions for different executable names if you have" \
|
16
|
+
" aliases for Toys. See the help for the \"install\" and \"remove\" tools for details.",
|
17
|
+
"",
|
18
|
+
"The \"eval\" tool is the actual completion command invoked by bash when it needs to" \
|
19
|
+
" complete a toys command line. You shouldn't need to invoke it directly."
|
20
|
+
|
21
|
+
tool "eval" do
|
22
|
+
desc "Tab completion command (executed by bash)"
|
23
|
+
|
24
|
+
long_desc \
|
25
|
+
"Completion command invoked by bash to compete a toys command line. Generally you do not" \
|
26
|
+
" need to invoke this directly. It reads the command line context from the COMP_LINE" \
|
27
|
+
" and COMP_POINT environment variables, and outputs completion candidates to stdout."
|
28
|
+
|
29
|
+
disable_argument_parsing
|
30
|
+
|
31
|
+
def run
|
32
|
+
require "toys/utils/completion_engine"
|
33
|
+
result = ::Toys::Utils::CompletionEngine::Bash.new(cli).run
|
34
|
+
if result > 1
|
35
|
+
logger.fatal("This tool must be invoked as a bash completion command.")
|
36
|
+
end
|
37
|
+
exit(result)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
tool "install" do
|
42
|
+
desc "Install bash tab completion"
|
43
|
+
|
44
|
+
long_desc \
|
45
|
+
"Outputs a command to set up Toys tab completion in the current bash shell.",
|
46
|
+
"",
|
47
|
+
"To use, execute the following line in a bash shell, or include it in an init file" \
|
48
|
+
" such as your .bashrc:",
|
49
|
+
[" $(toys system bash-completion install)"],
|
50
|
+
"",
|
51
|
+
"This will associate the toys tab completion logic with the `toys` executable by default." \
|
52
|
+
" If you have aliases for the toys executable, pass them as arguments. e.g.",
|
53
|
+
[" $(toys system bash-completion install my-toys-alias another-alias)"]
|
54
|
+
|
55
|
+
remaining_args :executable_names,
|
56
|
+
desc: "Names of executables for which to set up tab completion" \
|
57
|
+
" (default: #{::Toys::StandardCLI::EXECUTABLE_NAME})"
|
58
|
+
|
59
|
+
def run
|
60
|
+
require "shellwords"
|
61
|
+
path = ::File.join(::File.dirname(::File.dirname(__dir__)), "share", "bash-completion.sh")
|
62
|
+
exes = executable_names.empty? ? [::Toys::StandardCLI::EXECUTABLE_NAME] : executable_names
|
63
|
+
puts Shellwords.join(["source", path] + exes)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
tool "remove" do
|
68
|
+
desc "Remove bash tab completion"
|
69
|
+
|
70
|
+
long_desc \
|
71
|
+
"Outputs a command to remove Toys tab completion from the current bash shell.",
|
72
|
+
"",
|
73
|
+
"To use, execute the following line in a bash shell:",
|
74
|
+
[" $(toys system bash-completion remove)"],
|
75
|
+
"",
|
76
|
+
"If you have other names or aliases for the toys executable, pass them as arguments. e.g.",
|
77
|
+
[" $(toys system bash-completion remove my-toys-alias another-alias)"]
|
78
|
+
|
79
|
+
remaining_args :executable_names,
|
80
|
+
desc: "Names of executables for which to set up tab completion" \
|
81
|
+
" (default: #{::Toys::StandardCLI::EXECUTABLE_NAME})"
|
82
|
+
|
83
|
+
def run
|
84
|
+
require "shellwords"
|
85
|
+
path = ::File.join(::File.dirname(::File.dirname(__dir__)), "share", "bash-completion-remove.sh")
|
86
|
+
exes = executable_names.empty? ? [::Toys::StandardCLI::EXECUTABLE_NAME] : executable_names
|
87
|
+
puts Shellwords.join(["source", path] + exes)
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Run tool tests"
|
4
|
+
|
5
|
+
flag :directory, "-d", "--directory PATH",
|
6
|
+
desc: "Run tests from the given directory"
|
7
|
+
flag :seed, "-s", "--seed SEED",
|
8
|
+
desc: "Sets random seed."
|
9
|
+
flag :warnings, "-w", "--[no-]warnings",
|
10
|
+
default: true,
|
11
|
+
desc: "Turn on Ruby warnings (defaults to true)"
|
12
|
+
flag :name, "-n", "--name PATTERN",
|
13
|
+
desc: "Filter run on /regexp/ or string."
|
14
|
+
flag :exclude, "-e", "--exclude PATTERN",
|
15
|
+
desc: "Exclude /regexp/ or string from run."
|
16
|
+
flag :recursive, "--[no-]recursive", default: true,
|
17
|
+
desc: "Recursively test subtools (default is true)"
|
18
|
+
flag :tool, "-t TOOL", "--tool TOOL", default: "",
|
19
|
+
desc: "Run tests only for tools under the given path"
|
20
|
+
|
21
|
+
include :exec
|
22
|
+
include :gems
|
23
|
+
include :terminal
|
24
|
+
|
25
|
+
def run
|
26
|
+
gem "minitest", "~> 5.0"
|
27
|
+
::Dir.chdir(tool_dir)
|
28
|
+
test_files = find_test_files
|
29
|
+
result = exec_ruby(ruby_args, in: :controller, log_cmd: "Starting minitest...") do |controller|
|
30
|
+
controller.in.puts("gem 'minitest', '~> 5.0'")
|
31
|
+
controller.in.puts("require 'minitest/autorun'")
|
32
|
+
controller.in.puts("require 'toys'")
|
33
|
+
controller.in.puts("require 'toys/testing'")
|
34
|
+
test_files.each do |file|
|
35
|
+
controller.in.puts("load '#{file}'")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
if result.error?
|
39
|
+
logger.error("Minitest failed!")
|
40
|
+
exit(result.exit_code)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_test_files
|
45
|
+
glob = ".test/**/test_*.rb"
|
46
|
+
glob = "**/#{glob}" if recursive
|
47
|
+
test_files = ::Dir.glob(glob)
|
48
|
+
if test_files.empty?
|
49
|
+
logger.warn("No test files found")
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
test_files.each do |file|
|
53
|
+
logger.info("Loading: #{file}")
|
54
|
+
end
|
55
|
+
test_files
|
56
|
+
end
|
57
|
+
|
58
|
+
def tool_dir
|
59
|
+
words = cli.loader.split_path(tool)
|
60
|
+
dir = base_dir
|
61
|
+
unless words.empty?
|
62
|
+
dir = ::File.join(dir, *words)
|
63
|
+
unless ::File.directory?(dir)
|
64
|
+
logger.warn("No such directory: #{dir}")
|
65
|
+
exit
|
66
|
+
end
|
67
|
+
end
|
68
|
+
dir
|
69
|
+
end
|
70
|
+
|
71
|
+
def base_dir
|
72
|
+
return ::File.absolute_path(directory) if directory
|
73
|
+
dir = ::Dir.getwd
|
74
|
+
loop do
|
75
|
+
candidate = ::File.join(dir, ::Toys::StandardCLI::CONFIG_DIR_NAME)
|
76
|
+
return candidate if ::File.directory?(candidate)
|
77
|
+
parent = ::File.dirname(dir)
|
78
|
+
if parent == dir
|
79
|
+
logger.error("Unable to find a Toys directory")
|
80
|
+
exit(1)
|
81
|
+
end
|
82
|
+
dir = parent
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def ruby_args
|
87
|
+
args = []
|
88
|
+
args << "-w" if warnings
|
89
|
+
args << "-I#{::Toys::CORE_LIB_PATH}#{::File::PATH_SEPARATOR}#{::Toys::LIB_PATH}"
|
90
|
+
args << "-"
|
91
|
+
args << "--seed" << seed if seed
|
92
|
+
args << "--verbose" if verbosity.positive?
|
93
|
+
args << "--name" << name if name
|
94
|
+
args << "--exclude" << exclude if exclude
|
95
|
+
args
|
96
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Update Toys if a newer version is available"
|
4
|
+
|
5
|
+
long_desc "Checks rubygems for a newer version of Toys. If one is available, downloads" \
|
6
|
+
" and installs it."
|
7
|
+
|
8
|
+
flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
|
9
|
+
|
10
|
+
include :exec
|
11
|
+
include :terminal
|
12
|
+
|
13
|
+
def run
|
14
|
+
require "rubygems"
|
15
|
+
configure_exec(exit_on_nonzero_status: true)
|
16
|
+
version_info = spinner(leading_text: "Checking rubygems for the latest release... ",
|
17
|
+
final_text: "Done.\n") do
|
18
|
+
capture(["gem", "list", "-q", "-r", "-e", "toys"])
|
19
|
+
end
|
20
|
+
if version_info =~ /toys\s\((.+)\)/
|
21
|
+
latest_version = ::Gem::Version.new(::Regexp.last_match(1))
|
22
|
+
cur_version = ::Gem::Version.new(::Toys::VERSION)
|
23
|
+
if latest_version > cur_version
|
24
|
+
prompt = "Update Toys from #{cur_version} to #{latest_version}? "
|
25
|
+
exit(1) unless yes || confirm(prompt, default: true)
|
26
|
+
result = spinner(leading_text: "Installing Toys version #{latest_version}... ",
|
27
|
+
final_text: "Done.\n") do
|
28
|
+
exec(["gem", "install", "toys", "--version", latest_version.to_s],
|
29
|
+
out: :capture, err: :capture)
|
30
|
+
end
|
31
|
+
if result.error?
|
32
|
+
puts(result.captured_out + result.captured_err)
|
33
|
+
puts("Toys failed to install version #{latest_version}", :red, :bold)
|
34
|
+
exit(1)
|
35
|
+
end
|
36
|
+
puts("Toys successfully installed version #{latest_version}", :green, :bold)
|
37
|
+
elsif latest_version < cur_version
|
38
|
+
puts("Toys is already at experimental version #{cur_version}, which is later than" \
|
39
|
+
" the latest released version #{latest_version}",
|
40
|
+
:yellow, :bold)
|
41
|
+
else
|
42
|
+
puts("Toys is already at the latest version: #{latest_version}", :green, :bold)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
puts("Could not get latest Toys version", :red, :bold)
|
46
|
+
exit(1)
|
47
|
+
end
|
48
|
+
end
|
data/docs/guide.md
CHANGED
@@ -1118,8 +1118,8 @@ run Toys with no arguments:
|
|
1118
1118
|
|
1119
1119
|
The root tool will display the overall help screen for Toys.
|
1120
1120
|
|
1121
|
-
Although it is a less common pattern, it is possible for a tool
|
1122
|
-
|
1121
|
+
Although it is a less common pattern, it is possible for a tool to have its own
|
1122
|
+
`run` method even if it has subtools:
|
1123
1123
|
|
1124
1124
|
tool "test" do
|
1125
1125
|
def run
|
@@ -1142,12 +1142,100 @@ subtools to have its own `run` method:
|
|
1142
1142
|
Now running `toys test` will run its own implementation.
|
1143
1143
|
|
1144
1144
|
(Yes, it is even possible to write a `run` method for the root tool. I don't
|
1145
|
-
recommend doing so, because
|
1145
|
+
recommend doing so, because you would lose the root tool's useful default
|
1146
1146
|
implementation that lists all your tools.)
|
1147
1147
|
|
1148
1148
|
Toys allows subtools to be nested arbitrarily deep. In practice, however, more
|
1149
1149
|
than two or three levels of hierarchy can be confusing to use.
|
1150
1150
|
|
1151
|
+
### Defining subtools using classes
|
1152
|
+
|
1153
|
+
It is also possible to define subtools by subclassing `Toys::Tool`. The class
|
1154
|
+
will support the same DSL as a `tool` block would. For example, this is what
|
1155
|
+
our greet tool would look like as a class:
|
1156
|
+
|
1157
|
+
class Greet < Toys::Tool
|
1158
|
+
optional_arg :whom, default: "world"
|
1159
|
+
flag :shout, "-s", "--shout"
|
1160
|
+
|
1161
|
+
def run
|
1162
|
+
greeting = "Hello, #{whom}!"
|
1163
|
+
greeting = greeting.upcase if shout
|
1164
|
+
puts greeting
|
1165
|
+
end
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
Defining tools as clases is useful if you want your Toys files to look a bit
|
1169
|
+
more like normal Ruby or you want to avoid long blocks. Additionally, they can
|
1170
|
+
be useful to scope constants, which otherwise would be visible throughout the
|
1171
|
+
entire file, as noted in the [section on using constants](#Using_constants).
|
1172
|
+
|
1173
|
+
When you define a tool as a class, Toys infers the tool name by converting the
|
1174
|
+
class name to "kebab-case". For example, the `Greet` class above would define a
|
1175
|
+
tool called `greet`. If the class were called `GreetMany`, the tool would be
|
1176
|
+
called `greet-many`. If you need to override this behavior or set a tool name
|
1177
|
+
that is not possible from legal class names, pass the desired tool name to the
|
1178
|
+
`Toys.Tool` method like this:
|
1179
|
+
|
1180
|
+
class Greet < Toys.Tool("_my_greet")
|
1181
|
+
optional_arg :whom, default: "world"
|
1182
|
+
flag :shout, "-s", "--shout"
|
1183
|
+
|
1184
|
+
def run
|
1185
|
+
greeting = "Hello, #{whom}!"
|
1186
|
+
greeting = greeting.upcase if shout
|
1187
|
+
puts greeting
|
1188
|
+
end
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
You can create subtools by nesting classes:
|
1192
|
+
|
1193
|
+
class Test < Toys::Tool
|
1194
|
+
class Unit < Toys::Tool
|
1195
|
+
def run
|
1196
|
+
puts "run only unit tests here..."
|
1197
|
+
end
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
class Integration < Toys::Tool
|
1201
|
+
def run
|
1202
|
+
puts "run only integration tests here..."
|
1203
|
+
end
|
1204
|
+
end
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
The above defines `test unit` and `test integration` tools as expected.
|
1208
|
+
|
1209
|
+
Finally, you may not nest a class-based tool inside a block-based tool. (This
|
1210
|
+
is because Ruby's constant definition rules would put such a class in an
|
1211
|
+
unexpected namespace, leading to potential clashes that would be difficult to
|
1212
|
+
diagnose.) It is, however, permissible to nest a block-based tool inside a
|
1213
|
+
class-based tool.
|
1214
|
+
|
1215
|
+
Hence, this is not allowed, and will result in an exception:
|
1216
|
+
|
1217
|
+
tool "test" do
|
1218
|
+
# This will raise Toys::ToolDefinitionError...
|
1219
|
+
class Unit < Toys::Tool
|
1220
|
+
def run
|
1221
|
+
puts "run unit tests..."
|
1222
|
+
end
|
1223
|
+
end
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
But this is legal:
|
1227
|
+
|
1228
|
+
class Test < Toys::Tool
|
1229
|
+
tool "unit" do
|
1230
|
+
def run
|
1231
|
+
puts "run unit tests..."
|
1232
|
+
end
|
1233
|
+
end
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
In general, though, as a best practice, I recommend against mixing the two
|
1237
|
+
styles. Define tools either as classes or as blocks, not both.
|
1238
|
+
|
1151
1239
|
## Understanding Toys files
|
1152
1240
|
|
1153
1241
|
Toys commands are defined in Toys files. We covered the basic syntax for these
|
data/lib/toys/standard_cli.rb
CHANGED
@@ -139,7 +139,7 @@ module Toys
|
|
139
139
|
add_search_path_hierarchy(start: cur_dir, terminate: global_dirs)
|
140
140
|
global_dirs.each { |path| add_search_path(path) }
|
141
141
|
builtins_path = ::File.join(::File.dirname(::File.dirname(__dir__)), "builtins")
|
142
|
-
add_config_path(builtins_path)
|
142
|
+
add_config_path(builtins_path, source_name: "(builtin tools)", context_directory: nil)
|
143
143
|
self
|
144
144
|
end
|
145
145
|
|
@@ -157,8 +157,6 @@ module Toys
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
# rubocop:disable Metrics/MethodLength
|
161
|
-
|
162
160
|
##
|
163
161
|
# Returns the middleware for the standard Toys CLI.
|
164
162
|
#
|
@@ -179,6 +177,7 @@ module Toys
|
|
179
177
|
default_recursive: true,
|
180
178
|
allow_root_args: true,
|
181
179
|
show_source_path: true,
|
180
|
+
separate_sources: true,
|
182
181
|
use_less: true,
|
183
182
|
fallback_execution: true),
|
184
183
|
Middleware.spec(:show_root_version,
|
@@ -189,8 +188,6 @@ module Toys
|
|
189
188
|
]
|
190
189
|
end
|
191
190
|
|
192
|
-
# rubocop:enable Metrics/MethodLength
|
193
|
-
|
194
191
|
##
|
195
192
|
# Returns the default set of global config directories.
|
196
193
|
#
|
data/lib/toys/templates/clean.rb
CHANGED
@@ -23,10 +23,13 @@ module Toys
|
|
23
23
|
# to clean. You can also include the symbol `:gitignore` which will
|
24
24
|
# clean all items covered by `.gitignore` files, if contained in a
|
25
25
|
# git working tree.
|
26
|
+
# @param context_directory [String] A custom context directory to use
|
27
|
+
# when executing this tool.
|
26
28
|
#
|
27
|
-
def initialize(name: nil, paths: [])
|
29
|
+
def initialize(name: nil, paths: [], context_directory: nil)
|
28
30
|
@name = name
|
29
31
|
@paths = paths
|
32
|
+
@context_directory = context_directory
|
30
33
|
end
|
31
34
|
|
32
35
|
##
|
@@ -45,6 +48,17 @@ module Toys
|
|
45
48
|
#
|
46
49
|
attr_writer :paths
|
47
50
|
|
51
|
+
##
|
52
|
+
# Custom context directory for this tool.
|
53
|
+
#
|
54
|
+
# @param value [String]
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
attr_writer :context_directory
|
58
|
+
|
59
|
+
# @private
|
60
|
+
attr_reader :context_directory
|
61
|
+
|
48
62
|
# @private
|
49
63
|
def paths
|
50
64
|
Array(@paths)
|
@@ -59,6 +73,8 @@ module Toys
|
|
59
73
|
tool(template.name) do
|
60
74
|
desc "Clean built files and directories."
|
61
75
|
|
76
|
+
set_context_directory template.context_directory if template.context_directory
|
77
|
+
|
62
78
|
static :template_paths, template.paths
|
63
79
|
|
64
80
|
include :fileutils
|