toys-core 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -1
- data/lib/toys-core.rb +2 -0
- data/lib/toys/cli.rb +108 -15
- data/lib/toys/config_dsl.rb +101 -55
- data/lib/toys/context.rb +3 -3
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/errors.rb +76 -0
- data/lib/toys/helpers/highline.rb +0 -2
- data/lib/toys/helpers/spinner.rb +17 -11
- data/lib/toys/loader.rb +43 -18
- data/lib/toys/middleware.rb +14 -14
- data/lib/toys/middleware/add_verbosity_flags.rb +113 -0
- data/lib/toys/middleware/base.rb +1 -1
- data/lib/toys/middleware/handle_usage_errors.rb +15 -9
- data/lib/toys/middleware/set_default_descriptions.rb +114 -37
- data/lib/toys/middleware/show_help.rb +245 -0
- data/lib/toys/middleware/show_version.rb +20 -16
- data/lib/toys/templates/clean.rb +4 -1
- data/lib/toys/templates/gem_build.rb +3 -1
- data/lib/toys/templates/minitest.rb +5 -6
- data/lib/toys/tool.rb +418 -213
- data/lib/toys/utils/help_text.rb +487 -0
- data/lib/toys/utils/line_output.rb +105 -0
- data/lib/toys/utils/wrappable_string.rb +67 -19
- metadata +6 -5
- data/lib/toys/middleware/add_verbosity_switches.rb +0 -99
- data/lib/toys/middleware/show_usage.rb +0 -174
- data/lib/toys/utils/usage.rb +0 -250
@@ -0,0 +1,105 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
require "highline"
|
31
|
+
|
32
|
+
module Toys
|
33
|
+
module Utils
|
34
|
+
##
|
35
|
+
# Something that outputs lines to the console or log.
|
36
|
+
#
|
37
|
+
class LineOutput
|
38
|
+
##
|
39
|
+
# Create a line output.
|
40
|
+
#
|
41
|
+
# @param [IO,Logger,nil] sink Where to write lines.
|
42
|
+
#
|
43
|
+
def initialize(sink, log_level: ::Logger::INFO, styled: nil)
|
44
|
+
@sink = sink
|
45
|
+
@log_level = sink.is_a?(::Logger) ? log_level : nil
|
46
|
+
@styled =
|
47
|
+
if styled.nil?
|
48
|
+
sink.respond_to?(:tty?) && sink.tty?
|
49
|
+
else
|
50
|
+
styled ? true : false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Where to write lines
|
56
|
+
# @return [IO,Logger,nil]
|
57
|
+
#
|
58
|
+
attr_reader :sink
|
59
|
+
|
60
|
+
##
|
61
|
+
# Whether output is styled
|
62
|
+
# @return [Boolean]
|
63
|
+
#
|
64
|
+
attr_reader :styled
|
65
|
+
|
66
|
+
##
|
67
|
+
# If the sink is a Logger, the level to log, otherwise `nil`.
|
68
|
+
# @return [Integer,nil]
|
69
|
+
#
|
70
|
+
attr_reader :log_level
|
71
|
+
|
72
|
+
##
|
73
|
+
# Write a line.
|
74
|
+
#
|
75
|
+
# @param [String] str The line to write
|
76
|
+
# @param [Symbol...] styles Styles to apply to the entire line.
|
77
|
+
#
|
78
|
+
def puts(str = "", *styles)
|
79
|
+
if styled
|
80
|
+
str = color(str, *styles) unless styles.empty?
|
81
|
+
else
|
82
|
+
str = ::HighLine.uncolor(str)
|
83
|
+
end
|
84
|
+
case sink
|
85
|
+
when ::Logger
|
86
|
+
sink.log(log_level, str)
|
87
|
+
when ::IO
|
88
|
+
sink.puts(str)
|
89
|
+
end
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Apply the given styles to a string
|
95
|
+
#
|
96
|
+
# @param [String] str The string
|
97
|
+
# @param [Symbol...] styles Styles to apply to the string.
|
98
|
+
# @return [String] The string with styles applied.
|
99
|
+
#
|
100
|
+
def color(str, *styles)
|
101
|
+
::HighLine.color(str, *styles)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -35,58 +35,106 @@ module Toys
|
|
35
35
|
class WrappableString
|
36
36
|
##
|
37
37
|
# Create a wrapped string.
|
38
|
-
# @param [String] string The string
|
38
|
+
# @param [String,Array<String>] string The string or array of string
|
39
|
+
# fragments
|
39
40
|
#
|
40
41
|
def initialize(string = "")
|
41
|
-
@
|
42
|
+
@fragments = string.is_a?(::Array) ? string.map(&:to_s) : string.to_s.split
|
42
43
|
end
|
43
44
|
|
44
45
|
##
|
45
|
-
# Returns the
|
46
|
+
# Returns the fragments.
|
47
|
+
# @return [Array<String>]
|
48
|
+
#
|
49
|
+
attr_reader :fragments
|
50
|
+
|
51
|
+
##
|
52
|
+
# Concatenates this WrappableString with another WrappableString
|
53
|
+
# @param [WrappableString] other
|
54
|
+
#
|
55
|
+
def +(other)
|
56
|
+
other = WrappableString.new(other) unless other.is_a?(WrappableString)
|
57
|
+
WrappableString.new(fragments + other.fragments)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Returns true if the string is empty (i.e. has no fragments)
|
46
62
|
# @return [String]
|
47
63
|
#
|
48
|
-
|
64
|
+
def empty?
|
65
|
+
@fragments.empty?
|
66
|
+
end
|
49
67
|
|
50
68
|
##
|
51
|
-
# Returns the string
|
69
|
+
# Returns the string without any wrapping
|
52
70
|
# @return [String]
|
53
71
|
#
|
54
72
|
def to_s
|
55
|
-
|
73
|
+
@fragments.join(" ")
|
56
74
|
end
|
75
|
+
alias string to_s
|
57
76
|
|
58
77
|
## @private
|
59
78
|
def ==(other)
|
60
|
-
other.is_a?(WrappableString)
|
79
|
+
return false unless other.is_a?(WrappableString)
|
80
|
+
other.fragments == fragments
|
61
81
|
end
|
62
82
|
alias eql? ==
|
63
83
|
|
64
84
|
## @private
|
65
85
|
def hash
|
66
|
-
|
86
|
+
fragments.hash
|
67
87
|
end
|
68
88
|
|
69
89
|
##
|
70
90
|
# Wraps the string to the given width.
|
71
91
|
#
|
72
|
-
# @param [Integer] width Width in characters.
|
92
|
+
# @param [Integer,nil] width Width in characters, or `nil` for infinite.
|
93
|
+
# @param [Integer,nil] width2 Width in characters for the second and
|
94
|
+
# subsequent lines, or `nil` to use the same as width.
|
73
95
|
# @return [Array<String>] Wrapped lines
|
74
96
|
#
|
75
|
-
def wrap(width)
|
97
|
+
def wrap(width, width2 = nil)
|
76
98
|
lines = []
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
99
|
+
line = ""
|
100
|
+
line_len = 0
|
101
|
+
fragments.each do |frag|
|
102
|
+
frag_len = ::HighLine.uncolor(frag).size
|
103
|
+
if line_len.zero?
|
104
|
+
line = frag
|
105
|
+
line_len = frag_len
|
106
|
+
elsif width && line_len + 1 + frag_len > width
|
107
|
+
lines << line
|
108
|
+
line = frag
|
109
|
+
line_len = frag_len
|
110
|
+
width = width2 if width2
|
111
|
+
else
|
112
|
+
line_len += frag_len + 1
|
113
|
+
line = "#{line} #{frag}"
|
84
114
|
end
|
85
|
-
lines << str[0, i]
|
86
|
-
str = str[i..-1].sub(/^\s+/, "")
|
87
115
|
end
|
116
|
+
lines << line if line_len > 0
|
88
117
|
lines
|
89
118
|
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Wraps an array of lines to the given width.
|
122
|
+
#
|
123
|
+
# @param [Array<WrappableString>] strs Array of strings to wrap.
|
124
|
+
# @param [Integer,nil] width Width in characters, or `nil` for infinite.
|
125
|
+
# @param [Integer,nil] width2 Width in characters for the second and
|
126
|
+
# subsequent lines, or `nil` to use the same as width.
|
127
|
+
# @return [Array<String>] Wrapped lines
|
128
|
+
#
|
129
|
+
def self.wrap_lines(strs, width, width2 = nil)
|
130
|
+
result = Array(strs).map do |s|
|
131
|
+
lines = s.empty? ? [""] : s.wrap(width, width2)
|
132
|
+
width = width2 if width2
|
133
|
+
lines
|
134
|
+
end.flatten
|
135
|
+
result = [] if result.all?(&:empty?)
|
136
|
+
result
|
137
|
+
end
|
90
138
|
end
|
91
139
|
end
|
92
140
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toys-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -119,11 +119,11 @@ files:
|
|
119
119
|
- lib/toys/helpers/spinner.rb
|
120
120
|
- lib/toys/loader.rb
|
121
121
|
- lib/toys/middleware.rb
|
122
|
-
- lib/toys/middleware/
|
122
|
+
- lib/toys/middleware/add_verbosity_flags.rb
|
123
123
|
- lib/toys/middleware/base.rb
|
124
124
|
- lib/toys/middleware/handle_usage_errors.rb
|
125
125
|
- lib/toys/middleware/set_default_descriptions.rb
|
126
|
-
- lib/toys/middleware/
|
126
|
+
- lib/toys/middleware/show_help.rb
|
127
127
|
- lib/toys/middleware/show_version.rb
|
128
128
|
- lib/toys/template.rb
|
129
129
|
- lib/toys/templates.rb
|
@@ -133,8 +133,9 @@ files:
|
|
133
133
|
- lib/toys/templates/rubocop.rb
|
134
134
|
- lib/toys/templates/yardoc.rb
|
135
135
|
- lib/toys/tool.rb
|
136
|
+
- lib/toys/utils/help_text.rb
|
137
|
+
- lib/toys/utils/line_output.rb
|
136
138
|
- lib/toys/utils/module_lookup.rb
|
137
|
-
- lib/toys/utils/usage.rb
|
138
139
|
- lib/toys/utils/wrappable_string.rb
|
139
140
|
homepage: https://github.com/dazuma/toys
|
140
141
|
licenses:
|
@@ -1,99 +0,0 @@
|
|
1
|
-
# Copyright 2018 Daniel Azuma
|
2
|
-
#
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions are met:
|
7
|
-
#
|
8
|
-
# * Redistributions of source code must retain the above copyright notice,
|
9
|
-
# this list of conditions and the following disclaimer.
|
10
|
-
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
-
# contributors to this software, may be used to endorse or promote products
|
15
|
-
# derived from this software without specific prior written permission.
|
16
|
-
#
|
17
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
-
;
|
29
|
-
|
30
|
-
require "toys/middleware/base"
|
31
|
-
|
32
|
-
module Toys
|
33
|
-
module Middleware
|
34
|
-
##
|
35
|
-
# A middleware that provides switches for editing the verbosity.
|
36
|
-
#
|
37
|
-
# This middleware adds `-v`, `--verbose`, `-q`, and `--quiet` switches, if
|
38
|
-
# not already defined by the tool. These switches affect the setting of
|
39
|
-
# {Toys::Context::VERBOSITY}, and, thus, the logger level.
|
40
|
-
#
|
41
|
-
class AddVerbositySwitches < Base
|
42
|
-
##
|
43
|
-
# Default verbose switches
|
44
|
-
# @return [Array<String>]
|
45
|
-
#
|
46
|
-
DEFAULT_VERBOSE_SWITCHES = ["-v", "--verbose"].freeze
|
47
|
-
|
48
|
-
##
|
49
|
-
# Default quiet switches
|
50
|
-
# @return [Array<String>]
|
51
|
-
#
|
52
|
-
DEFAULT_QUIET_SWITCHES = ["-q", "--quiet"].freeze
|
53
|
-
|
54
|
-
##
|
55
|
-
# Create a AddVerbositySwitches middleware.
|
56
|
-
#
|
57
|
-
# @param [Boolean,Array<String>,Proc] verbose_switches Specify switches
|
58
|
-
# to increase verbosity. The value may be any of the following:
|
59
|
-
# * An array of switches that increase verbosity.
|
60
|
-
# * The `true` value to use {DEFAULT_VERBOSE_SWITCHES}. (Default)
|
61
|
-
# * The `false` value to disable verbose switches.
|
62
|
-
# * A proc that takes a tool and returns any of the above.
|
63
|
-
# @param [Boolean,Array<String>,Proc] quiet_switches Specify switches
|
64
|
-
# to decrease verbosity. The value may be any of the following:
|
65
|
-
# * An array of switches that decrease verbosity.
|
66
|
-
# * The `true` value to use {DEFAULT_QUIET_SWITCHES}. (Default)
|
67
|
-
# * The `false` value to disable quiet switches.
|
68
|
-
# * A proc that takes a tool and returns any of the above.
|
69
|
-
#
|
70
|
-
def initialize(verbose_switches: true, quiet_switches: true)
|
71
|
-
@verbose_switches = verbose_switches
|
72
|
-
@quiet_switches = quiet_switches
|
73
|
-
end
|
74
|
-
|
75
|
-
##
|
76
|
-
# Configure the tool switches.
|
77
|
-
#
|
78
|
-
def config(tool)
|
79
|
-
verbose_switches = Middleware.resolve_switches_spec(@verbose_switches, tool,
|
80
|
-
DEFAULT_VERBOSE_SWITCHES)
|
81
|
-
unless verbose_switches.empty?
|
82
|
-
tool.add_switch(Context::VERBOSITY, *verbose_switches,
|
83
|
-
docs: "Increase verbosity",
|
84
|
-
handler: ->(_val, cur) { cur + 1 },
|
85
|
-
only_unique: true)
|
86
|
-
end
|
87
|
-
quiet_switches = Middleware.resolve_switches_spec(@quiet_switches, tool,
|
88
|
-
DEFAULT_QUIET_SWITCHES)
|
89
|
-
unless quiet_switches.empty?
|
90
|
-
tool.add_switch(Context::VERBOSITY, *quiet_switches,
|
91
|
-
docs: "Decrease verbosity",
|
92
|
-
handler: ->(_val, cur) { cur - 1 },
|
93
|
-
only_unique: true)
|
94
|
-
end
|
95
|
-
yield
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,174 +0,0 @@
|
|
1
|
-
# Copyright 2018 Daniel Azuma
|
2
|
-
#
|
3
|
-
# All rights reserved.
|
4
|
-
#
|
5
|
-
# Redistribution and use in source and binary forms, with or without
|
6
|
-
# modification, are permitted provided that the following conditions are met:
|
7
|
-
#
|
8
|
-
# * Redistributions of source code must retain the above copyright notice,
|
9
|
-
# this list of conditions and the following disclaimer.
|
10
|
-
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
-
# contributors to this software, may be used to endorse or promote products
|
15
|
-
# derived from this software without specific prior written permission.
|
16
|
-
#
|
17
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
-
;
|
29
|
-
|
30
|
-
require "highline"
|
31
|
-
|
32
|
-
require "toys/middleware/base"
|
33
|
-
require "toys/utils/usage"
|
34
|
-
|
35
|
-
module Toys
|
36
|
-
module Middleware
|
37
|
-
##
|
38
|
-
# A middleware that shows usage documentation.
|
39
|
-
#
|
40
|
-
# This can be configured to display usage text when a switch (typically
|
41
|
-
# `--help`) is provided. It can also be configured to display usage text
|
42
|
-
# automatically for tools that do not have an executor.
|
43
|
-
#
|
44
|
-
# If a tool has no executor, this middleware can also add a
|
45
|
-
# `--[no-]recursive` flag, which, when set to `true` (the default), shows
|
46
|
-
# all subcommands recursively rather than only immediate subcommands.
|
47
|
-
#
|
48
|
-
class ShowUsage < Base
|
49
|
-
##
|
50
|
-
# Default help switches
|
51
|
-
# @return [Array<String>]
|
52
|
-
#
|
53
|
-
DEFAULT_HELP_SWITCHES = ["-?", "--help"].freeze
|
54
|
-
|
55
|
-
##
|
56
|
-
# Default recursive switches
|
57
|
-
# @return [Array<String>]
|
58
|
-
#
|
59
|
-
DEFAULT_RECURSIVE_SWITCHES = ["-r", "--[no-]recursive"].freeze
|
60
|
-
|
61
|
-
##
|
62
|
-
# Default search switches
|
63
|
-
# @return [Array<String>]
|
64
|
-
#
|
65
|
-
DEFAULT_SEARCH_SWITCHES = ["-s WORD", "--search=WORD"].freeze
|
66
|
-
|
67
|
-
##
|
68
|
-
# Create a ShowUsage middleware.
|
69
|
-
#
|
70
|
-
# @param [Boolean,Array<String>,Proc] help_switches Specify switches to
|
71
|
-
# activate help. The value may be any of the following:
|
72
|
-
# * An array of switches.
|
73
|
-
# * The `true` value to use {DEFAULT_HELP_SWITCHES}. (Default)
|
74
|
-
# * The `false` value for no switches.
|
75
|
-
# * A proc that takes a tool and returns any of the above.
|
76
|
-
# @param [Boolean,Array<String>,Proc] recursive_switches Specify switches
|
77
|
-
# to control recursive subcommand search. The value may be any of the
|
78
|
-
# following:
|
79
|
-
# * An array of switches.
|
80
|
-
# * The `true` value to use {DEFAULT_RECURSIVE_SWITCHES}. (Default)
|
81
|
-
# * The `false` value for no switches.
|
82
|
-
# * A proc that takes a tool and returns any of the above.
|
83
|
-
# @param [Boolean,Array<String>,Proc] search_switches Specify switches
|
84
|
-
# to search subcommands for a search term. The value may be any of
|
85
|
-
# the following:
|
86
|
-
# * An array of switches.
|
87
|
-
# * The `true` value to use {DEFAULT_SEARCH_SWITCHES}. (Default)
|
88
|
-
# * The `false` value for no switches.
|
89
|
-
# * A proc that takes a tool and returns any of the above.
|
90
|
-
# @param [Boolean] default_recursive Whether to search recursively for
|
91
|
-
# subcommands by default. Default is `true`.
|
92
|
-
# @param [Boolean] fallback_execution Cause the tool to display its own
|
93
|
-
# usage text if it does not otherwise have an executor. This is
|
94
|
-
# mostly useful for groups, which have children but no executor.
|
95
|
-
# Default is `true`.
|
96
|
-
#
|
97
|
-
def initialize(help_switches: true,
|
98
|
-
recursive_switches: true,
|
99
|
-
search_switches: true,
|
100
|
-
default_recursive: true,
|
101
|
-
fallback_execution: true)
|
102
|
-
@help_switches = help_switches
|
103
|
-
@recursive_switches = recursive_switches
|
104
|
-
@search_switches = search_switches
|
105
|
-
@default_recursive = default_recursive ? true : false
|
106
|
-
@fallback_execution = fallback_execution
|
107
|
-
end
|
108
|
-
|
109
|
-
##
|
110
|
-
# Configure switches and default data.
|
111
|
-
#
|
112
|
-
def config(tool)
|
113
|
-
help_switches = Middleware.resolve_switches_spec(@help_switches, tool,
|
114
|
-
DEFAULT_HELP_SWITCHES)
|
115
|
-
is_default = !tool.includes_executor? && @fallback_execution
|
116
|
-
if !help_switches.empty?
|
117
|
-
docs = "Show help message"
|
118
|
-
docs << " (default for groups)" if is_default
|
119
|
-
tool.add_switch(:_help, *help_switches,
|
120
|
-
docs: docs,
|
121
|
-
default: is_default,
|
122
|
-
only_unique: true)
|
123
|
-
elsif is_default
|
124
|
-
tool.default_data[:_help] = true
|
125
|
-
end
|
126
|
-
if !tool.includes_executor? && (!help_switches.empty? || @fallback_execution)
|
127
|
-
add_recursive_switches(tool)
|
128
|
-
add_search_switches(tool)
|
129
|
-
end
|
130
|
-
yield
|
131
|
-
end
|
132
|
-
|
133
|
-
##
|
134
|
-
# Display usage text if requested.
|
135
|
-
#
|
136
|
-
def execute(context)
|
137
|
-
if context[:_help]
|
138
|
-
usage = Utils::Usage.from_context(context)
|
139
|
-
width = ::HighLine.new.output_cols
|
140
|
-
puts(usage.string(recursive: context[:_recursive_subcommands],
|
141
|
-
search: context[:_search_subcommands],
|
142
|
-
show_path: context.verbosity > 0,
|
143
|
-
wrap_width: width))
|
144
|
-
else
|
145
|
-
yield
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
private
|
150
|
-
|
151
|
-
def add_recursive_switches(tool)
|
152
|
-
recursive_switches = Middleware.resolve_switches_spec(@recursive_switches, tool,
|
153
|
-
DEFAULT_RECURSIVE_SWITCHES)
|
154
|
-
unless recursive_switches.empty?
|
155
|
-
tool.add_switch(:_recursive_subcommands, *recursive_switches,
|
156
|
-
default: @default_recursive,
|
157
|
-
docs: "Show all subcommands recursively" \
|
158
|
-
" (default is #{@default_recursive})",
|
159
|
-
only_unique: true)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def add_search_switches(tool)
|
164
|
-
search_switches = Middleware.resolve_switches_spec(@search_switches, tool,
|
165
|
-
DEFAULT_SEARCH_SWITCHES)
|
166
|
-
unless search_switches.empty?
|
167
|
-
tool.add_switch(:_search_subcommands, *search_switches,
|
168
|
-
docs: "Search subcommands for the given term",
|
169
|
-
only_unique: true)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|