toys-core 0.24.0 → 0.25.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 +23 -0
- data/docs/guide.md +6 -3
- data/lib/toys/arg_parser.rb +2 -1
- data/lib/toys/cli.rb +10 -5
- data/lib/toys/compat.rb +111 -105
- data/lib/toys/core.rb +1 -1
- data/lib/toys/flag.rb +4 -2
- data/lib/toys/runner.rb +36 -10
- data/lib/toys/standard_middleware/handle_usage_errors.rb +3 -2
- data/lib/toys/standard_middleware/show_help.rb +7 -5
- data/lib/toys/standard_mixins/highline.rb +9 -2
- data/lib/toys/utils/git_cache.rb +165 -72
- data/lib/toys/utils/pager.rb +41 -9
- data/lib/toys/utils/standard_ui.rb +152 -23
- data/lib/toys/utils/terminal.rb +49 -2
- data/lib/toys/utils/xdg.rb +22 -2
- data/lib/toys/warnings.rb +161 -0
- data/lib/toys-core.rb +3 -1
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c9a692b91f8fcd9e2aee00a360ac14b676ec1876bbf889468440e3827ce8877b
|
|
4
|
+
data.tar.gz: 6fc4cbd7769db055405a17be755dd0dc0e9612f9e5fd00451c3a1480c2924c6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f3850a2d2d3eaf18f9ace3730a4bc34355400b8ff75308e0e739d77a5e664a7377c0fa9bacbd9726be3b99fc4bb5c5c6e742f5171d3ff4185dab90fe50f61f5
|
|
7
|
+
data.tar.gz: f0337ba0809e6e56f233fe22f2e4b423f19b36df4f1163498c8bd1ef6e545301bbbb0e51b12a92a2f218d001d5a9092e739ff088ea5caf6547e07568c4692a04
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### v0.25.0 / 2026-10-10
|
|
4
|
+
|
|
5
|
+
This is a release candidate release toward version 1.0. It includes a variety of fixes and small features, largely around adherence to clig.dev and other common CLI guidelines.
|
|
6
|
+
|
|
7
|
+
* ADDED: Added `Toys::Utils::Terminal.infer_styled`, the rule a terminal uses to decide whether to style output
|
|
8
|
+
* ADDED: The `FORCE_COLOR` environment variable forces styled output on, or off when set to 0 or false
|
|
9
|
+
* ADDED: The `show_help` middleware includes `-h` in the default help flags
|
|
10
|
+
* ADDED: `StandardUI` logs with a simple severity prefix unless verbosity is positive
|
|
11
|
+
* ADDED: Issue warnings for deprecated interfaces
|
|
12
|
+
* ADDED: `Utils::Pager` supports an output option
|
|
13
|
+
* FIXED: The `:push` handler creates a new array rather than appending in place, so that a frozen or non-cloneable default doesn't cause problems
|
|
14
|
+
* FIXED: An empty `NO_COLOR` environment variable no longer disables styled output, per the no-color.org spec
|
|
15
|
+
* FIXED: Styled output is disabled when the `TERM` environment variable is set to `dumb`
|
|
16
|
+
* FIXED: The highline mixin decides whether to use color from its own output stream, and honors `NO_COLOR`, `FORCE_COLOR`, and `TERM=dumb`
|
|
17
|
+
* FIXED: Help text displayed through a pager honors the styled output setting, including `NO_COLOR`, `FORCE_COLOR`, and `TERM=dumb`
|
|
18
|
+
* FIXED: Tool-not-found suggestions include namespaces
|
|
19
|
+
* FIXED: Tool initializers run within the logger level implied by the verbosity
|
|
20
|
+
* FIXED: `StandardUI` no longer colors the `DEBUG` log header
|
|
21
|
+
* FIXED: Re-vendor `simple_xdg` 0.1.2 to pick up home directory fix
|
|
22
|
+
* FIXED: Re-vendor `git_cache` 0.2.0 to report an unwritable cache directory clearly and fix repo lock races
|
|
23
|
+
* FIXED: Show_help writes paged help to the configured stream
|
|
24
|
+
* DOCS: Documentation no longer references a few obsolete features such as the `TOYS_PATH` variable
|
|
25
|
+
|
|
3
26
|
### v0.24.0 / 2026-09-11
|
|
4
27
|
|
|
5
28
|
Feature updates:
|
data/docs/guide.md
CHANGED
|
@@ -705,7 +705,8 @@ cli = Toys::CLI.new(logger_factory: my_logger_factory)
|
|
|
705
705
|
#### StandardUI logging
|
|
706
706
|
|
|
707
707
|
{Toys::Utils::StandardUI} implements the logger used by the `toys` gem, which
|
|
708
|
-
formats log entries with
|
|
708
|
+
formats log entries with a severity prefix using ANSI coloring, and adds a
|
|
709
|
+
timestamp when the tool is run with positive verbosity.
|
|
709
710
|
|
|
710
711
|
You can use this logger by passing the proc returned by
|
|
711
712
|
{Toys::Utils::StandardUI#logger_factory_proc} to the CLI constructor:
|
|
@@ -718,8 +719,10 @@ cli = Toys::CLI.new(logger_factory: standard_ui.logger_factory_proc)
|
|
|
718
719
|
You can also customize the logger by subclassing StandardUI and overriding its
|
|
719
720
|
methods or adjusting its parameters. In particular, you can alter the
|
|
720
721
|
{Toys::Utils::StandardUI#log_header_severity_styles} mapping to adjust styling,
|
|
721
|
-
or override {Toys::Utils::StandardUI#create_logger}
|
|
722
|
-
{Toys::Utils::StandardUI#
|
|
722
|
+
or override {Toys::Utils::StandardUI#create_logger},
|
|
723
|
+
{Toys::Utils::StandardUI#verbose_log_format?},
|
|
724
|
+
{Toys::Utils::StandardUI#format_simple_log_entry}, or
|
|
725
|
+
{Toys::Utils::StandardUI#format_verbose_log_entry} to adjust content and
|
|
723
726
|
formatting.
|
|
724
727
|
|
|
725
728
|
### Handling errors
|
data/lib/toys/arg_parser.rb
CHANGED
|
@@ -641,7 +641,8 @@ module Toys
|
|
|
641
641
|
if @tool.runnable? || !@seen_flags.empty?
|
|
642
642
|
ExtraArgumentsError.new(arguments: @unmatched_positional)
|
|
643
643
|
else
|
|
644
|
-
|
|
644
|
+
subtools = @loader.list_subtools(@tool.full_name, include_namespaces: true)
|
|
645
|
+
dictionary = subtools.map(&:simple_name)
|
|
645
646
|
first_arg = @unmatched_positional.first
|
|
646
647
|
ToolUnrecognizedError.new(full_name: @tool.full_name + [first_arg],
|
|
647
648
|
suggestions: Compat.suggestions(first_arg, dictionary))
|
data/lib/toys/cli.rb
CHANGED
|
@@ -88,6 +88,8 @@ module Toys
|
|
|
88
88
|
# as an argument, and returns a `Logger` to use when running that tool.
|
|
89
89
|
# Optional. If not provided (and no global logger is set),
|
|
90
90
|
# {Toys::CLI.default_logger_factory} is called to get a basic default.
|
|
91
|
+
# See {Toys::Runner} for how a logger can receive the verbosity of
|
|
92
|
+
# the run.
|
|
91
93
|
# @param base_level [Integer] The logger level that should correspond
|
|
92
94
|
# to zero verbosity.
|
|
93
95
|
# Optional. If not provided, defaults to the level the logger has
|
|
@@ -351,8 +353,8 @@ module Toys
|
|
|
351
353
|
# source list. If the given search directory path does not exist or does
|
|
352
354
|
# not contain either the file or directory, nothing is added.
|
|
353
355
|
#
|
|
354
|
-
# The main Toys executable uses this method to load tools from
|
|
355
|
-
# in the
|
|
356
|
+
# The main Toys executable uses this method to load tools from the
|
|
357
|
+
# directories in its upward walk and from the home directory.
|
|
356
358
|
#
|
|
357
359
|
# @param search_path [String,Pathname] A directory path to search for the
|
|
358
360
|
# well-known source file and directory. Must be a String or a Pathname.
|
|
@@ -405,9 +407,6 @@ module Toys
|
|
|
405
407
|
# given directory and works up through parent directories until it reaches
|
|
406
408
|
# the file system root or it encounters one of the "terminate" directories.
|
|
407
409
|
#
|
|
408
|
-
# The main Toys executable uses this method to load tools from the current
|
|
409
|
-
# directory and its ancestors.
|
|
410
|
-
#
|
|
411
410
|
# @param start [String,Pathname,nil] The first directory path to search.
|
|
412
411
|
# If not given, defaults to the current working directory. If provided,
|
|
413
412
|
# must be a String or a Pathname. Paths should generally be absolute.
|
|
@@ -581,6 +580,9 @@ module Toys
|
|
|
581
580
|
high_priority: false,
|
|
582
581
|
source_name: nil,
|
|
583
582
|
context_directory: :parent)
|
|
583
|
+
Warnings.warn(:add_config_path_deprecated,
|
|
584
|
+
"CLI#add_config_path is deprecated. Use add_source instead.",
|
|
585
|
+
uplevel: 1)
|
|
584
586
|
path = SourceSpec.check_and_normalize_path(path)
|
|
585
587
|
context_directory = resolve_context_directory(context_directory, path)
|
|
586
588
|
spec = SourceSpec.path(path, source_name: source_name, context_directory: context_directory)
|
|
@@ -631,6 +633,9 @@ module Toys
|
|
|
631
633
|
source_name: nil,
|
|
632
634
|
context_directory: nil,
|
|
633
635
|
&block)
|
|
636
|
+
Warnings.warn(:add_config_block_deprecated,
|
|
637
|
+
"CLI#add_config_block is deprecated. Use add_source instead.",
|
|
638
|
+
uplevel: 1)
|
|
634
639
|
spec = SourceSpec.block(source_name: source_name, context_directory: context_directory, &block)
|
|
635
640
|
add_source(spec, high_priority: high_priority)
|
|
636
641
|
end
|
data/lib/toys/compat.rb
CHANGED
|
@@ -22,127 +22,133 @@ module Toys
|
|
|
22
22
|
#
|
|
23
23
|
RUBY_VERSION_CODE = ruby_version
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
class << self
|
|
26
|
+
##
|
|
27
|
+
# @private
|
|
28
|
+
# Whether the current Ruby implementation is JRuby
|
|
29
|
+
#
|
|
30
|
+
# @return [boolean]
|
|
31
|
+
#
|
|
32
|
+
def jruby?
|
|
33
|
+
::RUBY_ENGINE == "jruby"
|
|
34
|
+
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
##
|
|
37
|
+
# @private
|
|
38
|
+
# Whether the current Ruby implementation is TruffleRuby
|
|
39
|
+
#
|
|
40
|
+
# @return [boolean]
|
|
41
|
+
#
|
|
42
|
+
def truffleruby?
|
|
43
|
+
::RUBY_ENGINE == "truffleruby"
|
|
44
|
+
end
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
##
|
|
47
|
+
# @private
|
|
48
|
+
# Whether we are running on Windows
|
|
49
|
+
#
|
|
50
|
+
# @return [boolean]
|
|
51
|
+
#
|
|
52
|
+
def windows?
|
|
53
|
+
::RbConfig::CONFIG["host_os"] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
54
|
+
end
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
##
|
|
57
|
+
# @private
|
|
58
|
+
# Whether we are running on Mac OS
|
|
59
|
+
#
|
|
60
|
+
# @return [boolean]
|
|
61
|
+
#
|
|
62
|
+
def macos?
|
|
63
|
+
::RbConfig::CONFIG["host_os"] =~ /darwin/
|
|
64
|
+
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
##
|
|
67
|
+
# @private
|
|
68
|
+
# Whether fork is supported on the current Ruby and OS
|
|
69
|
+
#
|
|
70
|
+
# @return [boolean]
|
|
71
|
+
#
|
|
72
|
+
def allow_fork?
|
|
73
|
+
!jruby? && !truffleruby? && !windows?
|
|
74
|
+
end
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
begin
|
|
85
|
-
require "did_you_mean"
|
|
86
|
-
rescue ::LoadError
|
|
87
|
-
require "rubygems"
|
|
76
|
+
##
|
|
77
|
+
# @private
|
|
78
|
+
# Whether it is possible to get suggestions from DidYouMean. If this
|
|
79
|
+
# returns false, {Compat.suggestions} will always return the empty array.
|
|
80
|
+
#
|
|
81
|
+
# @return [boolean]
|
|
82
|
+
#
|
|
83
|
+
def supports_suggestions?
|
|
84
|
+
unless defined?(@supports_suggestions)
|
|
88
85
|
begin
|
|
89
86
|
require "did_you_mean"
|
|
90
87
|
rescue ::LoadError
|
|
91
|
-
|
|
88
|
+
require "rubygems"
|
|
89
|
+
begin
|
|
90
|
+
require "did_you_mean"
|
|
91
|
+
rescue ::LoadError
|
|
92
|
+
# Oh well, it's not available
|
|
93
|
+
end
|
|
92
94
|
end
|
|
95
|
+
@supports_suggestions = defined?(::DidYouMean::SpellChecker)
|
|
93
96
|
end
|
|
94
|
-
@supports_suggestions
|
|
97
|
+
@supports_suggestions
|
|
95
98
|
end
|
|
96
|
-
@supports_suggestions
|
|
97
|
-
end
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
100
|
+
##
|
|
101
|
+
# @private
|
|
102
|
+
# A list of suggestions from DidYouMean.
|
|
103
|
+
#
|
|
104
|
+
# @param word [String] A value that seems wrong
|
|
105
|
+
# @param list [Array<String>] A list of valid values
|
|
106
|
+
#
|
|
107
|
+
# @return [Array<String>] A possibly empty array of suggestions from the
|
|
108
|
+
# valid list that could match the given word.
|
|
109
|
+
#
|
|
110
|
+
def suggestions(word, list)
|
|
111
|
+
if supports_suggestions?
|
|
112
|
+
::DidYouMean::SpellChecker.new(dictionary: list).correct(word)
|
|
113
|
+
else
|
|
114
|
+
[]
|
|
115
|
+
end
|
|
114
116
|
end
|
|
115
|
-
end
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
118
|
+
##
|
|
119
|
+
# @private
|
|
120
|
+
# A list of gems that should generally not be included in a bundle,
|
|
121
|
+
# usually because the Ruby implementation handles the library specially
|
|
122
|
+
# and cannot install the real gem. Currently, this includes the
|
|
123
|
+
# `pathname` gem for TruffleRuby, since TruffleRuby includes a special
|
|
124
|
+
# version of it.
|
|
125
|
+
#
|
|
126
|
+
# @return [Array<String>]
|
|
127
|
+
#
|
|
128
|
+
def gems_to_omit_from_bundles
|
|
129
|
+
if truffleruby?
|
|
130
|
+
["pathname"]
|
|
131
|
+
else
|
|
132
|
+
[]
|
|
133
|
+
end
|
|
131
134
|
end
|
|
132
|
-
end
|
|
133
135
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
136
|
+
##
|
|
137
|
+
# @private
|
|
138
|
+
# Sets the backtrace on an exception. In Ruby `< 3.4`,
|
|
139
|
+
# `Exception#set_backtrace` required a string array, whereas in newer
|
|
140
|
+
# Rubies, it would accept an array of backtrace locations.
|
|
141
|
+
#
|
|
142
|
+
# @param [Exception] exception
|
|
143
|
+
# @param [nil,Array<String>,Array<Thread::Backtrace::Location>] backtrace
|
|
144
|
+
#
|
|
145
|
+
# @return [Exception] The modified exception
|
|
146
|
+
#
|
|
147
|
+
def set_backtrace(exception, backtrace)
|
|
148
|
+
backtrace = backtrace.map(&:to_s) if RUBY_VERSION_CODE < 30400 && !backtrace.nil?
|
|
149
|
+
exception.set_backtrace(backtrace)
|
|
150
|
+
exception
|
|
151
|
+
end
|
|
146
152
|
end
|
|
147
153
|
end
|
|
148
154
|
end
|
data/lib/toys/core.rb
CHANGED
data/lib/toys/flag.rb
CHANGED
|
@@ -377,10 +377,12 @@ module Toys
|
|
|
377
377
|
SET_HANDLER = proc { |val| val }
|
|
378
378
|
|
|
379
379
|
##
|
|
380
|
-
# The push handler
|
|
380
|
+
# The push handler appends the given value, returning a new array. The
|
|
381
|
+
# previous array is not modified, so a shared or frozen default array
|
|
382
|
+
# can be used safely.
|
|
381
383
|
# @return [Proc]
|
|
382
384
|
#
|
|
383
|
-
PUSH_HANDLER = proc { |val, prev| prev.nil? ? [val] : prev
|
|
385
|
+
PUSH_HANDLER = proc { |val, prev| prev.nil? ? [val] : prev + [val] }
|
|
384
386
|
|
|
385
387
|
##
|
|
386
388
|
# The default handler is the set handler, which replaces the previous value.
|
data/lib/toys/runner.rb
CHANGED
|
@@ -38,6 +38,15 @@ module Toys
|
|
|
38
38
|
# end
|
|
39
39
|
# end
|
|
40
40
|
#
|
|
41
|
+
# While a tool runs, the Runner sets the level of the tool's logger to reflect
|
|
42
|
+
# the verbosity, as described under the `base_level` parameter of
|
|
43
|
+
# {#initialize}. A logger can also receive the verbosity itself, by
|
|
44
|
+
# implementing a `verbosity` attribute: if the logger responds to both
|
|
45
|
+
# `verbosity` and `verbosity=`, the Runner sets it to the verbosity (an
|
|
46
|
+
# Integer) for the duration of the run, and restores the previous value
|
|
47
|
+
# afterward. This lets a logger vary its behavior, such as its formatting, by
|
|
48
|
+
# verbosity independently of its level.
|
|
49
|
+
#
|
|
41
50
|
class Runner
|
|
42
51
|
##
|
|
43
52
|
# The singleton default logger_factory Proc, which simply returns a new
|
|
@@ -74,7 +83,8 @@ module Toys
|
|
|
74
83
|
# @param logger_factory [Proc,nil] A proc that takes a
|
|
75
84
|
# {Toys::ToolDefinition} as an argument, and returns a logger to use
|
|
76
85
|
# when running that tool. If not given,
|
|
77
|
-
# {Toys::Runner::DEFAULT_LOGGER_FACTORY} is used.
|
|
86
|
+
# {Toys::Runner::DEFAULT_LOGGER_FACTORY} is used. See {Toys::Runner}
|
|
87
|
+
# for how a logger can receive the verbosity of the run.
|
|
78
88
|
# @param base_level [Integer,nil] The logger level that corresponds to zero
|
|
79
89
|
# verbosity. If not provided, the level the logger has before a run
|
|
80
90
|
# adjusts it is used (typically Logger::WARN). A run nested inside
|
|
@@ -404,15 +414,15 @@ module Toys
|
|
|
404
414
|
end
|
|
405
415
|
|
|
406
416
|
# Prepares the runtime environment for the tool, applying lib paths and
|
|
407
|
-
# initializers, and then calls the tool within its middleware stack
|
|
408
|
-
#
|
|
409
|
-
#
|
|
417
|
+
# initializers, and then calls the tool within its middleware stack,
|
|
418
|
+
# returning the resulting exit code. The initializers and the tool both
|
|
419
|
+
# run within the logger level implied by the verbosity.
|
|
410
420
|
def execute_tool(context, &block)
|
|
411
421
|
@tool.source_info&.find_lib_paths&.reverse_each do |path|
|
|
412
422
|
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
|
413
423
|
end
|
|
414
|
-
@tool.run_initializers(context)
|
|
415
424
|
with_logger_level(context) do
|
|
425
|
+
@tool.run_initializers(context)
|
|
416
426
|
executor = build_executor(context, &block)
|
|
417
427
|
catch(:result) do
|
|
418
428
|
executor.call
|
|
@@ -426,23 +436,39 @@ module Toys
|
|
|
426
436
|
# afterward. The restoration must cover the level assignment itself,
|
|
427
437
|
# because a base level that cannot be combined with the verbosity fails
|
|
428
438
|
# there, and a base level left recorded behind a failed run would be
|
|
429
|
-
# picked up by later runs sharing the logger.
|
|
430
|
-
#
|
|
431
|
-
|
|
439
|
+
# picked up by later runs sharing the logger. Also sets the verbosity on
|
|
440
|
+
# a logger that supports it, as described in {Runner}. Yields directly if
|
|
441
|
+
# the tool has no logger.
|
|
442
|
+
def with_logger_level(context, &block)
|
|
432
443
|
cur_logger = context[Context::Key::LOGGER]
|
|
433
444
|
return yield unless cur_logger
|
|
445
|
+
verbosity = context[Context::Key::VERBOSITY].to_i
|
|
434
446
|
original_level = cur_logger.level
|
|
435
447
|
base_level = @base_level || base_levels[cur_logger] || original_level
|
|
436
448
|
saved_base_level = set_base_level(cur_logger, base_level)
|
|
437
449
|
begin
|
|
438
|
-
cur_logger.level = base_level -
|
|
439
|
-
|
|
450
|
+
cur_logger.level = base_level - verbosity
|
|
451
|
+
with_logger_verbosity(cur_logger, verbosity, &block)
|
|
440
452
|
ensure
|
|
441
453
|
set_base_level(cur_logger, saved_base_level)
|
|
442
454
|
cur_logger.level = original_level
|
|
443
455
|
end
|
|
444
456
|
end
|
|
445
457
|
|
|
458
|
+
# Sets the verbosity on a logger that supports it for the duration of
|
|
459
|
+
# the block, and restores it afterward. Yields directly if the logger
|
|
460
|
+
# does not have both a reader and a writer for the verbosity.
|
|
461
|
+
def with_logger_verbosity(logger, verbosity)
|
|
462
|
+
return yield unless logger.respond_to?(:verbosity) && logger.respond_to?(:verbosity=)
|
|
463
|
+
original_verbosity = logger.verbosity
|
|
464
|
+
begin
|
|
465
|
+
logger.verbosity = verbosity
|
|
466
|
+
yield
|
|
467
|
+
ensure
|
|
468
|
+
logger.verbosity = original_verbosity
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
446
472
|
# The base levels currently in effect on this thread, keyed by logger
|
|
447
473
|
# identity. A run that adjusts a logger's level records the base
|
|
448
474
|
# level it used, for the extent of that run, because a nested run cannot
|
|
@@ -22,8 +22,9 @@ module Toys
|
|
|
22
22
|
# occurs. Default is {USAGE_ERROR_EXIT_CODE}.
|
|
23
23
|
# @param stream [IO] Output stream to write to. Default is stderr.
|
|
24
24
|
# @param styled_output [boolean,nil] Cause the tool to display help text
|
|
25
|
-
# with ansi styles. If `nil`, display styles
|
|
26
|
-
#
|
|
25
|
+
# with ansi styles. If `nil`, whether to display styles is inferred
|
|
26
|
+
# from the output stream and the environment. See
|
|
27
|
+
# {Toys::Utils::Terminal.infer_styled}. Default is `nil`.
|
|
27
28
|
#
|
|
28
29
|
def initialize(exit_code: nil, stream: $stderr, styled_output: nil)
|
|
29
30
|
@exit_code = exit_code || USAGE_ERROR_EXIT_CODE
|
|
@@ -17,7 +17,7 @@ module Toys
|
|
|
17
17
|
# Default help flags
|
|
18
18
|
# @return [Array<String>]
|
|
19
19
|
#
|
|
20
|
-
DEFAULT_HELP_FLAGS = ["-?", "--help"].freeze
|
|
20
|
+
DEFAULT_HELP_FLAGS = ["-h", "-?", "--help"].freeze
|
|
21
21
|
|
|
22
22
|
##
|
|
23
23
|
# Default usage flags
|
|
@@ -165,8 +165,9 @@ module Toys
|
|
|
165
165
|
# false) if the output stream is not a tty.
|
|
166
166
|
# @param stream [IO] Output stream to write to. Default is stdout.
|
|
167
167
|
# @param styled_output [boolean,nil] Cause the tool to display help text
|
|
168
|
-
# with ansi styles. If `nil`, display styles
|
|
169
|
-
#
|
|
168
|
+
# with ansi styles. If `nil`, whether to display styles is inferred
|
|
169
|
+
# from the output stream and the environment. See
|
|
170
|
+
# {Toys::Utils::Terminal.infer_styled}. Default is `nil`.
|
|
170
171
|
#
|
|
171
172
|
def initialize(help_flags: false,
|
|
172
173
|
usage_flags: false,
|
|
@@ -297,10 +298,11 @@ module Toys
|
|
|
297
298
|
include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
|
|
298
299
|
show_source_path: @show_source_path,
|
|
299
300
|
separate_sources: @separate_sources,
|
|
300
|
-
wrap_width: terminal.width
|
|
301
|
+
wrap_width: terminal.width,
|
|
302
|
+
styled: terminal.styled
|
|
301
303
|
)
|
|
302
304
|
require "toys/utils/pager"
|
|
303
|
-
Utils::Pager.start(command: @use_pager, fallback_io: terminal) do |io|
|
|
305
|
+
Utils::Pager.start(command: @use_pager, output: @stream, fallback_io: terminal) do |io|
|
|
304
306
|
io.puts(str)
|
|
305
307
|
end
|
|
306
308
|
rescue Utils::HelpText::HelpGenerationError => e
|
|
@@ -27,6 +27,11 @@ module Toys
|
|
|
27
27
|
# The arguments will be passed on to the
|
|
28
28
|
# [HighLine constructor](https://www.rubydoc.info/gems/highline/HighLine:initialize).
|
|
29
29
|
#
|
|
30
|
+
# Whether the HighLine object uses color is inferred from its output
|
|
31
|
+
# stream and the environment, using the same rule as a terminal. See
|
|
32
|
+
# {Toys::Utils::Terminal.infer_styled}. You can override it by setting
|
|
33
|
+
# `use_color` on the HighLine object.
|
|
34
|
+
#
|
|
30
35
|
module Highline
|
|
31
36
|
include Mixin
|
|
32
37
|
|
|
@@ -131,10 +136,12 @@ module Toys
|
|
|
131
136
|
|
|
132
137
|
on_initialize do |*args|
|
|
133
138
|
require "toys/utils/gems"
|
|
139
|
+
require "toys/utils/terminal"
|
|
134
140
|
::Toys::Utils::Gems.activate("highline", "~> 2.0")
|
|
135
141
|
require "highline"
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
highline = ::HighLine.new(*args)
|
|
143
|
+
highline.use_color = ::Toys::Utils::Terminal.infer_styled(highline.output)
|
|
144
|
+
self[::Toys::StandardMixins::Highline::KEY] = highline
|
|
138
145
|
end
|
|
139
146
|
end
|
|
140
147
|
end
|