toys-core 0.3.6 → 0.3.7
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 +13 -0
- data/lib/toys-core.rb +20 -5
- data/lib/toys/cli.rb +39 -32
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/{tool → definition}/acceptor.rb +21 -15
- data/lib/toys/{utils/line_output.rb → definition/alias.rb} +47 -59
- data/lib/toys/{tool/arg_definition.rb → definition/arg.rb} +17 -7
- data/lib/toys/{tool/flag_definition.rb → definition/flag.rb} +19 -9
- data/lib/toys/definition/tool.rb +574 -0
- data/lib/toys/dsl/arg.rb +118 -0
- data/lib/toys/dsl/flag.rb +132 -0
- data/lib/toys/dsl/tool.rb +521 -0
- data/lib/toys/errors.rb +2 -2
- data/lib/toys/helpers.rb +3 -3
- data/lib/toys/helpers/exec.rb +31 -25
- data/lib/toys/helpers/fileutils.rb +8 -2
- data/lib/toys/helpers/highline.rb +8 -1
- data/lib/toys/{alias.rb → helpers/terminal.rb} +44 -53
- data/lib/toys/input_file.rb +61 -0
- data/lib/toys/loader.rb +87 -77
- data/lib/toys/middleware.rb +3 -3
- data/lib/toys/middleware/add_verbosity_flags.rb +22 -20
- data/lib/toys/middleware/base.rb +53 -5
- data/lib/toys/middleware/handle_usage_errors.rb +9 -12
- data/lib/toys/middleware/set_default_descriptions.rb +6 -7
- data/lib/toys/middleware/show_help.rb +71 -67
- data/lib/toys/middleware/show_root_version.rb +9 -9
- data/lib/toys/runner.rb +157 -0
- data/lib/toys/template.rb +4 -3
- data/lib/toys/templates.rb +2 -2
- data/lib/toys/templates/clean.rb +2 -2
- data/lib/toys/templates/gem_build.rb +5 -5
- data/lib/toys/templates/minitest.rb +2 -2
- data/lib/toys/templates/rubocop.rb +2 -2
- data/lib/toys/templates/yardoc.rb +2 -2
- data/lib/toys/tool.rb +168 -625
- data/lib/toys/utils/exec.rb +19 -18
- data/lib/toys/utils/gems.rb +140 -0
- data/lib/toys/utils/help_text.rb +25 -20
- data/lib/toys/utils/terminal.rb +412 -0
- data/lib/toys/utils/wrappable_string.rb +3 -1
- metadata +15 -24
- data/lib/toys/config_dsl.rb +0 -699
- data/lib/toys/context.rb +0 -290
- data/lib/toys/helpers/spinner.rb +0 -142
@@ -32,13 +32,13 @@ require "optparse"
|
|
32
32
|
require "toys/utils/wrappable_string"
|
33
33
|
|
34
34
|
module Toys
|
35
|
-
|
35
|
+
module Definition
|
36
36
|
##
|
37
37
|
# Representation of a formal positional argument
|
38
38
|
#
|
39
|
-
class
|
39
|
+
class Arg
|
40
40
|
##
|
41
|
-
# Create an
|
41
|
+
# Create an Arg definition
|
42
42
|
# @private
|
43
43
|
#
|
44
44
|
def initialize(key, type, accept, default, desc, long_desc, display_name)
|
@@ -111,16 +111,26 @@ module Toys
|
|
111
111
|
end
|
112
112
|
|
113
113
|
##
|
114
|
-
# Set description
|
115
|
-
#
|
114
|
+
# Set the short description string.
|
115
|
+
#
|
116
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
117
|
+
# single string (which will be wrapped), or an array of strings, which will
|
118
|
+
# be interpreted as string fragments that will be concatenated and wrapped.
|
119
|
+
#
|
120
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
116
121
|
#
|
117
122
|
def desc=(desc)
|
118
123
|
@desc = Utils::WrappableString.make(desc)
|
119
124
|
end
|
120
125
|
|
121
126
|
##
|
122
|
-
# Set long description
|
123
|
-
#
|
127
|
+
# Set the long description strings.
|
128
|
+
#
|
129
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a single
|
130
|
+
# string (which will be wrapped), or an array of strings, which will be
|
131
|
+
# interpreted as string fragments that will be concatenated and wrapped.
|
132
|
+
#
|
133
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] long_desc
|
124
134
|
#
|
125
135
|
def long_desc=(long_desc)
|
126
136
|
@long_desc = Utils::WrappableString.make_array(long_desc)
|
@@ -32,7 +32,7 @@ require "optparse"
|
|
32
32
|
require "toys/utils/wrappable_string"
|
33
33
|
|
34
34
|
module Toys
|
35
|
-
|
35
|
+
module Definition
|
36
36
|
##
|
37
37
|
# Representation of a single flag.
|
38
38
|
#
|
@@ -105,9 +105,9 @@ module Toys
|
|
105
105
|
|
106
106
|
##
|
107
107
|
# Representation of a formal set of flags that set a particular context
|
108
|
-
# key. The flags within a single
|
108
|
+
# key. The flags within a single Flag definition are synonyms.
|
109
109
|
#
|
110
|
-
class
|
110
|
+
class Flag
|
111
111
|
##
|
112
112
|
# The default handler replaces the previous value.
|
113
113
|
# @return [Proc]
|
@@ -115,7 +115,7 @@ module Toys
|
|
115
115
|
DEFAULT_HANDLER = ->(val, _prev) { val }
|
116
116
|
|
117
117
|
##
|
118
|
-
# Create a
|
118
|
+
# Create a Flag definition
|
119
119
|
# @private
|
120
120
|
#
|
121
121
|
def initialize(key, flags, used_flags, report_collisions, accept, handler, default)
|
@@ -228,7 +228,7 @@ module Toys
|
|
228
228
|
end
|
229
229
|
|
230
230
|
##
|
231
|
-
#
|
231
|
+
# Returns a list suitable for passing to OptionParser.
|
232
232
|
# @return [Array]
|
233
233
|
#
|
234
234
|
def optparser_info
|
@@ -245,16 +245,26 @@ module Toys
|
|
245
245
|
end
|
246
246
|
|
247
247
|
##
|
248
|
-
# Set description
|
249
|
-
#
|
248
|
+
# Set the short description string.
|
249
|
+
#
|
250
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
251
|
+
# single string (which will be wrapped), or an array of strings, which will
|
252
|
+
# be interpreted as string fragments that will be concatenated and wrapped.
|
253
|
+
#
|
254
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
250
255
|
#
|
251
256
|
def desc=(desc)
|
252
257
|
@desc = Utils::WrappableString.make(desc)
|
253
258
|
end
|
254
259
|
|
255
260
|
##
|
256
|
-
# Set long description
|
257
|
-
#
|
261
|
+
# Set the long description strings.
|
262
|
+
#
|
263
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a single
|
264
|
+
# string (which will be wrapped), or an array of strings, which will be
|
265
|
+
# interpreted as string fragments that will be concatenated and wrapped.
|
266
|
+
#
|
267
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] long_desc
|
258
268
|
#
|
259
269
|
def long_desc=(long_desc)
|
260
270
|
@long_desc = Utils::WrappableString.make_array(long_desc)
|
@@ -0,0 +1,574 @@
|
|
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 "optparse"
|
31
|
+
|
32
|
+
require "toys/utils/wrappable_string"
|
33
|
+
|
34
|
+
module Toys
|
35
|
+
module Definition
|
36
|
+
##
|
37
|
+
# A Tool is a single command that can be invoked using Toys.
|
38
|
+
# It has a name, a series of one or more words that you use to identify
|
39
|
+
# the tool on the command line. It also has a set of formal flags and
|
40
|
+
# command line arguments supported, and a block that gets run when the
|
41
|
+
# tool is executed.
|
42
|
+
#
|
43
|
+
class Tool
|
44
|
+
##
|
45
|
+
# Built-in acceptors (i.e. those recognized by OptionParser).
|
46
|
+
# You can reference these acceptors directly. Otherwise, you have to add
|
47
|
+
# one explicitly to the tool using {Tool#add_acceptor}.
|
48
|
+
#
|
49
|
+
OPTPARSER_ACCEPTORS = [
|
50
|
+
::Object,
|
51
|
+
::NilClass,
|
52
|
+
::String,
|
53
|
+
::Integer,
|
54
|
+
::Float,
|
55
|
+
::Numeric,
|
56
|
+
::TrueClass,
|
57
|
+
::FalseClass,
|
58
|
+
::Array,
|
59
|
+
::Regexp,
|
60
|
+
::OptionParser::DecimalInteger,
|
61
|
+
::OptionParser::OctalInteger,
|
62
|
+
::OptionParser::DecimalNumeric
|
63
|
+
].freeze
|
64
|
+
|
65
|
+
##
|
66
|
+
# Create a new tool.
|
67
|
+
# @private
|
68
|
+
#
|
69
|
+
def initialize(loader, parent, full_name, priority, middleware_stack)
|
70
|
+
@parent = parent
|
71
|
+
@full_name = full_name.dup.freeze
|
72
|
+
@tool_class = DSL::Tool.new_class(@full_name, priority, loader)
|
73
|
+
@priority = priority
|
74
|
+
@middleware_stack = Middleware.resolve_stack(middleware_stack)
|
75
|
+
|
76
|
+
@source_path = nil
|
77
|
+
@definition_finished = false
|
78
|
+
|
79
|
+
@desc = Toys::Utils::WrappableString.new("")
|
80
|
+
@long_desc = []
|
81
|
+
|
82
|
+
@default_data = {}
|
83
|
+
@acceptors = {}
|
84
|
+
OPTPARSER_ACCEPTORS.each { |a| @acceptors[a] = a }
|
85
|
+
@used_flags = []
|
86
|
+
|
87
|
+
@helpers = {}
|
88
|
+
|
89
|
+
@flag_definitions = []
|
90
|
+
@required_arg_definitions = []
|
91
|
+
@optional_arg_definitions = []
|
92
|
+
@remaining_args_definition = nil
|
93
|
+
@runnable = false
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Return the name of the tool as an array of strings.
|
98
|
+
# This array may not be modified.
|
99
|
+
# @return [Array<String>]
|
100
|
+
#
|
101
|
+
attr_reader :full_name
|
102
|
+
|
103
|
+
##
|
104
|
+
# Return the priority of this tool definition.
|
105
|
+
# @return [Integer]
|
106
|
+
#
|
107
|
+
attr_reader :priority
|
108
|
+
|
109
|
+
##
|
110
|
+
# Return the tool class.
|
111
|
+
# @return [Class]
|
112
|
+
#
|
113
|
+
attr_reader :tool_class
|
114
|
+
|
115
|
+
##
|
116
|
+
# Returns the short description string.
|
117
|
+
# @return [Toys::Utils::WrappableString]
|
118
|
+
#
|
119
|
+
attr_reader :desc
|
120
|
+
|
121
|
+
##
|
122
|
+
# Returns the long description strings as an array.
|
123
|
+
# @return [Array<Toys::Utils::WrappableString>]
|
124
|
+
#
|
125
|
+
attr_reader :long_desc
|
126
|
+
|
127
|
+
##
|
128
|
+
# Return a list of all defined flags.
|
129
|
+
# @return [Array<Toys::Definition::Flag>]
|
130
|
+
#
|
131
|
+
attr_reader :flag_definitions
|
132
|
+
|
133
|
+
##
|
134
|
+
# Return a list of all defined required positional arguments.
|
135
|
+
# @return [Array<Toys::Definition::Arg>]
|
136
|
+
#
|
137
|
+
attr_reader :required_arg_definitions
|
138
|
+
|
139
|
+
##
|
140
|
+
# Return a list of all defined optional positional arguments.
|
141
|
+
# @return [Array<Toys::Definition::Arg>]
|
142
|
+
#
|
143
|
+
attr_reader :optional_arg_definitions
|
144
|
+
|
145
|
+
##
|
146
|
+
# Return the remaining arguments specification, or `nil` if remaining
|
147
|
+
# arguments are currently not supported by this tool.
|
148
|
+
# @return [Toys::Definition::Arg,nil]
|
149
|
+
#
|
150
|
+
attr_reader :remaining_args_definition
|
151
|
+
|
152
|
+
##
|
153
|
+
# Return a list of flags that have been used in the flag definitions.
|
154
|
+
# @return [Array<String>]
|
155
|
+
#
|
156
|
+
attr_reader :used_flags
|
157
|
+
|
158
|
+
##
|
159
|
+
# Return the default argument data.
|
160
|
+
# @return [Hash]
|
161
|
+
#
|
162
|
+
attr_reader :default_data
|
163
|
+
|
164
|
+
##
|
165
|
+
# Returns the middleware stack
|
166
|
+
# @return [Array<Object>]
|
167
|
+
#
|
168
|
+
attr_reader :middleware_stack
|
169
|
+
|
170
|
+
##
|
171
|
+
# Returns the path to the file that contains the definition of this tool.
|
172
|
+
# @return [String]
|
173
|
+
#
|
174
|
+
attr_reader :source_path
|
175
|
+
|
176
|
+
##
|
177
|
+
# Returns the local name of this tool.
|
178
|
+
# @return [String]
|
179
|
+
#
|
180
|
+
def simple_name
|
181
|
+
full_name.last
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# Returns a displayable name of this tool, generally the full name
|
186
|
+
# delimited by spaces.
|
187
|
+
# @return [String]
|
188
|
+
#
|
189
|
+
def display_name
|
190
|
+
full_name.join(" ")
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Returns true if this tool is a root tool.
|
195
|
+
# @return [Boolean]
|
196
|
+
#
|
197
|
+
def root?
|
198
|
+
full_name.empty?
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Returns true if this tool is marked as runnable.
|
203
|
+
# @return [Boolean]
|
204
|
+
#
|
205
|
+
def runnable?
|
206
|
+
@runnable
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Returns true if there is a specific description set for this tool.
|
211
|
+
# @return [Boolean]
|
212
|
+
#
|
213
|
+
def includes_description?
|
214
|
+
!long_desc.empty? || !desc.empty?
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Returns true if at least one flag or positional argument is defined
|
219
|
+
# for this tool.
|
220
|
+
# @return [Boolean]
|
221
|
+
#
|
222
|
+
def includes_arguments?
|
223
|
+
!default_data.empty? || !flag_definitions.empty? ||
|
224
|
+
!required_arg_definitions.empty? || !optional_arg_definitions.empty? ||
|
225
|
+
!remaining_args_definition.nil?
|
226
|
+
end
|
227
|
+
|
228
|
+
##
|
229
|
+
# Returns true if this tool has any definition information.
|
230
|
+
# @return [Boolean]
|
231
|
+
#
|
232
|
+
def includes_definition?
|
233
|
+
includes_arguments? || runnable?
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# Returns true if this tool's definition has been finished and is locked.
|
238
|
+
# @return [Boolean]
|
239
|
+
#
|
240
|
+
def definition_finished?
|
241
|
+
@definition_finished
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Returns all arg definitions in order: required, optional, remaining.
|
246
|
+
# @return [Array<Toys::Definition::Arg>]
|
247
|
+
#
|
248
|
+
def arg_definitions
|
249
|
+
result = required_arg_definitions + optional_arg_definitions
|
250
|
+
result << remaining_args_definition if remaining_args_definition
|
251
|
+
result
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Returns a list of all custom acceptors used by this tool.
|
256
|
+
# @return [Array<Toys::Tool::Acceptor>]
|
257
|
+
#
|
258
|
+
def custom_acceptors
|
259
|
+
result = []
|
260
|
+
flag_definitions.each do |f|
|
261
|
+
result << f.accept if f.accept.is_a?(Acceptor)
|
262
|
+
end
|
263
|
+
arg_definitions.each do |a|
|
264
|
+
result << a.accept if a.accept.is_a?(Acceptor)
|
265
|
+
end
|
266
|
+
result.uniq
|
267
|
+
end
|
268
|
+
|
269
|
+
##
|
270
|
+
# Get the named helper from this tool or its ancestors.
|
271
|
+
#
|
272
|
+
# @param [String] name The helper name
|
273
|
+
# @return [Module,nil] The helper module, or `nil` if not found.
|
274
|
+
#
|
275
|
+
def resolve_helper(name)
|
276
|
+
@helpers.fetch(name.to_s) { |k| @parent ? @parent.resolve_helper(k) : nil }
|
277
|
+
end
|
278
|
+
|
279
|
+
##
|
280
|
+
# Include the given helper in the tool class.
|
281
|
+
#
|
282
|
+
# @param [String,Symbol,Module] name The helper name or module
|
283
|
+
#
|
284
|
+
def include_helper(name)
|
285
|
+
tool_class.include(name)
|
286
|
+
self
|
287
|
+
end
|
288
|
+
|
289
|
+
##
|
290
|
+
# Sets the path to the file that defines this tool.
|
291
|
+
# A tool may be defined from at most one path. If a different path is
|
292
|
+
# already set, raises {Toys::ToolDefinitionError}
|
293
|
+
#
|
294
|
+
# @param [String] path The path to the file defining this tool
|
295
|
+
#
|
296
|
+
def lock_source_path(path)
|
297
|
+
if source_path && source_path != path
|
298
|
+
raise ToolDefinitionError,
|
299
|
+
"Cannot redefine tool #{display_name.inspect} in #{path}" \
|
300
|
+
" (already defined in #{source_path})"
|
301
|
+
end
|
302
|
+
@source_path = path
|
303
|
+
end
|
304
|
+
|
305
|
+
##
|
306
|
+
# Set the short description string.
|
307
|
+
#
|
308
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
309
|
+
# single string (which will be wrapped), or an array of strings, which will
|
310
|
+
# be interpreted as string fragments that will be concatenated and wrapped.
|
311
|
+
#
|
312
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
313
|
+
#
|
314
|
+
def desc=(desc)
|
315
|
+
check_definition_state
|
316
|
+
@desc = Utils::WrappableString.make(desc)
|
317
|
+
end
|
318
|
+
|
319
|
+
##
|
320
|
+
# Set the long description strings.
|
321
|
+
#
|
322
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a single
|
323
|
+
# string (which will be wrapped), or an array of strings, which will be
|
324
|
+
# interpreted as string fragments that will be concatenated and wrapped.
|
325
|
+
#
|
326
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] long_desc
|
327
|
+
#
|
328
|
+
def long_desc=(long_desc)
|
329
|
+
check_definition_state
|
330
|
+
@long_desc = Utils::WrappableString.make_array(long_desc)
|
331
|
+
end
|
332
|
+
|
333
|
+
##
|
334
|
+
# Add an acceptor to the tool. This acceptor may be refereneced by name
|
335
|
+
# when adding a flag or an arg.
|
336
|
+
#
|
337
|
+
# @param [Toys::Tool::Acceptor] acceptor The acceptor to add.
|
338
|
+
#
|
339
|
+
def add_acceptor(acceptor)
|
340
|
+
@acceptors[acceptor.name] = acceptor
|
341
|
+
self
|
342
|
+
end
|
343
|
+
|
344
|
+
##
|
345
|
+
# Add a named helper module to this tool.
|
346
|
+
#
|
347
|
+
# @param [String] name The name of the helper.
|
348
|
+
# @param [Module] helper_module The helper module.
|
349
|
+
#
|
350
|
+
def add_helper(name, helper_module)
|
351
|
+
@helpers[name.to_s] = helper_module
|
352
|
+
self
|
353
|
+
end
|
354
|
+
|
355
|
+
##
|
356
|
+
# Add a flag to the current tool. Each flag must specify a key which
|
357
|
+
# the script may use to obtain the flag value from the context.
|
358
|
+
# You may then provide the flags themselves in `OptionParser` form.
|
359
|
+
#
|
360
|
+
# @param [Symbol] key The key to use to retrieve the value from the
|
361
|
+
# execution context.
|
362
|
+
# @param [Array<String>] flags The flags in OptionParser format.
|
363
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
364
|
+
# value. You may provide either the name of an acceptor you have
|
365
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
366
|
+
# Optional. If not specified, accepts any value as a string.
|
367
|
+
# @param [Object] default The default value. This is the value that will
|
368
|
+
# be set in the context if this flag is not provided on the command
|
369
|
+
# line. Defaults to `nil`.
|
370
|
+
# @param [Proc,nil] handler An optional handler for setting/updating the
|
371
|
+
# value. If given, it should take two arguments, the new given value
|
372
|
+
# and the previous value, and it should return the new value that
|
373
|
+
# should be set. The default handler simply replaces the previous
|
374
|
+
# value. i.e. the default is effectively `-> (val, _prev) { val }`.
|
375
|
+
# @param [Boolean] report_collisions Raise an exception if a flag is
|
376
|
+
# requested that is already in use or marked as disabled. Default is
|
377
|
+
# true.
|
378
|
+
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
379
|
+
# description for the flag. See {Toys::Tool#desc=} for a description of
|
380
|
+
# allowed formats. Defaults to the empty string.
|
381
|
+
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
382
|
+
# Long description for the flag. See {Toys::Tool#long_desc=} for a
|
383
|
+
# description of allowed formats. Defaults to the empty array.
|
384
|
+
#
|
385
|
+
def add_flag(key, flags = [],
|
386
|
+
accept: nil, default: nil, handler: nil,
|
387
|
+
report_collisions: true,
|
388
|
+
desc: nil, long_desc: nil)
|
389
|
+
check_definition_state
|
390
|
+
accept = resolve_acceptor(accept)
|
391
|
+
flag_def = Definition::Flag.new(key, flags, @used_flags, report_collisions,
|
392
|
+
accept, handler, default)
|
393
|
+
flag_def.desc = desc if desc
|
394
|
+
flag_def.long_desc = long_desc if long_desc
|
395
|
+
@flag_definitions << flag_def if flag_def.active?
|
396
|
+
@default_data[key] = default
|
397
|
+
self
|
398
|
+
end
|
399
|
+
|
400
|
+
##
|
401
|
+
# Mark one or more flags as disabled, preventing their use by any
|
402
|
+
# subsequent flag definition. This may be used to prevent middleware from
|
403
|
+
# defining a particular flag.
|
404
|
+
#
|
405
|
+
# @param [String...] flags The flags to disable
|
406
|
+
#
|
407
|
+
def disable_flag(*flags)
|
408
|
+
flags = flags.uniq
|
409
|
+
intersection = @used_flags & flags
|
410
|
+
unless intersection.empty?
|
411
|
+
raise ToolDefinitionError, "Cannot disable flags already used: #{intersection.inspect}"
|
412
|
+
end
|
413
|
+
@used_flags.concat(flags)
|
414
|
+
self
|
415
|
+
end
|
416
|
+
|
417
|
+
##
|
418
|
+
# Add a required positional argument to the current tool. You must specify
|
419
|
+
# a key which the script may use to obtain the argument value from the
|
420
|
+
# context.
|
421
|
+
#
|
422
|
+
# @param [Symbol] key The key to use to retrieve the value from the
|
423
|
+
# execution context.
|
424
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
425
|
+
# value. You may provide either the name of an acceptor you have
|
426
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
427
|
+
# Optional. If not specified, accepts any value as a string.
|
428
|
+
# @param [String] display_name A name to use for display (in help text and
|
429
|
+
# error reports). Defaults to the key in upper case.
|
430
|
+
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
431
|
+
# description for the flag. See {Toys::Tool#desc=} for a description of
|
432
|
+
# allowed formats. Defaults to the empty string.
|
433
|
+
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
434
|
+
# Long description for the flag. See {Toys::Tool#long_desc=} for a
|
435
|
+
# description of allowed formats. Defaults to the empty array.
|
436
|
+
#
|
437
|
+
def add_required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil)
|
438
|
+
check_definition_state
|
439
|
+
accept = resolve_acceptor(accept)
|
440
|
+
arg_def = Definition::Arg.new(key, :required, accept, nil, desc, long_desc, display_name)
|
441
|
+
@required_arg_definitions << arg_def
|
442
|
+
self
|
443
|
+
end
|
444
|
+
|
445
|
+
##
|
446
|
+
# Add an optional positional argument to the current tool. You must specify
|
447
|
+
# a key which the script may use to obtain the argument value from the
|
448
|
+
# context. If an optional argument is not given on the command line, the
|
449
|
+
# value is set to the given default.
|
450
|
+
#
|
451
|
+
# @param [Symbol] key The key to use to retrieve the value from the
|
452
|
+
# execution context.
|
453
|
+
# @param [Object] default The default value. This is the value that will
|
454
|
+
# be set in the context if this argument is not provided on the command
|
455
|
+
# line. Defaults to `nil`.
|
456
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
457
|
+
# value. You may provide either the name of an acceptor you have
|
458
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
459
|
+
# Optional. If not specified, accepts any value as a string.
|
460
|
+
# @param [String] display_name A name to use for display (in help text and
|
461
|
+
# error reports). Defaults to the key in upper case.
|
462
|
+
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
463
|
+
# description for the flag. See {Toys::Tool#desc=} for a description of
|
464
|
+
# allowed formats. Defaults to the empty string.
|
465
|
+
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
466
|
+
# Long description for the flag. See {Toys::Tool#long_desc=} for a
|
467
|
+
# description of allowed formats. Defaults to the empty array.
|
468
|
+
#
|
469
|
+
def add_optional_arg(key, default: nil, accept: nil, display_name: nil,
|
470
|
+
desc: nil, long_desc: nil)
|
471
|
+
check_definition_state
|
472
|
+
accept = resolve_acceptor(accept)
|
473
|
+
arg_def = Definition::Arg.new(key, :optional, accept, default,
|
474
|
+
desc, long_desc, display_name)
|
475
|
+
@optional_arg_definitions << arg_def
|
476
|
+
@default_data[key] = default
|
477
|
+
self
|
478
|
+
end
|
479
|
+
|
480
|
+
##
|
481
|
+
# Specify what should be done with unmatched positional arguments. You must
|
482
|
+
# specify a key which the script may use to obtain the remaining args
|
483
|
+
# from the context.
|
484
|
+
#
|
485
|
+
# @param [Symbol] key The key to use to retrieve the value from the
|
486
|
+
# execution context.
|
487
|
+
# @param [Object] default The default value. This is the value that will
|
488
|
+
# be set in the context if no unmatched arguments are provided on the
|
489
|
+
# command line. Defaults to the empty array `[]`.
|
490
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
491
|
+
# value. You may provide either the name of an acceptor you have
|
492
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
493
|
+
# Optional. If not specified, accepts any value as a string.
|
494
|
+
# @param [String] display_name A name to use for display (in help text and
|
495
|
+
# error reports). Defaults to the key in upper case.
|
496
|
+
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
497
|
+
# description for the flag. See {Toys::Tool#desc=} for a description of
|
498
|
+
# allowed formats. Defaults to the empty string.
|
499
|
+
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
500
|
+
# Long description for the flag. See {Toys::Tool#long_desc=} for a
|
501
|
+
# description of allowed formats. Defaults to the empty array.
|
502
|
+
#
|
503
|
+
def set_remaining_args(key, default: [], accept: nil, display_name: nil,
|
504
|
+
desc: nil, long_desc: nil)
|
505
|
+
check_definition_state
|
506
|
+
accept = resolve_acceptor(accept)
|
507
|
+
arg_def = Definition::Arg.new(key, :remaining, accept, default,
|
508
|
+
desc, long_desc, display_name)
|
509
|
+
@remaining_args_definition = arg_def
|
510
|
+
@default_data[key] = default
|
511
|
+
self
|
512
|
+
end
|
513
|
+
|
514
|
+
##
|
515
|
+
# Set the runnable block
|
516
|
+
#
|
517
|
+
# @param [Proc] proc The runnable block
|
518
|
+
#
|
519
|
+
def runnable=(proc)
|
520
|
+
@tool_class.run(&proc)
|
521
|
+
end
|
522
|
+
|
523
|
+
##
|
524
|
+
# Mark this tool as runnable. Should be called from the DSL only.
|
525
|
+
# @private
|
526
|
+
#
|
527
|
+
def mark_runnable
|
528
|
+
check_definition_state
|
529
|
+
@runnable = true
|
530
|
+
self
|
531
|
+
end
|
532
|
+
|
533
|
+
##
|
534
|
+
# Complete definition and run middleware configs. Should be called from
|
535
|
+
# the Loader only.
|
536
|
+
# @private
|
537
|
+
#
|
538
|
+
def finish_definition(loader)
|
539
|
+
unless @definition_finished
|
540
|
+
ContextualError.capture("Error installing tool middleware!", tool_name: full_name) do
|
541
|
+
config_proc = proc {}
|
542
|
+
middleware_stack.reverse.each do |middleware|
|
543
|
+
config_proc = make_config_proc(middleware, loader, config_proc)
|
544
|
+
end
|
545
|
+
config_proc.call
|
546
|
+
end
|
547
|
+
@definition_finished = true
|
548
|
+
end
|
549
|
+
self
|
550
|
+
end
|
551
|
+
|
552
|
+
private
|
553
|
+
|
554
|
+
def make_config_proc(middleware, loader, next_config)
|
555
|
+
proc { middleware.config(self, loader, &next_config) }
|
556
|
+
end
|
557
|
+
|
558
|
+
def check_definition_state
|
559
|
+
if @definition_finished
|
560
|
+
raise ToolDefinitionError,
|
561
|
+
"Defintion of tool #{display_name.inspect} is already finished"
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
def resolve_acceptor(accept)
|
566
|
+
return accept if accept.nil? || accept.is_a?(Acceptor)
|
567
|
+
unless @acceptors.key?(accept)
|
568
|
+
raise ToolDefinitionError, "Unknown acceptor: #{accept.inspect}"
|
569
|
+
end
|
570
|
+
@acceptors[accept]
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|