toys-core 0.9.2 → 0.10.2
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/.yardopts +2 -1
- data/CHANGELOG.md +47 -0
- data/LICENSE.md +1 -1
- data/README.md +3 -3
- data/lib/toys-core.rb +14 -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 +136 -51
- data/lib/toys/errors.rb +1 -22
- 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 +42 -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 +478 -128
- 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 +142 -71
- data/lib/toys/utils/gems.rb +181 -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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5ae179649a0653db765b024bf25809d9e2cac6eb97aa3f1058be9ac59e9837c
|
4
|
+
data.tar.gz: eabbdaf0d81b86ab64674fbda0728ca361d66e9d69cfcd3ce76670f44b828d9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1312418f9bd568f880580faed87e55100800def6bb34cf159e26e342949fefceec6a73584af62569775a29921d923618a8cbc05f113d1797103c0133c1b7b2d
|
7
|
+
data.tar.gz: 335c0424407723fc242d9ea3ee0153bc9213b1b86e36a347106a96262aeb423c2aaa91cc71dcce72b4179eba5c40df1da112c87982c1543af337276db85bfb86
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,52 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.10.2 / 2020-07-03
|
4
|
+
|
5
|
+
* FIXED: The load path no longer loses the toys and toys-core directories after a bundle install.
|
6
|
+
|
7
|
+
### 0.10.1 / 2020-03-07
|
8
|
+
|
9
|
+
* FIXED: Setting `:exit_on_nonzero_status` explicitly to false now works as expected.
|
10
|
+
|
11
|
+
### 0.10.0 / 2020-02-24
|
12
|
+
|
13
|
+
Functional changes:
|
14
|
+
|
15
|
+
* ADDED: `:bundler` mixin that installs and sets up a bundle for the tool
|
16
|
+
* ADDED: `bundle` method to `Toys::Utils::Gems` that performs bundler install and setup
|
17
|
+
* ADDED: `subtool_apply` directive which applies a block to all subtools.
|
18
|
+
* ADDED: Add `.lib` directories to the Ruby load path when executing a tool.
|
19
|
+
* ADDED: `toys_version?` and `toys_version!` directives that check against version requirements.
|
20
|
+
* ADDED: `exec_separate_tool` and `capture_separate_tool` methods in the `:exec` mixin, to support executing tools in a separate process without forking
|
21
|
+
* IMPROVED: `long_desc` directive can now read the description from a text file.
|
22
|
+
* IMPROVED: The `tool` directive can take delimited strings as tool names.
|
23
|
+
* IMPROVED: Subtool blocks aren't actually executed unless the tool is needed.
|
24
|
+
* CHANGED: Added `on_missing` and `on_conflict` arguments to `Toys::Utils::Gems` constructor (which also affects the `:gems` mixin), and deprecated `suppress_confirm` and `default_confirm`.
|
25
|
+
|
26
|
+
Internal interface changes:
|
27
|
+
|
28
|
+
* ADDED: `Toys::Tool#subtool_middleware_stack` allowing a tool to modify the middleware stack for its subtools.
|
29
|
+
* ADDED: The `Toys::Middleware::Stack` class represents a stack of middleware specs, and distinguishes the default set from those added afterward.
|
30
|
+
* ADDED: `Toys.executable_path` attribute allowing an executable to provide the executable for running tools separately.
|
31
|
+
* ADDED: `Toys::CLI` now has a `logger_factory` property, to generate separate loggers per tool execution.
|
32
|
+
* ADDED: `Toys::CLI` and `Toys::Loader` now let you set `:lib_dir_name`.
|
33
|
+
* IMPROVED: Toys-core no longer has a general dependency on rubygems. (Parts that do depend on rubygems, such as the `:gems` mixin, do an explicit `require "rubygems"`.) This makes it possible to write an executable with `ruby --disable=gems` which improves startup time.
|
34
|
+
* IMPROVED: Middleware objects no longer have to respond to all middleware methods. If a method is not implemented, it is simply considered a nop.
|
35
|
+
* IMPROVED: `Toys::Utils::Terminal` is now thread-safe.
|
36
|
+
* CHANGED: `Toys::Utils::Terminal#styled` is no longer mutable.
|
37
|
+
* CHANGED: `Toys::Tool#middleware_stack` renamed to `Toys::Tool#built_middleware` to clarify that it is an array of middleware objects rather than specs.
|
38
|
+
* CHANGED: `Toys::CLI.default_logger` removed and replaced with `Toys::CLI.default_logger_factory`. In general, global loggers for CLI are now discouraged because they are not thread-safe.
|
39
|
+
* CHANGED: `Toys::Loader` uses an internal monitor rather than including `MonitorMixin`.
|
40
|
+
|
41
|
+
### 0.9.4 / 2020-01-26
|
42
|
+
|
43
|
+
* FIXED: Crash in the loader when a non-ruby file appears in a toys directory
|
44
|
+
|
45
|
+
### 0.9.3 / 2020-01-05
|
46
|
+
|
47
|
+
* FIXED: `delegate_to` directive could crash if an overriding tool has already been defined.
|
48
|
+
* FIXED: A Ruby 2.7 warning when reporting a Toys file syntax error.
|
49
|
+
|
3
50
|
### 0.9.2 / 2020-01-03
|
4
51
|
|
5
52
|
* IMPROVED: Mixins can now take real keyword arguments, and will pass them on properly to `on_initialize` and `on_include` blocks.
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -74,7 +74,7 @@ use to write Toys files. You could point your executable at a directory
|
|
74
74
|
containing actual Toys files, but the simplest option is to provide the
|
75
75
|
information to the Toys CLI object in a block.
|
76
76
|
|
77
|
-
Let's add some functionality.
|
77
|
+
Let's add some functionality.
|
78
78
|
|
79
79
|
#!/usr/bin/env ruby
|
80
80
|
|
@@ -150,7 +150,7 @@ available tools.
|
|
150
150
|
$ ./mycmd
|
151
151
|
|
152
152
|
Notice that the description set at the "root" of the config block (outside the
|
153
|
-
tool blocks) shows up here.
|
153
|
+
tool blocks) shows up here.
|
154
154
|
|
155
155
|
### Configuring the CLI
|
156
156
|
|
@@ -338,7 +338,7 @@ templates, and middleware, in the
|
|
338
338
|
|
339
339
|
## License
|
340
340
|
|
341
|
-
Copyright 2019 Daniel Azuma
|
341
|
+
Copyright 2019-2020 Daniel Azuma and the Toys contributors
|
342
342
|
|
343
343
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
344
344
|
of this software and associated documentation files (the "Software"), to deal
|
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
|
##
|
25
4
|
# Toys is a configurable command line tool. Write commands in config files
|
26
5
|
# using a simple DSL, and Toys will provide the command line executable and
|
@@ -68,6 +47,20 @@ module Toys
|
|
68
47
|
# `require "toys/utils/exec"`.
|
69
48
|
#
|
70
49
|
module Utils; end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
##
|
53
|
+
# Path to the executable. This can, for example, be invoked to run a subtool
|
54
|
+
# in a clean environment.
|
55
|
+
#
|
56
|
+
# @return [String] if there is an executable
|
57
|
+
# @return [nil] if there is no such executable
|
58
|
+
#
|
59
|
+
attr_accessor :executable_path
|
60
|
+
end
|
61
|
+
|
62
|
+
# @private
|
63
|
+
CORE_LIB_PATH = __dir__
|
71
64
|
end
|
72
65
|
|
73
66
|
require "toys/acceptor"
|
data/lib/toys/acceptor.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
|
# An Acceptor validates and converts arguments. It is designed to be
|
data/lib/toys/arg_parser.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
|
# An internal class that parses command line arguments for a tool.
|
@@ -444,7 +423,7 @@ module Toys
|
|
444
423
|
Context::Key::ARGS => nil,
|
445
424
|
Context::Key::CLI => cli,
|
446
425
|
Context::Key::CONTEXT_DIRECTORY => tool.context_directory,
|
447
|
-
Context::Key::LOGGER => cli.
|
426
|
+
Context::Key::LOGGER => cli.logger_factory.call(tool),
|
448
427
|
Context::Key::TOOL => tool,
|
449
428
|
Context::Key::TOOL_SOURCE => tool.source_info,
|
450
429
|
Context::Key::TOOL_NAME => tool.full_name,
|
data/lib/toys/cli.rb
CHANGED
@@ -1,26 +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
|
-
;
|
23
|
-
|
3
|
+
require "rbconfig"
|
24
4
|
require "logger"
|
25
5
|
require "toys/completion"
|
26
6
|
|
@@ -71,7 +51,8 @@ module Toys
|
|
71
51
|
# roughly into four categories:
|
72
52
|
#
|
73
53
|
# * Options affecting output behavior:
|
74
|
-
# * `logger`:
|
54
|
+
# * `logger`: A global logger for all tools to use
|
55
|
+
# * `logger_factory`: A proc that returns a logger to use
|
75
56
|
# * `base_level`: The default log level
|
76
57
|
# * `error_handler`: Callback for handling exceptions
|
77
58
|
# * `executable_name`: The name of the executable
|
@@ -91,10 +72,17 @@ module Toys
|
|
91
72
|
# * `preload_dir_name`: Name of preload directories in tool directories
|
92
73
|
# * `data_dir_name`: Name of data directories in tool directories
|
93
74
|
#
|
94
|
-
# @param logger [Logger]
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
75
|
+
# @param logger [Logger] A global logger to use for all tools. This may be
|
76
|
+
# set if the CLI will call at most one tool at a time. However, it will
|
77
|
+
# behave incorrectly if CLI might run multiple tools at the same time
|
78
|
+
# with different verbosity settings (since the logger cannot have
|
79
|
+
# multiple level settings simultaneously). In that case, do not set a
|
80
|
+
# global logger, but use the `logger_factory` parameter instead.
|
81
|
+
# @param logger_factory [Proc] A proc that takes a {Toys::Tool} as an
|
82
|
+
# argument, and returns a `Logger` to use when running that tool.
|
83
|
+
# Optional. If not provided (and no global logger is set), CLI will use
|
84
|
+
# a default factory that writes generates loggers writing formatted
|
85
|
+
# output to `STDERR`, as defined by {Toys::CLI.default_logger_factory}.
|
98
86
|
# @param base_level [Integer] The logger level that should correspond
|
99
87
|
# to zero verbosity.
|
100
88
|
# Optional. If not provided, defaults to the current level of the
|
@@ -181,13 +169,31 @@ module Toys
|
|
181
169
|
# path for any tool file in that directory.
|
182
170
|
# Optional. If not provided, data directories are disabled.
|
183
171
|
# Note: the standard toys executable sets this to `".data"`.
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
172
|
+
# @param lib_dir_name [String] A directory with this name that appears in
|
173
|
+
# any configuration directory is added to the Ruby load path when
|
174
|
+
# executing any tool file in that directory.
|
175
|
+
# Optional. If not provided, lib directories are disabled.
|
176
|
+
# Note: the standard toys executable sets this to `".lib"`.
|
177
|
+
#
|
178
|
+
def initialize( # rubocop:disable Metrics/MethodLength
|
179
|
+
executable_name: nil,
|
180
|
+
middleware_stack: nil,
|
181
|
+
extra_delimiters: "",
|
182
|
+
config_dir_name: nil,
|
183
|
+
config_file_name: nil,
|
184
|
+
index_file_name: nil,
|
185
|
+
preload_file_name: nil,
|
186
|
+
preload_dir_name: nil,
|
187
|
+
data_dir_name: nil,
|
188
|
+
lib_dir_name: nil,
|
189
|
+
mixin_lookup: nil,
|
190
|
+
middleware_lookup: nil,
|
191
|
+
template_lookup: nil,
|
192
|
+
logger_factory: nil,
|
193
|
+
logger: nil,
|
194
|
+
base_level: nil,
|
195
|
+
error_handler: nil,
|
196
|
+
completion: nil
|
191
197
|
)
|
192
198
|
@executable_name = executable_name || ::File.basename($PROGRAM_NAME)
|
193
199
|
@middleware_stack = middleware_stack || CLI.default_middleware_stack
|
@@ -196,8 +202,9 @@ module Toys
|
|
196
202
|
@template_lookup = template_lookup || CLI.default_template_lookup
|
197
203
|
@error_handler = error_handler || DefaultErrorHandler.new
|
198
204
|
@completion = completion || DefaultCompletion.new
|
199
|
-
@logger = logger
|
200
|
-
@
|
205
|
+
@logger = logger
|
206
|
+
@logger_factory = logger ? proc { logger } : logger_factory || CLI.default_logger_factory
|
207
|
+
@base_level = base_level
|
201
208
|
@extra_delimiters = extra_delimiters
|
202
209
|
@config_dir_name = config_dir_name
|
203
210
|
@config_file_name = config_file_name
|
@@ -205,12 +212,18 @@ module Toys
|
|
205
212
|
@preload_file_name = preload_file_name
|
206
213
|
@preload_dir_name = preload_dir_name
|
207
214
|
@data_dir_name = data_dir_name
|
215
|
+
@lib_dir_name = lib_dir_name
|
208
216
|
@loader = Loader.new(
|
209
|
-
index_file_name: @index_file_name,
|
210
|
-
preload_dir_name: @preload_dir_name,
|
217
|
+
index_file_name: @index_file_name,
|
218
|
+
preload_dir_name: @preload_dir_name,
|
219
|
+
preload_file_name: @preload_file_name,
|
211
220
|
data_dir_name: @data_dir_name,
|
212
|
-
|
213
|
-
|
221
|
+
lib_dir_name: @lib_dir_name,
|
222
|
+
middleware_stack: @middleware_stack,
|
223
|
+
extra_delimiters: @extra_delimiters,
|
224
|
+
mixin_lookup: @mixin_lookup,
|
225
|
+
template_lookup: @template_lookup,
|
226
|
+
middleware_lookup: @middleware_lookup
|
214
227
|
)
|
215
228
|
end
|
216
229
|
|
@@ -235,12 +248,14 @@ module Toys
|
|
235
248
|
preload_dir_name: @preload_dir_name,
|
236
249
|
preload_file_name: @preload_file_name,
|
237
250
|
data_dir_name: @data_dir_name,
|
251
|
+
lib_dir_name: @lib_dir_name,
|
238
252
|
middleware_stack: @middleware_stack,
|
239
253
|
extra_delimiters: @extra_delimiters,
|
240
254
|
mixin_lookup: @mixin_lookup,
|
241
255
|
middleware_lookup: @middleware_lookup,
|
242
256
|
template_lookup: @template_lookup,
|
243
257
|
logger: @logger,
|
258
|
+
logger_factory: @logger_factory,
|
244
259
|
base_level: @base_level,
|
245
260
|
error_handler: @error_handler,
|
246
261
|
completion: @completion,
|
@@ -269,14 +284,21 @@ module Toys
|
|
269
284
|
attr_reader :extra_delimiters
|
270
285
|
|
271
286
|
##
|
272
|
-
# The logger
|
273
|
-
# @return [Logger]
|
287
|
+
# The global logger, if any.
|
288
|
+
# @return [Logger,nil]
|
274
289
|
#
|
275
290
|
attr_reader :logger
|
276
291
|
|
292
|
+
##
|
293
|
+
# The logger factory.
|
294
|
+
# @return [Proc]
|
295
|
+
#
|
296
|
+
attr_reader :logger_factory
|
297
|
+
|
277
298
|
##
|
278
299
|
# The initial logger level in this CLI, used as the level for verbosity 0.
|
279
|
-
#
|
300
|
+
# May be `nil`, indicating it will use the initial logger setting.
|
301
|
+
# @return [Integer,nil]
|
280
302
|
#
|
281
303
|
attr_reader :base_level
|
282
304
|
|
@@ -432,19 +454,22 @@ module Toys
|
|
432
454
|
require_exact_flag_match: tool.exact_flag_match_required?)
|
433
455
|
arg_parser.parse(args).finish
|
434
456
|
context = tool.tool_class.new(arg_parser.data)
|
457
|
+
tool.source_info&.apply_lib_paths
|
435
458
|
tool.run_initializers(context)
|
436
459
|
|
437
|
-
cur_logger =
|
438
|
-
|
439
|
-
|
460
|
+
cur_logger = context[Context::Key::LOGGER]
|
461
|
+
if cur_logger
|
462
|
+
original_level = cur_logger.level
|
463
|
+
cur_logger.level = (base_level || original_level) - context[Context::Key::VERBOSITY].to_i
|
464
|
+
end
|
440
465
|
begin
|
441
|
-
|
466
|
+
execute_tool_in_context(context, tool)
|
442
467
|
ensure
|
443
|
-
cur_logger.level = original_level
|
468
|
+
cur_logger.level = original_level if cur_logger
|
444
469
|
end
|
445
470
|
end
|
446
471
|
|
447
|
-
def
|
472
|
+
def execute_tool_in_context(context, tool)
|
448
473
|
executor = proc do
|
449
474
|
begin
|
450
475
|
if !context[Context::Key::USAGE_ERRORS].empty?
|
@@ -459,7 +484,7 @@ module Toys
|
|
459
484
|
handle_interrupt(context, tool.interrupt_handler, e)
|
460
485
|
end
|
461
486
|
end
|
462
|
-
tool.
|
487
|
+
tool.built_middleware.reverse_each do |middleware|
|
463
488
|
executor = make_executor(middleware, context, executor)
|
464
489
|
end
|
465
490
|
catch(:result) do
|
@@ -493,7 +518,11 @@ module Toys
|
|
493
518
|
end
|
494
519
|
|
495
520
|
def make_executor(middleware, context, next_executor)
|
496
|
-
|
521
|
+
if middleware.respond_to?(:run)
|
522
|
+
proc { middleware.run(context, &next_executor) }
|
523
|
+
else
|
524
|
+
next_executor
|
525
|
+
end
|
497
526
|
end
|
498
527
|
|
499
528
|
##
|
@@ -646,30 +675,33 @@ module Toys
|
|
646
675
|
end
|
647
676
|
|
648
677
|
##
|
649
|
-
# Returns a
|
678
|
+
# Returns a logger factory that generates loggers that write to stderr.
|
679
|
+
# All loggers generated by this factory share a single
|
680
|
+
# {Toys::Utils::Terminal}, so log entries may interleave but will not
|
681
|
+
# interrupt one another.
|
650
682
|
#
|
651
|
-
# @
|
652
|
-
# @return [Logger]
|
683
|
+
# @return [Proc]
|
653
684
|
#
|
654
|
-
def
|
685
|
+
def default_logger_factory
|
655
686
|
require "toys/utils/terminal"
|
656
|
-
output
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
687
|
+
shared_terminal = Utils::Terminal.new(output: $stderr)
|
688
|
+
proc do
|
689
|
+
logger = ::Logger.new(shared_terminal)
|
690
|
+
logger.formatter = proc do |severity, time, _progname, msg|
|
691
|
+
msg_str =
|
692
|
+
case msg
|
693
|
+
when ::String
|
694
|
+
msg
|
695
|
+
when ::Exception
|
696
|
+
"#{msg.message} (#{msg.class})\n" << (msg.backtrace || []).join("\n")
|
697
|
+
else
|
698
|
+
msg.inspect
|
699
|
+
end
|
700
|
+
format_log(shared_terminal, time, severity, msg_str)
|
701
|
+
end
|
702
|
+
logger.level = ::Logger::WARN
|
703
|
+
logger
|
670
704
|
end
|
671
|
-
logger.level = ::Logger::WARN
|
672
|
-
logger
|
673
705
|
end
|
674
706
|
|
675
707
|
private
|