toys-core 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/toys-core.rb +3 -5
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/definition/flag.rb +57 -22
- data/lib/toys/definition/flag_group.rb +205 -0
- data/lib/toys/definition/tool.rb +71 -4
- data/lib/toys/dsl/flag.rb +36 -10
- data/lib/toys/dsl/flag_group.rb +108 -0
- data/lib/toys/dsl/tool.rb +177 -4
- data/lib/toys/runner.rb +13 -3
- data/lib/toys/standard_middleware.rb +47 -0
- data/lib/toys/standard_middleware/add_verbosity_flags.rb +5 -2
- data/lib/toys/standard_middleware/show_help.rb +13 -6
- data/lib/toys/utils/exec.rb +7 -4
- data/lib/toys/utils/gems.rb +1 -1
- data/lib/toys/utils/help_text.rb +94 -26
- metadata +5 -2
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Daniel Azuma
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are met:
|
9
|
+
#
|
10
|
+
# * Redistributions of source code must retain the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer.
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
16
|
+
# contributors to this software, may be used to endorse or promote products
|
17
|
+
# derived from this software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
;
|
31
|
+
|
32
|
+
module Toys
|
33
|
+
##
|
34
|
+
# Namespace for standard middleware classes.
|
35
|
+
#
|
36
|
+
module StandardMiddleware
|
37
|
+
## @private
|
38
|
+
COMMON_FLAG_GROUP = :__common
|
39
|
+
|
40
|
+
## @private
|
41
|
+
def self.append_common_flag_group(tool)
|
42
|
+
tool.add_flag_group(type: :optional, name: COMMON_FLAG_GROUP,
|
43
|
+
desc: "Common Flags", report_collisions: false)
|
44
|
+
COMMON_FLAG_GROUP
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -82,6 +82,7 @@ module Toys
|
|
82
82
|
#
|
83
83
|
def config(tool_definition, _loader)
|
84
84
|
unless tool_definition.argument_parsing_disabled?
|
85
|
+
StandardMiddleware.append_common_flag_group(tool_definition)
|
85
86
|
add_verbose_flags(tool_definition)
|
86
87
|
add_quiet_flags(tool_definition)
|
87
88
|
end
|
@@ -99,7 +100,8 @@ module Toys
|
|
99
100
|
report_collisions: false,
|
100
101
|
handler: ->(_val, cur) { cur + 1 },
|
101
102
|
desc: "Increase verbosity",
|
102
|
-
long_desc: "Increase verbosity, causing additional logging levels to display."
|
103
|
+
long_desc: "Increase verbosity, causing additional logging levels to display.",
|
104
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
103
105
|
)
|
104
106
|
end
|
105
107
|
end
|
@@ -112,7 +114,8 @@ module Toys
|
|
112
114
|
report_collisions: false,
|
113
115
|
handler: ->(_val, cur) { cur - 1 },
|
114
116
|
desc: "Decrease verbosity",
|
115
|
-
long_desc: "Decrease verbosity, causing fewer logging levels to display."
|
117
|
+
long_desc: "Decrease verbosity, causing fewer logging levels to display.",
|
118
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
116
119
|
)
|
117
120
|
end
|
118
121
|
end
|
@@ -232,6 +232,7 @@ module Toys
|
|
232
232
|
#
|
233
233
|
def config(tool_definition, loader)
|
234
234
|
unless tool_definition.argument_parsing_disabled?
|
235
|
+
StandardMiddleware.append_common_flag_group(tool_definition)
|
235
236
|
has_subtools = loader.has_subtools?(tool_definition.full_name)
|
236
237
|
help_flags = add_help_flags(tool_definition)
|
237
238
|
usage_flags = add_usage_flags(tool_definition)
|
@@ -323,7 +324,8 @@ module Toys
|
|
323
324
|
tool_definition.add_flag(
|
324
325
|
SHOW_HELP_KEY, flags,
|
325
326
|
report_collisions: false,
|
326
|
-
desc: "Display help for this tool"
|
327
|
+
desc: "Display help for this tool",
|
328
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
327
329
|
)
|
328
330
|
end
|
329
331
|
flags
|
@@ -335,7 +337,8 @@ module Toys
|
|
335
337
|
tool_definition.add_flag(
|
336
338
|
SHOW_USAGE_KEY, flags,
|
337
339
|
report_collisions: false,
|
338
|
-
desc: "Display a brief usage string for this tool"
|
340
|
+
desc: "Display a brief usage string for this tool",
|
341
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
339
342
|
)
|
340
343
|
end
|
341
344
|
flags
|
@@ -347,7 +350,8 @@ module Toys
|
|
347
350
|
tool_definition.add_flag(
|
348
351
|
SHOW_LIST_KEY, flags,
|
349
352
|
report_collisions: false,
|
350
|
-
desc: "List the subtools under this tool"
|
353
|
+
desc: "List the subtools under this tool",
|
354
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
351
355
|
)
|
352
356
|
end
|
353
357
|
flags
|
@@ -362,7 +366,8 @@ module Toys
|
|
362
366
|
RECURSIVE_SUBTOOLS_KEY, flags,
|
363
367
|
report_collisions: false, default: @default_recursive,
|
364
368
|
desc: "List all subtools recursively when displaying help" \
|
365
|
-
" (default is #{@default_recursive})"
|
369
|
+
" (default is #{@default_recursive})",
|
370
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
366
371
|
)
|
367
372
|
end
|
368
373
|
flags
|
@@ -374,7 +379,8 @@ module Toys
|
|
374
379
|
tool_definition.add_flag(
|
375
380
|
SEARCH_STRING_KEY, flags,
|
376
381
|
report_collisions: false,
|
377
|
-
desc: "Search subtools for the given regular expression when displaying help"
|
382
|
+
desc: "Search subtools for the given regular expression when displaying help",
|
383
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
378
384
|
)
|
379
385
|
end
|
380
386
|
flags
|
@@ -390,7 +396,8 @@ module Toys
|
|
390
396
|
SHOW_ALL_SUBTOOLS_KEY, flags,
|
391
397
|
report_collisions: false, default: @default_show_all_subtools,
|
392
398
|
desc: "List all subtools including hidden subtools and namespaces" \
|
393
|
-
" (default is #{@default_show_all_subtools})"
|
399
|
+
" (default is #{@default_show_all_subtools})",
|
400
|
+
group: StandardMiddleware::COMMON_FLAG_GROUP
|
394
401
|
)
|
395
402
|
end
|
396
403
|
flags
|
data/lib/toys/utils/exec.rb
CHANGED
@@ -48,8 +48,11 @@ module Toys
|
|
48
48
|
# * **:env** (Hash) Environment variables to pass to the subprocess
|
49
49
|
# * **:logger** (Logger) Logger to use for logging the actual command.
|
50
50
|
# If not present, the command is not logged.
|
51
|
-
# * **:log_level** (Integer)
|
52
|
-
# Defaults to Logger::INFO if not present.
|
51
|
+
# * **:log_level** (Integer,false) Level for logging the actual command.
|
52
|
+
# Defaults to Logger::INFO if not present. You may also pass `false` to
|
53
|
+
# disable logging of the command.
|
54
|
+
# * **:log_cmd** (String) The string logged for the actual command.
|
55
|
+
# Defaults to the `inspect` representation of the command.
|
53
56
|
# * **:background** (Boolean) Runs the process in the background,
|
54
57
|
# returning a controller object instead of a result object.
|
55
58
|
# * **:in** Connects the input stream of the subprocess. See the section
|
@@ -456,7 +459,7 @@ module Toys
|
|
456
459
|
end
|
457
460
|
|
458
461
|
##
|
459
|
-
# Captures the remaining data in the
|
462
|
+
# Captures the remaining data in the standard output stream.
|
460
463
|
# After calling this, do not read directly from the stream.
|
461
464
|
#
|
462
465
|
def capture_out
|
@@ -464,7 +467,7 @@ module Toys
|
|
464
467
|
end
|
465
468
|
|
466
469
|
##
|
467
|
-
# Captures the remaining data in the
|
470
|
+
# Captures the remaining data in the standard error stream.
|
468
471
|
# After calling this, do not read directly from the stream.
|
469
472
|
#
|
470
473
|
def capture_err
|
data/lib/toys/utils/gems.rb
CHANGED
@@ -129,7 +129,7 @@ module Toys
|
|
129
129
|
if @suppress_confirm
|
130
130
|
@default_confirm
|
131
131
|
else
|
132
|
-
@terminal.confirm("Gem needed: #{requirements_text}. Install?",
|
132
|
+
@terminal.confirm("Gem needed: #{requirements_text}. Install? ",
|
133
133
|
default: @default_confirm)
|
134
134
|
end
|
135
135
|
unless response
|
data/lib/toys/utils/help_text.rb
CHANGED
@@ -193,7 +193,7 @@ module Toys
|
|
193
193
|
|
194
194
|
def assemble
|
195
195
|
add_synopsis_section
|
196
|
-
|
196
|
+
add_flag_group_sections
|
197
197
|
add_positional_arguments_section if @tool.runnable?
|
198
198
|
add_subtool_list_section
|
199
199
|
@result = @lines.join("\n") + "\n"
|
@@ -224,12 +224,14 @@ module Toys
|
|
224
224
|
([@binary_name] + @tool.full_name + ["TOOL", "[ARGUMENTS...]"]).join(" ")
|
225
225
|
end
|
226
226
|
|
227
|
-
def
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
227
|
+
def add_flag_group_sections
|
228
|
+
@tool.flag_groups.each do |group|
|
229
|
+
next if group.empty?
|
230
|
+
@lines << ""
|
231
|
+
@lines << group.desc.to_s + ":"
|
232
|
+
group.flag_definitions.each do |flag|
|
233
|
+
add_flag(flag)
|
234
|
+
end
|
233
235
|
end
|
234
236
|
end
|
235
237
|
|
@@ -328,7 +330,7 @@ module Toys
|
|
328
330
|
add_name_section
|
329
331
|
add_synopsis_section
|
330
332
|
add_description_section
|
331
|
-
|
333
|
+
add_flag_group_sections
|
332
334
|
add_positional_arguments_section
|
333
335
|
add_subtool_list_section
|
334
336
|
add_source_section
|
@@ -358,13 +360,9 @@ module Toys
|
|
358
360
|
def add_synopsis_section
|
359
361
|
@lines << ""
|
360
362
|
@lines << bold("SYNOPSIS")
|
361
|
-
if !@subtools.empty? && !@tool.runnable?
|
362
|
-
add_synopsis_clause(namespace_synopsis)
|
363
|
-
end
|
363
|
+
add_synopsis_clause(namespace_synopsis) if !@subtools.empty? && !@tool.runnable?
|
364
364
|
add_synopsis_clause(tool_synopsis)
|
365
|
-
if !@subtools.empty? && @tool.runnable?
|
366
|
-
add_synopsis_clause(namespace_synopsis)
|
367
|
-
end
|
365
|
+
add_synopsis_clause(namespace_synopsis) if !@subtools.empty? && @tool.runnable?
|
368
366
|
end
|
369
367
|
|
370
368
|
def add_synopsis_clause(synopsis)
|
@@ -377,8 +375,19 @@ module Toys
|
|
377
375
|
|
378
376
|
def tool_synopsis
|
379
377
|
synopsis = [full_binary_name]
|
380
|
-
@tool.
|
381
|
-
|
378
|
+
@tool.flag_groups.each do |flag_group|
|
379
|
+
case flag_group
|
380
|
+
when Definition::FlagGroup::Required
|
381
|
+
add_required_group_to_synopsis(flag_group, synopsis)
|
382
|
+
when Definition::FlagGroup::ExactlyOne
|
383
|
+
add_exactly_one_group_to_synopsis(flag_group, synopsis)
|
384
|
+
when Definition::FlagGroup::AtMostOne
|
385
|
+
add_at_most_one_group_to_synopsis(flag_group, synopsis)
|
386
|
+
when Definition::FlagGroup::AtLeastOne
|
387
|
+
add_at_least_one_group_to_synopsis(flag_group, synopsis)
|
388
|
+
else
|
389
|
+
add_ordinary_group_to_synopsis(flag_group, synopsis)
|
390
|
+
end
|
382
391
|
end
|
383
392
|
@tool.arg_definitions.each do |arg_info|
|
384
393
|
synopsis << arg_name(arg_info)
|
@@ -386,6 +395,57 @@ module Toys
|
|
386
395
|
wrap_indent_indent2(Utils::WrappableString.new(synopsis))
|
387
396
|
end
|
388
397
|
|
398
|
+
def add_ordinary_group_to_synopsis(flag_group, synopsis)
|
399
|
+
flag_group.flag_definitions.each do |flag_def|
|
400
|
+
synopsis << "[#{flag_spec_string(flag_def, true)}]"
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def add_required_group_to_synopsis(flag_group, synopsis)
|
405
|
+
flag_group.flag_definitions.each do |flag_def|
|
406
|
+
synopsis << "(#{flag_spec_string(flag_def, true)})"
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def add_exactly_one_group_to_synopsis(flag_group, synopsis)
|
411
|
+
return if flag_group.empty?
|
412
|
+
synopsis << "("
|
413
|
+
first = true
|
414
|
+
flag_group.flag_definitions.each do |flag_def|
|
415
|
+
if first
|
416
|
+
first = false
|
417
|
+
else
|
418
|
+
synopsis << "|"
|
419
|
+
end
|
420
|
+
synopsis << flag_spec_string(flag_def, true)
|
421
|
+
end
|
422
|
+
synopsis << ")"
|
423
|
+
end
|
424
|
+
|
425
|
+
def add_at_most_one_group_to_synopsis(flag_group, synopsis)
|
426
|
+
return if flag_group.empty?
|
427
|
+
synopsis << "["
|
428
|
+
first = true
|
429
|
+
flag_group.flag_definitions.each do |flag_def|
|
430
|
+
if first
|
431
|
+
first = false
|
432
|
+
else
|
433
|
+
synopsis << "|"
|
434
|
+
end
|
435
|
+
synopsis << flag_spec_string(flag_def, true)
|
436
|
+
end
|
437
|
+
synopsis << "]"
|
438
|
+
end
|
439
|
+
|
440
|
+
def add_at_least_one_group_to_synopsis(flag_group, synopsis)
|
441
|
+
return if flag_group.empty?
|
442
|
+
synopsis << "("
|
443
|
+
flag_group.flag_definitions.each do |flag_def|
|
444
|
+
synopsis << "[#{flag_spec_string(flag_def, true)}]"
|
445
|
+
end
|
446
|
+
synopsis << ")"
|
447
|
+
end
|
448
|
+
|
389
449
|
def namespace_synopsis
|
390
450
|
synopsis = [full_binary_name, underline("TOOL"), "[#{underline('ARGUMENTS')}...]"]
|
391
451
|
wrap_indent_indent2(Utils::WrappableString.new(synopsis))
|
@@ -412,18 +472,26 @@ module Toys
|
|
412
472
|
end
|
413
473
|
end
|
414
474
|
|
415
|
-
def
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
475
|
+
def add_flag_group_sections
|
476
|
+
@tool.flag_groups.each do |group|
|
477
|
+
next if group.empty?
|
478
|
+
@lines << ""
|
479
|
+
@lines << bold(group.desc.to_s.upcase)
|
480
|
+
precede_with_blank = false
|
481
|
+
unless group.long_desc.empty?
|
482
|
+
wrap_indent(group.long_desc).each do |line|
|
483
|
+
@lines << indent_str(line)
|
484
|
+
end
|
485
|
+
precede_with_blank = true
|
486
|
+
end
|
487
|
+
group.flag_definitions.each do |flag|
|
488
|
+
add_indented_section(flag_spec_string(flag), flag, precede_with_blank)
|
489
|
+
precede_with_blank = true
|
490
|
+
end
|
423
491
|
end
|
424
492
|
end
|
425
493
|
|
426
|
-
def flag_spec_string(flag)
|
494
|
+
def flag_spec_string(flag, in_synopsis = false)
|
427
495
|
flag.flag_syntax.map do |fs|
|
428
496
|
str = bold(fs.str_without_value)
|
429
497
|
if fs.flag_type != :value
|
@@ -433,7 +501,7 @@ module Toys
|
|
433
501
|
else
|
434
502
|
"#{str}#{fs.value_delim}#{underline(fs.value_label)}"
|
435
503
|
end
|
436
|
-
end.join(", ")
|
504
|
+
end.join(in_synopsis ? " | " : ", ")
|
437
505
|
end
|
438
506
|
|
439
507
|
def add_positional_arguments_section
|
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.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -128,10 +128,12 @@ files:
|
|
128
128
|
- lib/toys/definition/alias.rb
|
129
129
|
- lib/toys/definition/arg.rb
|
130
130
|
- lib/toys/definition/flag.rb
|
131
|
+
- lib/toys/definition/flag_group.rb
|
131
132
|
- lib/toys/definition/source_info.rb
|
132
133
|
- lib/toys/definition/tool.rb
|
133
134
|
- lib/toys/dsl/arg.rb
|
134
135
|
- lib/toys/dsl/flag.rb
|
136
|
+
- lib/toys/dsl/flag_group.rb
|
135
137
|
- lib/toys/dsl/tool.rb
|
136
138
|
- lib/toys/errors.rb
|
137
139
|
- lib/toys/input_file.rb
|
@@ -139,6 +141,7 @@ files:
|
|
139
141
|
- lib/toys/middleware.rb
|
140
142
|
- lib/toys/mixin.rb
|
141
143
|
- lib/toys/runner.rb
|
144
|
+
- lib/toys/standard_middleware.rb
|
142
145
|
- lib/toys/standard_middleware/add_verbosity_flags.rb
|
143
146
|
- lib/toys/standard_middleware/handle_usage_errors.rb
|
144
147
|
- lib/toys/standard_middleware/set_default_descriptions.rb
|