toys-core 0.3.5 → 0.3.6
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 +12 -0
- data/lib/toys/cli.rb +15 -10
- data/lib/toys/config_dsl.rb +103 -17
- data/lib/toys/context.rb +60 -48
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/helpers/exec.rb +1 -1
- data/lib/toys/helpers/highline.rb +4 -9
- data/lib/toys/middleware/add_verbosity_flags.rb +6 -6
- data/lib/toys/middleware/set_default_descriptions.rb +162 -92
- data/lib/toys/middleware/show_help.rb +12 -6
- data/lib/toys/middleware/{show_version.rb → show_root_version.rb} +14 -23
- data/lib/toys/tool.rb +122 -372
- data/lib/toys/tool/acceptor.rb +190 -0
- data/lib/toys/tool/arg_definition.rb +130 -0
- data/lib/toys/tool/flag_definition.rb +322 -0
- data/lib/toys/utils/exec.rb +1 -1
- data/lib/toys/utils/help_text.rb +21 -15
- data/lib/toys/utils/line_output.rb +29 -12
- data/lib/toys/utils/wrappable_string.rb +23 -0
- metadata +6 -3
data/lib/toys/core_version.rb
CHANGED
data/lib/toys/helpers/exec.rb
CHANGED
@@ -35,20 +35,15 @@ module Toys
|
|
35
35
|
# A module that provides access to highline.
|
36
36
|
#
|
37
37
|
module Highline
|
38
|
-
##
|
39
|
-
# Returns a global highline instance
|
40
|
-
# @return [::HighLine]
|
41
|
-
#
|
42
|
-
def self.highline
|
43
|
-
@highline ||= ::HighLine.new
|
44
|
-
end
|
45
|
-
|
46
38
|
##
|
47
39
|
# Returns a global highline instance
|
48
40
|
# @return [::HighLine]
|
49
41
|
#
|
50
42
|
def highline
|
51
|
-
Highline
|
43
|
+
self[Highline] ||= begin
|
44
|
+
::HighLine.use_color = $stdout.tty?
|
45
|
+
::HighLine.new
|
46
|
+
end
|
52
47
|
end
|
53
48
|
|
54
49
|
##
|
@@ -89,10 +89,10 @@ module Toys
|
|
89
89
|
unless verbose_flags.empty?
|
90
90
|
long_desc = "Increase verbosity, causing additional logging levels to display."
|
91
91
|
tool.add_flag(Context::VERBOSITY, verbose_flags,
|
92
|
-
|
93
|
-
long_desc: long_desc,
|
92
|
+
report_collisions: false,
|
94
93
|
handler: ->(_val, cur) { cur + 1 },
|
95
|
-
|
94
|
+
desc: "Increase verbosity",
|
95
|
+
long_desc: long_desc)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -102,10 +102,10 @@ module Toys
|
|
102
102
|
unless quiet_flags.empty?
|
103
103
|
long_desc = "Decrease verbosity, causing fewer logging levels to display."
|
104
104
|
tool.add_flag(Context::VERBOSITY, quiet_flags,
|
105
|
-
|
106
|
-
long_desc: long_desc,
|
105
|
+
report_collisions: false,
|
107
106
|
handler: ->(_val, cur) { cur - 1 },
|
108
|
-
|
107
|
+
desc: "Decrease verbosity",
|
108
|
+
long_desc: long_desc)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
@@ -32,9 +32,12 @@ require "toys/middleware/base"
|
|
32
32
|
module Toys
|
33
33
|
module Middleware
|
34
34
|
##
|
35
|
-
# This middleware sets default description fields for tools
|
36
|
-
#
|
37
|
-
#
|
35
|
+
# This middleware sets default description fields for tools and command
|
36
|
+
# line arguments and flags that do not have them set otherwise.
|
37
|
+
#
|
38
|
+
# You can modify the static descriptions for tools, namespaces, and the
|
39
|
+
# root tool by passing parameters to this middleware. For finer control,
|
40
|
+
# you can override methods to modify the description generation logic.
|
38
41
|
#
|
39
42
|
class SetDefaultDescriptions < Base
|
40
43
|
##
|
@@ -59,34 +62,25 @@ module Toys
|
|
59
62
|
# The default long description for the root tool.
|
60
63
|
# @return [String]
|
61
64
|
#
|
62
|
-
DEFAULT_ROOT_LONG_DESC =
|
65
|
+
DEFAULT_ROOT_LONG_DESC = [
|
63
66
|
"This command line tool was built using the toys-core gem. See" \
|
64
|
-
|
65
|
-
" configure the SetDefaultDescriptions middleware."
|
66
|
-
|
67
|
-
##
|
68
|
-
# The default description for flags.
|
69
|
-
# @return [String]
|
70
|
-
#
|
71
|
-
DEFAULT_FLAG_DESC = "(No flag description available)".freeze
|
72
|
-
|
73
|
-
##
|
74
|
-
# The default description for required args.
|
75
|
-
# @return [String]
|
76
|
-
#
|
77
|
-
DEFAULT_REQUIRED_ARG_DESC = "(Required argument - no description available)".freeze
|
78
|
-
|
79
|
-
##
|
80
|
-
# The default description for optional args.
|
81
|
-
# @return [String]
|
82
|
-
#
|
83
|
-
DEFAULT_OPTIONAL_ARG_DESC = "(Optional argument - no description available)".freeze
|
67
|
+
" https://www.rubydoc.info/gems/toys-core for more info.",
|
68
|
+
"To replace this message, configure the SetDefaultDescriptions middleware."
|
69
|
+
].freeze
|
84
70
|
|
85
71
|
##
|
86
|
-
#
|
87
|
-
# @return [
|
72
|
+
# A mapping of names for acceptable types
|
73
|
+
# @return [Hash]
|
88
74
|
#
|
89
|
-
|
75
|
+
ACCEPTABLE_NAMES = {
|
76
|
+
nil => "string",
|
77
|
+
::String => "nonempty string",
|
78
|
+
::TrueClass => "boolean",
|
79
|
+
::FalseClass => "boolean",
|
80
|
+
::OptionParser::DecimalInteger => "decimal integer",
|
81
|
+
::OptionParser::OctalInteger => "octal integer",
|
82
|
+
::OptionParser::DecimalNumeric => "decimal numeric"
|
83
|
+
}.freeze
|
90
84
|
|
91
85
|
##
|
92
86
|
# Create a SetDefaultDescriptions middleware given default descriptions.
|
@@ -109,100 +103,176 @@ module Toys
|
|
109
103
|
# @param [String,nil] default_root_long_desc The default long description
|
110
104
|
# for the root tool, or `nil` not to set one. Defaults to
|
111
105
|
# {DEFAULT_ROOT_LONG_DESC}.
|
112
|
-
# @param [String,nil] default_flag_desc The default short description for
|
113
|
-
# flags, or `nil` not to set one. Defaults to {DEFAULT_FLAG_DESC}.
|
114
|
-
# @param [String,nil] default_flag_long_desc The default long description
|
115
|
-
# for flags, or `nil` not to set one. Defaults to `nil`.
|
116
|
-
# @param [String,nil] default_required_arg_desc The default short
|
117
|
-
# description for required args, or `nil` not to set one. Defaults to
|
118
|
-
# {DEFAULT_REQUIRED_ARG_DESC}.
|
119
|
-
# @param [String,nil] default_required_arg_long_desc The default long
|
120
|
-
# description for required args, or `nil` not to set one. Defaults to
|
121
|
-
# `nil`.
|
122
|
-
# @param [String,nil] default_optional_arg_desc The default short
|
123
|
-
# description for optional args, or `nil` not to set one. Defaults to
|
124
|
-
# {DEFAULT_OPTIONAL_ARG_DESC}.
|
125
|
-
# @param [String,nil] default_optional_arg_long_desc The default long
|
126
|
-
# description for optional args, or `nil` not to set one. Defaults to
|
127
|
-
# `nil`.
|
128
|
-
# @param [String,nil] default_remaining_arg_desc The default short
|
129
|
-
# description for remaining args, or `nil` not to set one. Defaults
|
130
|
-
# to {DEFAULT_REMAINING_ARG_DESC}.
|
131
|
-
# @param [String,nil] default_remaining_arg_long_desc The default long
|
132
|
-
# description for remaining args, or `nil` not to set one. Defaults
|
133
|
-
# to `nil`.
|
134
106
|
#
|
135
107
|
def initialize(default_tool_desc: DEFAULT_TOOL_DESC,
|
136
108
|
default_tool_long_desc: nil,
|
137
109
|
default_namespace_desc: DEFAULT_NAMESPACE_DESC,
|
138
110
|
default_namespace_long_desc: nil,
|
139
111
|
default_root_desc: DEFAULT_ROOT_DESC,
|
140
|
-
default_root_long_desc: DEFAULT_ROOT_LONG_DESC
|
141
|
-
default_flag_desc: DEFAULT_FLAG_DESC,
|
142
|
-
default_flag_long_desc: nil,
|
143
|
-
default_required_arg_desc: DEFAULT_REQUIRED_ARG_DESC,
|
144
|
-
default_required_arg_long_desc: nil,
|
145
|
-
default_optional_arg_desc: DEFAULT_OPTIONAL_ARG_DESC,
|
146
|
-
default_optional_arg_long_desc: nil,
|
147
|
-
default_remaining_arg_desc: DEFAULT_REMAINING_ARG_DESC,
|
148
|
-
default_remaining_arg_long_desc: nil)
|
112
|
+
default_root_long_desc: DEFAULT_ROOT_LONG_DESC)
|
149
113
|
@default_tool_desc = default_tool_desc
|
150
114
|
@default_tool_long_desc = default_tool_long_desc
|
151
115
|
@default_namespace_desc = default_namespace_desc
|
152
116
|
@default_namespace_long_desc = default_namespace_long_desc
|
153
117
|
@default_root_desc = default_root_desc
|
154
118
|
@default_root_long_desc = default_root_long_desc
|
155
|
-
@default_flag_desc = default_flag_desc
|
156
|
-
@default_flag_long_desc = default_flag_long_desc
|
157
|
-
@default_required_arg_desc = default_required_arg_desc
|
158
|
-
@default_required_arg_long_desc = default_required_arg_long_desc
|
159
|
-
@default_optional_arg_desc = default_optional_arg_desc
|
160
|
-
@default_optional_arg_long_desc = default_optional_arg_long_desc
|
161
|
-
@default_remaining_arg_desc = default_remaining_arg_desc
|
162
|
-
@default_remaining_arg_long_desc = default_remaining_arg_long_desc
|
163
119
|
end
|
164
120
|
|
165
121
|
##
|
166
122
|
# Add default description text to tools.
|
167
123
|
#
|
168
|
-
def config(tool,
|
169
|
-
|
170
|
-
config_descs(tool, @default_root_desc, @default_root_long_desc)
|
171
|
-
elsif tool.includes_script?
|
172
|
-
config_descs(tool, @default_tool_desc, @default_tool_long_desc)
|
173
|
-
else
|
174
|
-
config_descs(tool, @default_namespace_desc, @default_namespace_long_desc)
|
175
|
-
end
|
124
|
+
def config(tool, loader)
|
125
|
+
data = {tool: tool, loader: loader}
|
176
126
|
tool.flag_definitions.each do |flag|
|
177
|
-
|
127
|
+
config_desc(flag, generate_flag_desc(flag, data), generate_flag_long_desc(flag, data))
|
128
|
+
end
|
129
|
+
tool.arg_definitions.each do |arg|
|
130
|
+
config_desc(arg, generate_arg_desc(arg, data), generate_arg_long_desc(arg, data))
|
178
131
|
end
|
179
|
-
|
132
|
+
config_desc(tool, generate_tool_desc(tool, data), generate_tool_long_desc(tool, data))
|
180
133
|
yield
|
181
134
|
end
|
182
135
|
|
183
|
-
|
136
|
+
protected
|
184
137
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
138
|
+
##
|
139
|
+
# This method implements the logic for generating a tool description.
|
140
|
+
# By default, it uses the parameters given to the middleware object.
|
141
|
+
# Override this method to provide different logic.
|
142
|
+
#
|
143
|
+
# @param [Toys::Tool] tool The tool to document.
|
144
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
145
|
+
# the {Toys::Loader} is passed with key `:loader`. Future versions
|
146
|
+
# of Toys may provide additional information.
|
147
|
+
# @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
|
148
|
+
# default description, or `nil` not to set a default. See
|
149
|
+
# {Toys::Tool#desc=} for info on the format.
|
150
|
+
#
|
151
|
+
def generate_tool_desc(tool, data)
|
152
|
+
if tool.root?
|
153
|
+
@default_root_desc
|
154
|
+
elsif !tool.includes_script? && data[:loader].has_subtools?(tool.full_name)
|
155
|
+
@default_namespace_desc
|
156
|
+
else
|
157
|
+
@default_tool_desc
|
195
158
|
end
|
196
159
|
end
|
197
160
|
|
198
|
-
|
199
|
-
|
200
|
-
|
161
|
+
##
|
162
|
+
# This method implements logic for generating a tool long description.
|
163
|
+
# By default, it uses the parameters given to the middleware object.
|
164
|
+
# Override this method to provide different logic.
|
165
|
+
#
|
166
|
+
# @param [Toys::Tool] tool The tool to document
|
167
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
168
|
+
# the {Toys::Loader} is passed with key `:loader`. Future versions
|
169
|
+
# of Toys may provide additional information.
|
170
|
+
# @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
|
171
|
+
# The default long description, or `nil` not to set a default. See
|
172
|
+
# {Toys::Tool#long_desc=} for info on the format.
|
173
|
+
#
|
174
|
+
def generate_tool_long_desc(tool, data)
|
175
|
+
if tool.root?
|
176
|
+
@default_root_long_desc
|
177
|
+
elsif !tool.includes_script? && data[:loader].has_subtools?(tool.full_name)
|
178
|
+
@default_namespace_long_desc
|
179
|
+
else
|
180
|
+
@default_tool_long_desc
|
201
181
|
end
|
202
|
-
|
203
|
-
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# This method implements the logic for generating a flag description.
|
186
|
+
# Override this method to provide different logic.
|
187
|
+
#
|
188
|
+
# @param [Toys::Tool::FlagDefinition] flag The flag to document
|
189
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
190
|
+
# the {Toys::Tool} is passed with key `:tool`. Future versions of
|
191
|
+
# Toys may provide additional information.
|
192
|
+
# @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
|
193
|
+
# default description, or `nil` not to set a default. See
|
194
|
+
# {Toys::Tool#desc=} for info on the format.
|
195
|
+
#
|
196
|
+
def generate_flag_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
|
197
|
+
name = flag.key.to_s.tr("_", "-").gsub(/[^\w-]/, "").downcase.inspect
|
198
|
+
acceptable = flag.flag_type == :value ? acceptable_name(flag.accept) : "boolean flag"
|
199
|
+
default_clause = flag.default ? " (default is #{flag.default.inspect})" : ""
|
200
|
+
"Sets the #{name} option as type #{acceptable}#{default_clause}."
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# This method implements logic for generating a flag long description.
|
205
|
+
# Override this method to provide different logic.
|
206
|
+
#
|
207
|
+
# @param [Toys::Tool::FlagDefinition] flag The flag to document
|
208
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
209
|
+
# the {Toys::Tool} is passed with key `:tool`. Future versions of
|
210
|
+
# Toys may provide additional information.
|
211
|
+
# @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
|
212
|
+
# The default long description, or `nil` not to set a default. See
|
213
|
+
# {Toys::Tool#long_desc=} for info on the format.
|
214
|
+
#
|
215
|
+
def generate_flag_long_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
|
216
|
+
nil
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# This method implements the logic for generating an arg description.
|
221
|
+
# Override this method to provide different logic.
|
222
|
+
#
|
223
|
+
# @param [Toys::Tool::ArgDefinition] arg The arg to document
|
224
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
225
|
+
# the {Toys::Tool} is passed with key `:tool`. Future versions of
|
226
|
+
# Toys may provide additional information.
|
227
|
+
# @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
|
228
|
+
# default description, or `nil` not to set a default. See
|
229
|
+
# {Toys::Tool#desc=} for info on the format.
|
230
|
+
#
|
231
|
+
def generate_arg_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
|
232
|
+
acceptable = acceptable_name(arg.accept)
|
233
|
+
default_clause = arg.default ? " (default is #{arg.default.inspect})" : ""
|
234
|
+
case arg.type
|
235
|
+
when :required
|
236
|
+
"Required #{acceptable} argument."
|
237
|
+
when :optional
|
238
|
+
"Optional #{acceptable} argument#{default_clause}."
|
239
|
+
else
|
240
|
+
"Remaining arguments are type #{acceptable}#{default_clause}."
|
204
241
|
end
|
205
242
|
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# This method implements logic for generating an arg long description.
|
246
|
+
# Override this method to provide different logic.
|
247
|
+
#
|
248
|
+
# @param [Toys::Tool::ArgDefinition] arg The arg to document
|
249
|
+
# @param [Hash] data Additional data that might be useful. Currently,
|
250
|
+
# the {Toys::Tool} is passed with key `:tool`. Future versions of
|
251
|
+
# Toys may provide additional information.
|
252
|
+
# @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
|
253
|
+
# The default long description, or `nil` not to set a default. See
|
254
|
+
# {Toys::Tool#long_desc=} for info on the format.
|
255
|
+
#
|
256
|
+
def generate_arg_long_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
|
257
|
+
nil
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# Return a reasonable name for an acceptor
|
262
|
+
#
|
263
|
+
# @param [Object] accept An acceptor to name
|
264
|
+
# @return [String]
|
265
|
+
#
|
266
|
+
def acceptable_name(accept)
|
267
|
+
ACCEPTABLE_NAMES[accept] || accept.to_s.downcase
|
268
|
+
end
|
269
|
+
|
270
|
+
private
|
271
|
+
|
272
|
+
def config_desc(object, desc, long_desc)
|
273
|
+
object.desc = desc if desc && object.desc.empty?
|
274
|
+
object.long_desc = long_desc if long_desc && object.long_desc.empty?
|
275
|
+
end
|
206
276
|
end
|
207
277
|
end
|
208
278
|
end
|
@@ -110,6 +110,8 @@ module Toys
|
|
110
110
|
# help or usage, and doesn't otherwise use positional arguments,
|
111
111
|
# then a tool name can be passed as arguments to display help for
|
112
112
|
# that tool.
|
113
|
+
# @param [Boolean] show_source_path Show the source path section. Default
|
114
|
+
# is `false`.
|
113
115
|
# @param [Boolean] use_less If the `less` tool is available, and the
|
114
116
|
# output stream is a tty, then use `less` to display help text.
|
115
117
|
# @param [IO] stream Output stream to write to. Default is stdout.
|
@@ -124,6 +126,7 @@ module Toys
|
|
124
126
|
default_recursive: false,
|
125
127
|
fallback_execution: false,
|
126
128
|
allow_root_args: false,
|
129
|
+
show_source_path: false,
|
127
130
|
use_less: false,
|
128
131
|
stream: $stdout,
|
129
132
|
styled_output: nil)
|
@@ -134,6 +137,7 @@ module Toys
|
|
134
137
|
@default_recursive = default_recursive ? true : false
|
135
138
|
@fallback_execution = fallback_execution
|
136
139
|
@allow_root_args = allow_root_args
|
140
|
+
@show_source_path = show_source_path
|
137
141
|
@stream = stream
|
138
142
|
@styled_output = styled_output
|
139
143
|
@use_less = use_less
|
@@ -171,6 +175,7 @@ module Toys
|
|
171
175
|
help_text = get_help_text(context)
|
172
176
|
str = help_text.help_string(recursive: context[:_recursive_subtools],
|
173
177
|
search: context[:_search_subtools],
|
178
|
+
show_source_path: @show_source_path,
|
174
179
|
wrap_width: output_cols)
|
175
180
|
output_help(str)
|
176
181
|
else
|
@@ -229,7 +234,7 @@ module Toys
|
|
229
234
|
DEFAULT_HELP_FLAGS)
|
230
235
|
unless help_flags.empty?
|
231
236
|
tool.add_flag(:_show_help, help_flags,
|
232
|
-
desc: "Display help for this tool"
|
237
|
+
report_collisions: false, desc: "Display help for this tool")
|
233
238
|
end
|
234
239
|
help_flags
|
235
240
|
end
|
@@ -239,7 +244,8 @@ module Toys
|
|
239
244
|
DEFAULT_USAGE_FLAGS)
|
240
245
|
unless usage_flags.empty?
|
241
246
|
tool.add_flag(:_show_usage, usage_flags,
|
242
|
-
|
247
|
+
report_collisions: false,
|
248
|
+
desc: "Display a brief usage string for this tool")
|
243
249
|
end
|
244
250
|
usage_flags
|
245
251
|
end
|
@@ -249,9 +255,9 @@ module Toys
|
|
249
255
|
DEFAULT_RECURSIVE_FLAGS)
|
250
256
|
unless recursive_flags.empty?
|
251
257
|
tool.add_flag(:_recursive_subtools, recursive_flags,
|
258
|
+
report_collisions: false,
|
252
259
|
default: @default_recursive,
|
253
|
-
desc: "Show all subtools recursively (default is #{@default_recursive})"
|
254
|
-
only_unique: true)
|
260
|
+
desc: "Show all subtools recursively (default is #{@default_recursive})")
|
255
261
|
end
|
256
262
|
end
|
257
263
|
|
@@ -260,8 +266,8 @@ module Toys
|
|
260
266
|
DEFAULT_SEARCH_FLAGS)
|
261
267
|
unless search_flags.empty?
|
262
268
|
tool.add_flag(:_search_subtools, search_flags,
|
263
|
-
|
264
|
-
|
269
|
+
report_collisions: false,
|
270
|
+
desc: "Search subtools for the given regular expression")
|
265
271
|
end
|
266
272
|
end
|
267
273
|
end
|