tty-option 0.2.0 → 0.3.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 +25 -0
- data/README.md +1200 -488
- data/lib/tty/option/conversions.rb +27 -17
- data/lib/tty/option/deep_dup.rb +43 -19
- data/lib/tty/option/errors.rb +33 -3
- data/lib/tty/option/formatter.rb +364 -69
- data/lib/tty/option/param_permitted.rb +7 -3
- data/lib/tty/option/param_validation.rb +124 -20
- data/lib/tty/option/parameter.rb +2 -1
- data/lib/tty/option/parser/options.rb +6 -1
- data/lib/tty/option/version.rb +1 -1
- metadata +3 -2
data/lib/tty/option/formatter.rb
CHANGED
@@ -5,30 +5,55 @@ require_relative "usage_wrapper"
|
|
5
5
|
|
6
6
|
module TTY
|
7
7
|
module Option
|
8
|
+
# Responsible for formatting help display
|
9
|
+
#
|
10
|
+
# @api private
|
8
11
|
class Formatter
|
9
12
|
include UsageWrapper
|
10
13
|
|
11
|
-
|
14
|
+
BOOLEANS = [true, false].freeze
|
12
15
|
DEFAULT_WIDTH = 80
|
13
|
-
|
16
|
+
DOUBLE_SPACE = " "
|
14
17
|
ELLIPSIS = "..."
|
18
|
+
EMPTY = ""
|
19
|
+
LIST_SEPARATOR = ", "
|
20
|
+
MAP_SEPARATOR = ":"
|
21
|
+
NEWLINE = "\n"
|
15
22
|
SPACE = " "
|
16
23
|
|
17
|
-
|
24
|
+
DEFAULT_NAME_SELECTOR = ->(param) { param.name }
|
18
25
|
DEFAULT_ORDER = ->(params) { params.sort }
|
26
|
+
DEFAULT_PARAM_DISPLAY = ->(str) { str.to_s.upcase }
|
19
27
|
NOOP_PROC = ->(param) { param }
|
20
|
-
DEFAULT_NAME_SELECTOR = ->(param) { param.name }
|
21
28
|
|
29
|
+
# Generate help for parameters and usage
|
30
|
+
#
|
31
|
+
# @param [TTY::Option::Parameters] parameters
|
32
|
+
# the parameters to format
|
33
|
+
# @param [TTY::Option::Usage] usage
|
34
|
+
# the usage to format
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
#
|
22
38
|
# @api public
|
23
39
|
def self.help(parameters, usage, **config, &block)
|
24
40
|
new(parameters, usage, **config).help(&block)
|
25
41
|
end
|
26
42
|
|
27
|
-
|
28
|
-
|
29
|
-
# Create a help formatter
|
43
|
+
# Create a Formatter instance
|
30
44
|
#
|
31
|
-
# @param [Parameters]
|
45
|
+
# @param [TTY::Option::Parameters] parameters
|
46
|
+
# the parameters to format
|
47
|
+
# @param [TTY::Option::Usage] usage
|
48
|
+
# the usage to format
|
49
|
+
# @param [Proc] param_display
|
50
|
+
# the parameter display formatter, by default, uppercases all chars
|
51
|
+
# @param [Integer] width
|
52
|
+
# the width at which to wrap the help display, by default 80 columns
|
53
|
+
# @param [Proc] order
|
54
|
+
# the order for displaying parameters, by default alphabetical
|
55
|
+
# @param [Integer] indent
|
56
|
+
# the indent for help display
|
32
57
|
#
|
33
58
|
# @api public
|
34
59
|
def initialize(parameters, usage, param_display: DEFAULT_PARAM_DISPLAY,
|
@@ -51,7 +76,10 @@ module TTY
|
|
51
76
|
}
|
52
77
|
end
|
53
78
|
|
54
|
-
#
|
79
|
+
# Generate help display
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# formatter.help
|
55
83
|
#
|
56
84
|
# @yieldparam [TTY::Option::Sections] sections
|
57
85
|
#
|
@@ -90,18 +118,50 @@ module TTY
|
|
90
118
|
formatted.end_with?(NEWLINE) ? formatted : formatted + NEWLINE
|
91
119
|
end
|
92
120
|
|
121
|
+
# Generate help header
|
122
|
+
#
|
123
|
+
# @example
|
124
|
+
# formatter.help_header
|
125
|
+
#
|
126
|
+
# @return [String]
|
127
|
+
#
|
128
|
+
# @api public
|
93
129
|
def help_header
|
94
130
|
"#{format_multiline(@usage.header, @indent)}#{NEWLINE}"
|
95
131
|
end
|
96
132
|
|
133
|
+
# Generate help banner
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# formatter.help_banner
|
137
|
+
#
|
138
|
+
# @return [String]
|
139
|
+
#
|
140
|
+
# @api public
|
97
141
|
def help_banner
|
98
142
|
(@usage.banner? ? @usage.banner : format_usage)
|
99
143
|
end
|
100
144
|
|
145
|
+
# Generate help description
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# formatter.help_description
|
149
|
+
#
|
150
|
+
# @return [String]
|
151
|
+
#
|
152
|
+
# @api public
|
101
153
|
def help_description
|
102
154
|
"#{NEWLINE}#{format_description}"
|
103
155
|
end
|
104
156
|
|
157
|
+
# Generate help arguments
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# formatter.help_arguments
|
161
|
+
#
|
162
|
+
# @return [String]
|
163
|
+
#
|
164
|
+
# @api public
|
105
165
|
def help_arguments
|
106
166
|
"#{NEWLINE}#{@space_indent}#{@section_names[:arguments]}#{NEWLINE}" +
|
107
167
|
format_section(@parameters.arguments, ->(param) do
|
@@ -109,6 +169,14 @@ module TTY
|
|
109
169
|
end)
|
110
170
|
end
|
111
171
|
|
172
|
+
# Generate help keywords
|
173
|
+
#
|
174
|
+
# @example
|
175
|
+
# formatter.help_keywords
|
176
|
+
#
|
177
|
+
# @return [String]
|
178
|
+
#
|
179
|
+
# @api public
|
112
180
|
def help_keywords
|
113
181
|
"#{NEWLINE}#{@space_indent}#{@section_names[:keywords]}#{NEWLINE}" +
|
114
182
|
format_section(@parameters.keywords, ->(param) do
|
@@ -116,28 +184,62 @@ module TTY
|
|
116
184
|
end)
|
117
185
|
end
|
118
186
|
|
187
|
+
# Generate help options
|
188
|
+
#
|
189
|
+
# @example
|
190
|
+
# formatter.help_options
|
191
|
+
#
|
192
|
+
# @return [String]
|
193
|
+
#
|
194
|
+
# @api public
|
119
195
|
def help_options
|
120
196
|
"#{NEWLINE}#{@space_indent}#{@section_names[:options]}#{NEWLINE}" +
|
121
197
|
format_options
|
122
198
|
end
|
123
199
|
|
200
|
+
# Generate help environment variables
|
201
|
+
#
|
202
|
+
# @example
|
203
|
+
# formatter.help_environments
|
204
|
+
#
|
205
|
+
# @return [String]
|
206
|
+
#
|
207
|
+
# @api public
|
124
208
|
def help_environments
|
125
209
|
"#{NEWLINE}#{@space_indent}#{@section_names[:env]}#{NEWLINE}" +
|
126
210
|
format_section(@order.(@parameters.environments))
|
127
211
|
end
|
128
212
|
|
213
|
+
# Generate help examples
|
214
|
+
#
|
215
|
+
# @example
|
216
|
+
# formatter.help_examples
|
217
|
+
#
|
218
|
+
# @return [String]
|
219
|
+
#
|
220
|
+
# @api public
|
129
221
|
def help_examples
|
130
222
|
"#{NEWLINE}#{@space_indent}#{@section_names[:examples]}#{NEWLINE}" +
|
131
223
|
format_examples
|
132
224
|
end
|
133
225
|
|
226
|
+
# Generate help footer
|
227
|
+
#
|
228
|
+
# @example
|
229
|
+
# formatter.help_footer
|
230
|
+
#
|
231
|
+
# @return [String]
|
232
|
+
#
|
233
|
+
# @api public
|
134
234
|
def help_footer
|
135
235
|
"#{NEWLINE}#{format_multiline(@usage.footer, @indent)}"
|
136
236
|
end
|
137
237
|
|
138
238
|
private
|
139
239
|
|
140
|
-
#
|
240
|
+
# Format default usage banner
|
241
|
+
#
|
242
|
+
# @return [String]
|
141
243
|
#
|
142
244
|
# @api private
|
143
245
|
def format_usage
|
@@ -149,10 +251,12 @@ module TTY
|
|
149
251
|
output << " [#{@param_display.("environment")}]" if @parameters.environments?
|
150
252
|
output << " #{format_arguments_usage}" if @parameters.arguments?
|
151
253
|
output << " #{format_keywords_usage}" if @parameters.keywords?
|
152
|
-
usage + wrap(output.join, indent: usage.length, width: width)
|
254
|
+
usage + wrap(output.join, indent: usage.length, width: @width)
|
153
255
|
end
|
154
256
|
|
155
|
-
# Format arguments
|
257
|
+
# Format arguments usage
|
258
|
+
#
|
259
|
+
# @return [String]
|
156
260
|
#
|
157
261
|
# @api private
|
158
262
|
def format_arguments_usage
|
@@ -165,7 +269,12 @@ module TTY
|
|
165
269
|
end.join(SPACE)
|
166
270
|
end
|
167
271
|
|
168
|
-
#
|
272
|
+
# Format argument usage
|
273
|
+
#
|
274
|
+
# @param [TTY::Option::Parameter::Argument] arg
|
275
|
+
# the argument to format
|
276
|
+
#
|
277
|
+
# @return [String]
|
169
278
|
#
|
170
279
|
# @api private
|
171
280
|
def format_argument_usage(arg)
|
@@ -175,6 +284,13 @@ module TTY
|
|
175
284
|
|
176
285
|
# Format parameter usage
|
177
286
|
#
|
287
|
+
# @param [TTY::Option::Parameter] param
|
288
|
+
# the parameter to format
|
289
|
+
# @param [String] param_name
|
290
|
+
# the parameter name
|
291
|
+
#
|
292
|
+
# @return [String]
|
293
|
+
#
|
178
294
|
# @api private
|
179
295
|
def format_parameter_usage(param, param_name)
|
180
296
|
args = []
|
@@ -193,6 +309,8 @@ module TTY
|
|
193
309
|
|
194
310
|
# Format keywords usage
|
195
311
|
#
|
312
|
+
# @return [String]
|
313
|
+
#
|
196
314
|
# @api private
|
197
315
|
def format_keywords_usage
|
198
316
|
return "" unless @parameters.keywords?
|
@@ -204,7 +322,12 @@ module TTY
|
|
204
322
|
end.join(SPACE)
|
205
323
|
end
|
206
324
|
|
207
|
-
#
|
325
|
+
# Format keyword usage
|
326
|
+
#
|
327
|
+
# @param [TTY::Option::Parameter::Keyword] kwarg
|
328
|
+
# the keyword to format
|
329
|
+
#
|
330
|
+
# @return [String]
|
208
331
|
#
|
209
332
|
# @api private
|
210
333
|
def format_keyword_usage(kwarg)
|
@@ -212,7 +335,14 @@ module TTY
|
|
212
335
|
format_parameter_usage(kwarg, param_name)
|
213
336
|
end
|
214
337
|
|
215
|
-
#
|
338
|
+
# Format keyword name
|
339
|
+
#
|
340
|
+
# @param [TTY::Option::Parameter::Keyword] kwarg
|
341
|
+
# the keyword to format
|
342
|
+
# @param [Proc] param_display
|
343
|
+
# the parameter display formatter, by default, uppercases all chars
|
344
|
+
#
|
345
|
+
# @return [String]
|
216
346
|
#
|
217
347
|
# @api private
|
218
348
|
def kwarg_param_display(kwarg, param_display = NOOP_PROC)
|
@@ -227,19 +357,18 @@ module TTY
|
|
227
357
|
"#{kwarg_name}=#{conv_name}"
|
228
358
|
end
|
229
359
|
|
230
|
-
# Format
|
231
|
-
#
|
232
|
-
# @param [String] parameters_name
|
233
|
-
# the name of parameter type
|
360
|
+
# Format section parameters
|
234
361
|
#
|
362
|
+
# @param [Array<TTY::Option::Parameter>] params
|
363
|
+
# the parameters to format
|
235
364
|
# @param [Proc] name_selector
|
236
|
-
#
|
365
|
+
# the parameter name selector, by default, calls the name
|
237
366
|
#
|
238
367
|
# @return [String]
|
239
368
|
#
|
240
369
|
# @api private
|
241
370
|
def format_section(params, name_selector = DEFAULT_NAME_SELECTOR)
|
242
|
-
longest_param = params
|
371
|
+
longest_param = find_longest_parameter(params, &name_selector)
|
243
372
|
|
244
373
|
params.reduce([]) do |acc, param|
|
245
374
|
next acc if param.hidden?
|
@@ -248,44 +377,45 @@ module TTY
|
|
248
377
|
end.join(NEWLINE)
|
249
378
|
end
|
250
379
|
|
251
|
-
# Format
|
380
|
+
# Format section parameter
|
381
|
+
#
|
382
|
+
# @param [TTY::Option::Parameter] param
|
383
|
+
# the parameter to format
|
384
|
+
# @param [Integer] longest_param
|
385
|
+
# the longest parameter length
|
386
|
+
# @param [Proc] name_selector
|
387
|
+
# the parameter name selector, by default, calls the name
|
252
388
|
#
|
253
389
|
# @return [String]
|
254
390
|
#
|
255
391
|
# @api private
|
256
392
|
def format_section_parameter(param, longest_param, name_selector)
|
257
393
|
line = []
|
258
|
-
desc = []
|
259
|
-
indent = @param_indent + longest_param + 2
|
260
394
|
param_name = name_selector.(param)
|
395
|
+
description = parameter_description?(param)
|
396
|
+
template = description ? "%s%-#{longest_param}s" : "%s%s"
|
261
397
|
|
262
|
-
|
263
|
-
line << format("%s%-#{longest_param}s", SPACE * @param_indent, param_name)
|
264
|
-
desc << " #{param.desc}"
|
265
|
-
else
|
266
|
-
line << format("%s%s", SPACE * @param_indent, param_name)
|
267
|
-
end
|
398
|
+
line << format(template, SPACE * @param_indent, param_name)
|
268
399
|
|
269
|
-
if
|
270
|
-
desc
|
400
|
+
if description
|
401
|
+
desc = format_parameter_description(param)
|
402
|
+
indent = @param_indent + longest_param + 2
|
403
|
+
line << wrap(desc, indent: indent, width: @width)
|
271
404
|
end
|
272
405
|
|
273
|
-
if (default = format_default(param))
|
274
|
-
desc << default
|
275
|
-
end
|
276
|
-
|
277
|
-
line << wrap(desc.join, indent: indent, width: width)
|
278
406
|
line.join
|
279
407
|
end
|
280
408
|
|
281
409
|
# Format multiline description
|
282
410
|
#
|
411
|
+
# @return [String]
|
412
|
+
#
|
283
413
|
# @api private
|
284
414
|
def format_description
|
285
415
|
format_multiline(@usage.desc, @indent)
|
286
416
|
end
|
287
417
|
|
288
|
-
#
|
418
|
+
# Format options
|
289
419
|
#
|
290
420
|
# @return [String]
|
291
421
|
#
|
@@ -293,69 +423,225 @@ module TTY
|
|
293
423
|
def format_options
|
294
424
|
return "" if @parameters.options.empty?
|
295
425
|
|
296
|
-
longest_option = @parameters.options.map(&:long)
|
297
|
-
.compact.max_by(&:length).length
|
298
|
-
any_short = @parameters.options.map(&:short).compact.any?
|
299
426
|
ordered_options = @order.(@parameters.options)
|
427
|
+
longest_short = find_longest_short_option
|
428
|
+
longest_long = find_longest_long_option
|
300
429
|
|
301
430
|
ordered_options.reduce([]) do |acc, option|
|
302
431
|
next acc if option.hidden?
|
303
|
-
|
432
|
+
|
433
|
+
acc << format_option(option, longest_short, longest_long)
|
304
434
|
end.join(NEWLINE)
|
305
435
|
end
|
306
436
|
|
437
|
+
# Find the longest short option
|
438
|
+
#
|
439
|
+
# @return [Integer, nil]
|
440
|
+
#
|
441
|
+
# @api private
|
442
|
+
def find_longest_short_option
|
443
|
+
short_options = @parameters.options.select(&:short?)
|
444
|
+
find_longest_parameter(short_options) do |option|
|
445
|
+
option.long? ? option.short_name : option.short
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
# Find the longest long option
|
450
|
+
#
|
451
|
+
# @return [Integer, nil]
|
452
|
+
#
|
453
|
+
# @api private
|
454
|
+
def find_longest_long_option
|
455
|
+
long_options = @parameters.options.select(&:long?)
|
456
|
+
find_longest_parameter(long_options, &:long)
|
457
|
+
end
|
458
|
+
|
459
|
+
# Find the longest parameter
|
460
|
+
#
|
461
|
+
# @param [Array<TTY::Option::Parameter>] params
|
462
|
+
# the parameters to search
|
463
|
+
#
|
464
|
+
# @yield [TTY::Option::Parameter]
|
465
|
+
#
|
466
|
+
# @return [Integer, nil]
|
467
|
+
#
|
468
|
+
# @api private
|
469
|
+
def find_longest_parameter(params, &name_selector)
|
470
|
+
params = params.reject(&:hidden?).map(&name_selector)
|
471
|
+
|
472
|
+
params.max_by(&:length).length if params.any?
|
473
|
+
end
|
474
|
+
|
307
475
|
# Format an option
|
308
476
|
#
|
477
|
+
# @param [TTY::Option::Parameter::Option] option
|
478
|
+
# the option to format
|
479
|
+
# @param [Integer, nil] longest_short
|
480
|
+
# the longest short option length or nil
|
481
|
+
# @param [Integer, nil] longest_long
|
482
|
+
# the longest long option length or nil
|
483
|
+
#
|
484
|
+
# @return [String]
|
485
|
+
#
|
309
486
|
# @api private
|
310
|
-
def format_option(option,
|
487
|
+
def format_option(option, longest_short, longest_long)
|
311
488
|
line = [@space_indent]
|
312
|
-
desc = []
|
313
489
|
indent = @indent
|
314
490
|
|
315
|
-
if
|
316
|
-
|
317
|
-
|
318
|
-
indent += SHORT_OPT_LENGTH
|
491
|
+
if longest_short
|
492
|
+
line << " #{format_short_option(option, longest_short)}"
|
493
|
+
indent += line.last.length
|
319
494
|
end
|
320
495
|
|
321
|
-
|
322
|
-
|
323
|
-
|
496
|
+
if longest_long
|
497
|
+
separator = short_and_long_option_separator(option)
|
498
|
+
line << "#{separator}#{format_long_option(option, longest_long)}"
|
499
|
+
indent += line.last.length
|
500
|
+
end
|
324
501
|
|
502
|
+
if parameter_description?(option)
|
503
|
+
indent += 2
|
504
|
+
desc = format_parameter_description(option)
|
505
|
+
line << wrap(desc, indent: indent, width: @width)
|
506
|
+
end
|
507
|
+
|
508
|
+
line.join
|
509
|
+
end
|
510
|
+
|
511
|
+
# Format a short option
|
512
|
+
#
|
513
|
+
# @param [TTY::Option::Parameter::Option] option
|
514
|
+
# the option to format
|
515
|
+
# @param [Integer] longest
|
516
|
+
# the longest short option length
|
517
|
+
#
|
518
|
+
# @return [String]
|
519
|
+
#
|
520
|
+
# @api private
|
521
|
+
def format_short_option(option, longest)
|
522
|
+
if option.long?
|
523
|
+
format("%-#{longest}s", option.short_name)
|
524
|
+
elsif parameter_description?(option)
|
525
|
+
format("%-#{longest}s", option.short)
|
526
|
+
else
|
527
|
+
option.short
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
# Format a long option
|
532
|
+
#
|
533
|
+
# @param [TTY::Option::Parameter::Option] option
|
534
|
+
# the option to format
|
535
|
+
# @param [Integer] longest
|
536
|
+
# the longest long option length
|
537
|
+
#
|
538
|
+
# @return [String]
|
539
|
+
#
|
540
|
+
# @api private
|
541
|
+
def format_long_option(option, longest)
|
325
542
|
if option.long?
|
326
|
-
if option
|
327
|
-
|
543
|
+
if parameter_description?(option)
|
544
|
+
format("%-#{longest}s", option.long)
|
328
545
|
else
|
329
|
-
|
546
|
+
option.long
|
330
547
|
end
|
331
|
-
|
332
|
-
|
548
|
+
elsif parameter_description?(option)
|
549
|
+
format("%-#{longest}s", SPACE)
|
333
550
|
end
|
334
|
-
|
551
|
+
end
|
335
552
|
|
336
|
-
|
337
|
-
|
553
|
+
# Short and long option separator
|
554
|
+
#
|
555
|
+
# @param [TTY::Option::Parameter::Option] option
|
556
|
+
# the option to separate short and long names
|
557
|
+
#
|
558
|
+
# @return [String]
|
559
|
+
#
|
560
|
+
# @api private
|
561
|
+
def short_and_long_option_separator(option)
|
562
|
+
if option.short? && option.long?
|
563
|
+
LIST_SEPARATOR
|
564
|
+
elsif option.long? || parameter_description?(option)
|
565
|
+
DOUBLE_SPACE
|
566
|
+
else
|
567
|
+
EMPTY
|
338
568
|
end
|
339
|
-
|
569
|
+
end
|
570
|
+
|
571
|
+
# Format a parameter description
|
572
|
+
#
|
573
|
+
# @param [TTY::Option::Parameter] param
|
574
|
+
# the parameter to format
|
575
|
+
#
|
576
|
+
# @return [String]
|
577
|
+
#
|
578
|
+
# @api private
|
579
|
+
def format_parameter_description(param)
|
580
|
+
desc = []
|
340
581
|
|
341
|
-
if
|
342
|
-
|
582
|
+
desc << " #{param.desc}" if param.desc?
|
583
|
+
|
584
|
+
if param.permit?
|
585
|
+
desc << SPACE unless param.desc?
|
586
|
+
desc << format_permitted(param.permit)
|
343
587
|
end
|
344
588
|
|
345
|
-
if (default = format_default(
|
589
|
+
if (default = format_default(param))
|
590
|
+
desc << SPACE unless param.desc?
|
346
591
|
desc << default
|
347
592
|
end
|
348
593
|
|
349
|
-
|
594
|
+
desc.join
|
595
|
+
end
|
350
596
|
|
351
|
-
|
597
|
+
# Check whether or not parameter has description
|
598
|
+
#
|
599
|
+
# @param [TTY::Option::Parameter] param
|
600
|
+
# the parameter to check for description
|
601
|
+
#
|
602
|
+
# @return [Boolean]
|
603
|
+
#
|
604
|
+
# @api private
|
605
|
+
def parameter_description?(param)
|
606
|
+
param.desc? || param.permit? || parameter_default?(param)
|
607
|
+
end
|
608
|
+
|
609
|
+
# Check whether or not parameter has default
|
610
|
+
#
|
611
|
+
# @param [TTY::Option::Parameter] param
|
612
|
+
# the parameter to check for default
|
613
|
+
#
|
614
|
+
# @return [Boolean]
|
615
|
+
#
|
616
|
+
# @api private
|
617
|
+
def parameter_default?(param)
|
618
|
+
param.default? && !BOOLEANS.include?(param.default)
|
619
|
+
end
|
620
|
+
|
621
|
+
# Format permitted values
|
622
|
+
#
|
623
|
+
# @param [Parameter] values
|
624
|
+
# the permitted values to format
|
625
|
+
#
|
626
|
+
# @return [String]
|
627
|
+
#
|
628
|
+
# @api private
|
629
|
+
def format_permitted(values)
|
630
|
+
format(" (permitted: %s)", values.map do |val|
|
631
|
+
val.respond_to?(:to_ary) ? val.join(MAP_SEPARATOR) : val
|
632
|
+
end.join(LIST_SEPARATOR))
|
352
633
|
end
|
353
634
|
|
354
|
-
# Format default value
|
635
|
+
# Format a default value
|
636
|
+
#
|
637
|
+
# @param [TTY::Option::Parameter] param
|
638
|
+
# the parameter to format
|
639
|
+
#
|
640
|
+
# @return [String]
|
355
641
|
#
|
356
642
|
# @api private
|
357
643
|
def format_default(param)
|
358
|
-
return
|
644
|
+
return unless parameter_default?(param)
|
359
645
|
|
360
646
|
if param.default.is_a?(String)
|
361
647
|
format(" (default %p)", param.default)
|
@@ -366,6 +652,8 @@ module TTY
|
|
366
652
|
|
367
653
|
# Format examples section
|
368
654
|
#
|
655
|
+
# @return [String]
|
656
|
+
#
|
369
657
|
# @api private
|
370
658
|
def format_examples
|
371
659
|
format_multiline(@usage.example, @param_indent)
|
@@ -373,15 +661,22 @@ module TTY
|
|
373
661
|
|
374
662
|
# Format multiline content
|
375
663
|
#
|
664
|
+
# @param [Array<Array<String>>] lines
|
665
|
+
# the lines to format
|
666
|
+
# @param [Integer] indent
|
667
|
+
# the indent for the lines
|
668
|
+
#
|
669
|
+
# @return [String]
|
670
|
+
#
|
376
671
|
# @api private
|
377
672
|
def format_multiline(lines, indent)
|
378
673
|
last_index = lines.size - 1
|
379
674
|
lines.map.with_index do |line, i|
|
380
675
|
line.map do |part|
|
381
676
|
part.split(NEWLINE).map do |p|
|
382
|
-
wrap(p, indent: indent, width: width, indent_first: true)
|
677
|
+
wrap(p, indent: indent, width: @width, indent_first: true)
|
383
678
|
end.join(NEWLINE)
|
384
|
-
end.join(NEWLINE) + (last_index
|
679
|
+
end.join(NEWLINE) + (last_index == i ? EMPTY : NEWLINE)
|
385
680
|
end.join(NEWLINE)
|
386
681
|
end
|
387
682
|
end # Formatter
|
@@ -13,12 +13,16 @@ module TTY
|
|
13
13
|
#
|
14
14
|
# @api public
|
15
15
|
def call(param, value)
|
16
|
-
return Result.success(value)
|
16
|
+
return Result.success(value) if !param.permit? || value.nil?
|
17
17
|
|
18
|
-
|
18
|
+
unpermitted = Array(value) - Array(param.permit)
|
19
|
+
|
20
|
+
if unpermitted.empty?
|
19
21
|
Result.success(value)
|
20
22
|
else
|
21
|
-
Result.failure(
|
23
|
+
Result.failure(unpermitted.map do |val|
|
24
|
+
UnpermittedArgument.new(param, val)
|
25
|
+
end)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
module_function :call
|