tty-option 0.1.0 → 0.2.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 +16 -1
- data/LICENSE.txt +1 -1
- data/README.md +10 -10
- data/lib/tty/option/aggregate_errors.rb +3 -3
- data/lib/tty/option/const.rb +17 -0
- data/lib/tty/option/conversions.rb +27 -19
- data/lib/tty/option/converter.rb +2 -2
- data/lib/tty/option/deep_dup.rb +0 -1
- data/lib/tty/option/dsl.rb +5 -5
- data/lib/tty/option/formatter.rb +5 -5
- data/lib/tty/option/param_conversion.rb +11 -9
- data/lib/tty/option/param_permitted.rb +1 -1
- data/lib/tty/option/param_validation.rb +1 -1
- data/lib/tty/option/parameter.rb +21 -14
- data/lib/tty/option/parameters.rb +15 -1
- data/lib/tty/option/parser.rb +1 -1
- data/lib/tty/option/parser/arguments.rb +1 -1
- data/lib/tty/option/parser/arity_check.rb +1 -1
- data/lib/tty/option/parser/environments.rb +2 -2
- data/lib/tty/option/parser/keywords.rb +1 -1
- data/lib/tty/option/parser/param_types.rb +16 -4
- data/lib/tty/option/parser/required_check.rb +1 -1
- data/lib/tty/option/pipeline.rb +1 -1
- data/lib/tty/option/result.rb +25 -3
- data/lib/tty/option/usage.rb +58 -1
- data/lib/tty/option/usage_wrapper.rb +3 -2
- data/lib/tty/option/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fabf2ee6efdc82e500dee823a54a90675a52dc06e90496b922396fe412c7780f
|
4
|
+
data.tar.gz: c2e00f207d86ca4adfbe84b0e8a99298720d50e754cdb77e3ab815c11d9152eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c484049a77722baae844331533373d174f35999ab621040b2be38968fd64b0d6fa14372873741e4df40d75fa15d36f7f22557d02f48f5d25de40f14ad42da400
|
7
|
+
data.tar.gz: 173e26541c883f4111a69b5f1d8287cea032bd727275ac04f62ab4da3d4925680b5dcd8ef0cf81a7cc5d73a32e67aaf71042b7dbe5c72817429155a5abc55479
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.2.0] - 2021-08-04
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add predicate methods for checking if a given parameter is supported
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
* Change Conversions to stop raising error and return Undefined value instead
|
10
|
+
* Change to skip conversion of parameters with nil value
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
* Fix conversion of nil into array or hash to stop raising an error
|
14
|
+
* Fix #no_command to correctly mark command as not present
|
15
|
+
* Fix warnings about shadowing local variables
|
16
|
+
|
3
17
|
## [v0.1.0] - 2020-05-18
|
4
18
|
|
5
19
|
* Initial implementation and release
|
6
20
|
|
7
|
-
[v0.
|
21
|
+
[v0.2.0]: https://github.com/piotrmurach/tty-option/compare/v0.1.0...v0.2.0
|
22
|
+
[v0.1.0]: https://github.com/piotrmurach/tty-option/compare/95179f0...v0.1.0
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2020 Piotr Murach
|
3
|
+
Copyright (c) 2020 Piotr Murach (piotrmurach.com)
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
<div align="center">
|
2
|
-
<a href="https://
|
2
|
+
<a href="https://ttytoolkit.org"><img width="130" src="https://github.com/piotrmurach/tty/raw/master/images/tty.png" alt="TTY Toolkit logo"/></a>
|
3
3
|
</div>
|
4
4
|
|
5
5
|
# TTY::Option
|
6
6
|
|
7
7
|
[][gem]
|
8
|
-
[][gh_actions_ci]
|
9
9
|
[][appveyor]
|
10
10
|
[][codeclimate]
|
11
11
|
[][coverage]
|
12
|
-
[][inchpages]
|
13
13
|
|
14
|
-
[gem]:
|
15
|
-
[
|
14
|
+
[gem]: https://badge.fury.io/rb/tty-option
|
15
|
+
[gh_actions_ci]: https://github.com/piotrmurach/tty-option/actions?query=workflow%3ACI
|
16
16
|
[appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-option
|
17
17
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/tty-option/maintainability
|
18
18
|
[coverage]: https://coveralls.io/github/piotrmurach/tty-option
|
19
|
-
[inchpages]:
|
19
|
+
[inchpages]: https://inch-ci.org/github/piotrmurach/tty-option
|
20
20
|
|
21
21
|
> Parser for command line arguments, keywords, options and environment variables
|
22
22
|
|
@@ -280,7 +280,7 @@ argument :foo do
|
|
280
280
|
required # a default
|
281
281
|
variable "foo(int)" # name for the usage display
|
282
282
|
arity one_or_more # how many times to occur
|
283
|
-
convert :int # values converted to
|
283
|
+
convert :int # values converted to integer
|
284
284
|
validate -> { |v| v < 14 } # validation rule
|
285
285
|
desc "Some foo desc" # description for the usage display
|
286
286
|
end
|
@@ -338,7 +338,7 @@ A more involved example to parse multiple keyword arguments requires use of help
|
|
338
338
|
keyword :foo do
|
339
339
|
required # by default keywrod is not required
|
340
340
|
arity one_or_more # how many times to occur
|
341
|
-
convert :int # values converted to
|
341
|
+
convert :int # values converted to integer
|
342
342
|
validate -> { |v| v < 14 } # validation rule
|
343
343
|
desc "Some foo desc" # description for the usage display
|
344
344
|
end
|
@@ -362,7 +362,7 @@ You can also specify for the keyword argument to accept a list type:
|
|
362
362
|
keyword :foo do
|
363
363
|
required # by default keyword is not required
|
364
364
|
arity one_or_more # how many times to occur
|
365
|
-
convert :int_list # input can be a list of
|
365
|
+
convert :int_list # input can be a list of integers
|
366
366
|
validate -> { |v| v < 14 } # validation rule
|
367
367
|
desc "Some foo desc" # description for the usage display
|
368
368
|
end
|
@@ -453,7 +453,7 @@ option :foo do
|
|
453
453
|
arity one_or_more # how many times option can occur
|
454
454
|
short "-f" # declares a short flag name
|
455
455
|
long "--foo list" # declares a long flag with a required argument
|
456
|
-
convert :int_list # input can be a list of
|
456
|
+
convert :int_list # input can be a list of integers
|
457
457
|
validate -> { |v| v < 14 } # validation rule
|
458
458
|
desc "Some foo desc" # description for the usage display
|
459
459
|
end
|
@@ -75,12 +75,12 @@ module TTY
|
|
75
75
|
output = []
|
76
76
|
space_indent = " " * indent
|
77
77
|
if messages.count == 1
|
78
|
-
|
78
|
+
msg = messages.first
|
79
79
|
label = "Error: "
|
80
80
|
output << "#{space_indent}#{label}" \
|
81
|
-
"#{wrap(
|
81
|
+
"#{wrap(msg, indent: indent + label.length, width: width)}"
|
82
82
|
else
|
83
|
-
output << space_indent
|
83
|
+
output << "#{space_indent}Errors:"
|
84
84
|
messages.each_with_index do |message, num|
|
85
85
|
entry = " #{num + 1}) "
|
86
86
|
output << "#{space_indent}#{entry}" \
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
module Option
|
5
|
+
module Const
|
6
|
+
Undefined = Object.new.tap do |obj|
|
7
|
+
def obj.to_s
|
8
|
+
"undefined"
|
9
|
+
end
|
10
|
+
|
11
|
+
def obj.inspect
|
12
|
+
"undefined".inspect
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end # Const
|
16
|
+
end # Option
|
17
|
+
end # TTY
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "const"
|
3
4
|
require_relative "converter"
|
4
5
|
|
5
6
|
module TTY
|
@@ -10,13 +11,6 @@ module TTY
|
|
10
11
|
TRUE_VALUES = /^(true|y(es)?|t|1)$/i.freeze
|
11
12
|
FALSE_VALUES = /^(false|n(o)?|f|0)$/i.freeze
|
12
13
|
|
13
|
-
# @api public
|
14
|
-
def self.raise_invalid_argument(conv_name, val)
|
15
|
-
raise ConversionError,
|
16
|
-
format("invalid value of %<value>s for %<conv>s conversion",
|
17
|
-
value: val.inspect, conv: conv_name.inspect)
|
18
|
-
end
|
19
|
-
|
20
14
|
convert :bool, :boolean do |val|
|
21
15
|
case val.to_s
|
22
16
|
when TRUE_VALUES
|
@@ -24,7 +18,7 @@ module TTY
|
|
24
18
|
when FALSE_VALUES
|
25
19
|
false
|
26
20
|
else
|
27
|
-
|
21
|
+
Const::Undefined
|
28
22
|
end
|
29
23
|
end
|
30
24
|
|
@@ -33,7 +27,7 @@ module TTY
|
|
33
27
|
require "date" unless defined?(::Date)
|
34
28
|
::Date.parse(val)
|
35
29
|
rescue ArgumentError, TypeError
|
36
|
-
|
30
|
+
Const::Undefined
|
37
31
|
end
|
38
32
|
end
|
39
33
|
|
@@ -41,7 +35,7 @@ module TTY
|
|
41
35
|
begin
|
42
36
|
Float(val)
|
43
37
|
rescue ArgumentError, TypeError
|
44
|
-
|
38
|
+
Const::Undefined
|
45
39
|
end
|
46
40
|
end
|
47
41
|
|
@@ -49,7 +43,7 @@ module TTY
|
|
49
43
|
begin
|
50
44
|
Float(val).to_i
|
51
45
|
rescue ArgumentError, TypeError
|
52
|
-
|
46
|
+
Const::Undefined
|
53
47
|
end
|
54
48
|
end
|
55
49
|
|
@@ -62,7 +56,7 @@ module TTY
|
|
62
56
|
begin
|
63
57
|
Regexp.new(val.to_s)
|
64
58
|
rescue TypeError, RegexpError
|
65
|
-
|
59
|
+
Const::Undefined
|
66
60
|
end
|
67
61
|
end
|
68
62
|
|
@@ -70,7 +64,7 @@ module TTY
|
|
70
64
|
begin
|
71
65
|
String(val).to_sym
|
72
66
|
rescue ArgumentError
|
73
|
-
|
67
|
+
Const::Undefined
|
74
68
|
end
|
75
69
|
end
|
76
70
|
|
@@ -79,18 +73,22 @@ module TTY
|
|
79
73
|
require "uri"
|
80
74
|
::URI.parse(val)
|
81
75
|
rescue ::URI::InvalidURIError
|
82
|
-
|
76
|
+
Const::Undefined
|
83
77
|
end
|
84
78
|
end
|
85
79
|
|
86
80
|
convert :list, :array do |val|
|
87
|
-
|
81
|
+
next Const::Undefined if val.nil?
|
82
|
+
|
83
|
+
(val.respond_to?(:map) ? val : val.to_s.split(/(?<!\\),/))
|
88
84
|
.map { |v| v.strip.gsub(/\\,/, ",") }
|
89
85
|
.reject(&:empty?)
|
90
86
|
end
|
91
87
|
|
92
88
|
convert :map, :hash do |val|
|
93
|
-
|
89
|
+
next Const::Undefined if val.nil?
|
90
|
+
|
91
|
+
values = val.respond_to?(:each) ? val : val.to_s.split(/[& ]/)
|
94
92
|
values.each_with_object({}) do |pair, pairs|
|
95
93
|
key, value = pair.split(/[=:]/, 2)
|
96
94
|
if (current = pairs[key.to_sym])
|
@@ -107,16 +105,26 @@ module TTY
|
|
107
105
|
|
108
106
|
[:"#{type}_list", :"#{type}_array", :"#{type}s"].each do |new_type|
|
109
107
|
convert new_type do |val|
|
110
|
-
conversions[:list].(val)
|
111
|
-
|
108
|
+
list_conversion = conversions[:list].(val)
|
109
|
+
next list_conversion if list_conversion == Const::Undefined
|
110
|
+
|
111
|
+
list_conversion.map do |obj|
|
112
|
+
converted = conversions[type].(obj)
|
113
|
+
break converted if converted == Const::Undefined
|
114
|
+
converted
|
112
115
|
end
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
116
119
|
[:"#{type}_map", :"#{type}_hash"].each do |new_type|
|
117
120
|
convert new_type do |val|
|
121
|
+
map_conversion = conversions[:map].(val)
|
122
|
+
next map_conversion if map_conversion == Const::Undefined
|
123
|
+
|
118
124
|
conversions[:map].(val).each_with_object({}) do |(k, v), h|
|
119
|
-
|
125
|
+
converted = conversions[type].(v)
|
126
|
+
break converted if converted == Const::Undefined
|
127
|
+
h[k] = converted
|
120
128
|
end
|
121
129
|
end
|
122
130
|
end
|
data/lib/tty/option/converter.rb
CHANGED
@@ -32,7 +32,7 @@ module TTY
|
|
32
32
|
names.each do |name|
|
33
33
|
if contain?(name)
|
34
34
|
raise ConversionAlreadyDefined,
|
35
|
-
|
35
|
+
"conversion #{name.inspect} is already defined"
|
36
36
|
end
|
37
37
|
conversions[name] = block
|
38
38
|
end
|
@@ -56,7 +56,7 @@ module TTY
|
|
56
56
|
# @api public
|
57
57
|
def raise_unsupported_error(conv_name)
|
58
58
|
raise UnsupportedConversion,
|
59
|
-
|
59
|
+
"unsupported conversion type #{conv_name.inspect}"
|
60
60
|
end
|
61
61
|
end # Converter
|
62
62
|
end # Option
|
data/lib/tty/option/deep_dup.rb
CHANGED
data/lib/tty/option/dsl.rb
CHANGED
@@ -28,10 +28,10 @@ module TTY
|
|
28
28
|
# @api public
|
29
29
|
def usage(**properties, &block)
|
30
30
|
@usage ||= Usage.create(**properties, &block).tap do |usage|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
unless usage.command? || usage.no_command?
|
32
|
+
usage.command(dasherize(demodulize(self.name)))
|
33
|
+
end
|
34
|
+
end
|
35
35
|
end
|
36
36
|
|
37
37
|
# Specify an argument
|
@@ -69,7 +69,7 @@ module TTY
|
|
69
69
|
#
|
70
70
|
# @api public
|
71
71
|
def flag(name, **settings, &block)
|
72
|
-
defaults = {
|
72
|
+
defaults = {default: false}
|
73
73
|
option(name, **defaults.merge(settings), &block)
|
74
74
|
end
|
75
75
|
|
data/lib/tty/option/formatter.rb
CHANGED
@@ -53,10 +53,12 @@ module TTY
|
|
53
53
|
|
54
54
|
# A formatted help usage information
|
55
55
|
#
|
56
|
+
# @yieldparam [TTY::Option::Sections] sections
|
57
|
+
#
|
56
58
|
# @return [String]
|
57
59
|
#
|
58
60
|
# @api public
|
59
|
-
def help
|
61
|
+
def help
|
60
62
|
sections = Sections.new
|
61
63
|
|
62
64
|
sections.add(:header, help_header) if @usage.header?
|
@@ -82,9 +84,7 @@ module TTY
|
|
82
84
|
sections.add(:examples, help_examples) if @usage.example?
|
83
85
|
sections.add(:footer, help_footer) if @usage.footer?
|
84
86
|
|
85
|
-
if block_given?
|
86
|
-
yield(sections)
|
87
|
-
end
|
87
|
+
yield(sections) if block_given?
|
88
88
|
|
89
89
|
formatted = sections.reject(&:empty?).join(NEWLINE)
|
90
90
|
formatted.end_with?(NEWLINE) ? formatted : formatted + NEWLINE
|
@@ -182,7 +182,7 @@ module TTY
|
|
182
182
|
args << "[" if param.optional?
|
183
183
|
args << param_name
|
184
184
|
(param.arity - 1).times { args << " #{param_name}" }
|
185
|
-
args
|
185
|
+
args << "]" if param.optional?
|
186
186
|
args.join
|
187
187
|
else
|
188
188
|
(param.arity.abs - 1).times { args << param_name }
|
@@ -10,24 +10,26 @@ module TTY
|
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# param = Parameter::Argument.create(:foo, convert: :int)
|
13
|
-
# ParamConversion[param, "12"]
|
13
|
+
# result = ParamConversion[param, "12"]
|
14
|
+
# result.value # => 12
|
14
15
|
#
|
15
16
|
# @api public
|
16
17
|
def call(param, value)
|
17
|
-
return Result.success(value)
|
18
|
+
return Result.success(value) if !param.convert? || value.nil?
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
cast = param.convert
|
21
|
+
cast = cast.is_a?(Proc) ? cast : Conversions[cast]
|
22
|
+
converted = cast.(value)
|
23
|
+
|
24
|
+
if converted == Const::Undefined
|
25
|
+
Result.failure(InvalidConversionArgument.new(param, value))
|
22
26
|
else
|
23
|
-
Result.success(
|
27
|
+
Result.success(converted)
|
24
28
|
end
|
25
|
-
rescue ConversionError
|
26
|
-
Result.failure(InvalidConversionArgument.new(param, value))
|
27
29
|
end
|
28
30
|
module_function :call
|
29
31
|
|
30
|
-
alias
|
32
|
+
alias [] call
|
31
33
|
module_function :[]
|
32
34
|
end # ParamConversion
|
33
35
|
end # Option
|
data/lib/tty/option/parameter.rb
CHANGED
@@ -11,6 +11,12 @@ module TTY
|
|
11
11
|
include DSL::Arity
|
12
12
|
include DSL::Conversion
|
13
13
|
|
14
|
+
# Zero or more parameter arity pattern
|
15
|
+
ZERO_OR_MORE_ARITY = /\*|any/.freeze
|
16
|
+
|
17
|
+
# One or more parameter arity pattern
|
18
|
+
ONE_OR_MORE_ARITY = /\+/.freeze
|
19
|
+
|
14
20
|
# A parameter factory
|
15
21
|
#
|
16
22
|
# @api public
|
@@ -32,20 +38,20 @@ module TTY
|
|
32
38
|
def initialize(key, **settings, &block)
|
33
39
|
@key = key
|
34
40
|
@settings = {}
|
35
|
-
settings.each do |
|
36
|
-
case
|
41
|
+
settings.each do |name, val|
|
42
|
+
case name.to_sym
|
37
43
|
when :arity
|
38
44
|
val = check_arity(val)
|
39
45
|
when :default
|
40
46
|
val = check_default(val)
|
41
47
|
when :optional
|
42
|
-
|
48
|
+
name, val = :required, check_required(!val)
|
43
49
|
when :permit
|
44
50
|
val = check_permitted(val)
|
45
51
|
when :validate
|
46
52
|
val = check_validation(val)
|
47
53
|
end
|
48
|
-
@settings[
|
54
|
+
@settings[name.to_sym] = val
|
49
55
|
end
|
50
56
|
|
51
57
|
instance_eval(&block) if block_given?
|
@@ -136,7 +142,7 @@ module TTY
|
|
136
142
|
end
|
137
143
|
|
138
144
|
def required?
|
139
|
-
@settings.fetch(:required
|
145
|
+
@settings.fetch(:required, false)
|
140
146
|
end
|
141
147
|
|
142
148
|
def hidden
|
@@ -144,7 +150,7 @@ module TTY
|
|
144
150
|
end
|
145
151
|
|
146
152
|
def hidden?
|
147
|
-
@settings.fetch(:hidden
|
153
|
+
@settings.fetch(:hidden, false)
|
148
154
|
end
|
149
155
|
|
150
156
|
def display?
|
@@ -203,6 +209,7 @@ module TTY
|
|
203
209
|
# @api public
|
204
210
|
def ==(other)
|
205
211
|
return false unless instance_of?(other.class)
|
212
|
+
|
206
213
|
name == other.name && to_h == other.to_h
|
207
214
|
end
|
208
215
|
|
@@ -211,6 +218,7 @@ module TTY
|
|
211
218
|
# @api public
|
212
219
|
def eql?(other)
|
213
220
|
return false unless instance_of?(other.class)
|
221
|
+
|
214
222
|
name.eql?(other.name) && to_h.eql?(other.to_h)
|
215
223
|
end
|
216
224
|
|
@@ -250,15 +258,14 @@ module TTY
|
|
250
258
|
end
|
251
259
|
|
252
260
|
case value.to_s
|
253
|
-
when
|
254
|
-
when
|
255
|
-
else value
|
256
|
-
end
|
257
|
-
|
258
|
-
|
259
|
-
|
261
|
+
when ZERO_OR_MORE_ARITY then -1
|
262
|
+
when ONE_OR_MORE_ARITY then -2
|
263
|
+
else value.to_i
|
264
|
+
end.tap do |val|
|
265
|
+
if val.zero?
|
266
|
+
raise ConfigurationError, "#{to_sym} '#{name}' arity cannot be zero"
|
267
|
+
end
|
260
268
|
end
|
261
|
-
value
|
262
269
|
end
|
263
270
|
|
264
271
|
# @api private
|
@@ -13,7 +13,16 @@ module TTY
|
|
13
13
|
# @api private
|
14
14
|
def self.define_query(name)
|
15
15
|
define_method(:"#{name}?") do
|
16
|
-
!
|
16
|
+
!public_send(name).empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Define a predicate method to check if a parameter is supported
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
def self.define_param_query(name)
|
24
|
+
define_method(:"#{name}?") do |param|
|
25
|
+
public_send(:"#{name}s").map(&:key).include?(param)
|
17
26
|
end
|
18
27
|
end
|
19
28
|
|
@@ -37,6 +46,11 @@ module TTY
|
|
37
46
|
define_query :options
|
38
47
|
define_query :environments
|
39
48
|
|
49
|
+
define_param_query :argument
|
50
|
+
define_param_query :keyword
|
51
|
+
define_param_query :option
|
52
|
+
define_param_query :environment
|
53
|
+
|
40
54
|
# A parameters list
|
41
55
|
#
|
42
56
|
# @api private
|
data/lib/tty/option/parser.rb
CHANGED
@@ -150,10 +150,10 @@ module TTY
|
|
150
150
|
if allowed
|
151
151
|
case value
|
152
152
|
when Hash
|
153
|
-
(@parsed[env_arg.key] ||=
|
153
|
+
(@parsed[env_arg.key] ||= {}).merge!(value)
|
154
154
|
else
|
155
155
|
Array(value).each do |v|
|
156
|
-
(@parsed[env_arg.key] ||=
|
156
|
+
(@parsed[env_arg.key] ||= []) << v
|
157
157
|
end
|
158
158
|
end
|
159
159
|
else
|
@@ -4,6 +4,18 @@ module TTY
|
|
4
4
|
module Option
|
5
5
|
class Parser
|
6
6
|
module ParamTypes
|
7
|
+
# Positional argument pattern
|
8
|
+
ARGUMENT_PARAMETER = /^[^-][^=]*\z/.freeze
|
9
|
+
|
10
|
+
# Environment variable pattern
|
11
|
+
ENV_VAR_PARAMETER = /^[\p{Lu}_\-\d]+=/.freeze
|
12
|
+
|
13
|
+
# Keyword pattern
|
14
|
+
KEYWORD_PARAMETER = /^([^-=][\p{Ll}_\-\d]*)=([^=]+)/.freeze
|
15
|
+
|
16
|
+
# Option and flag pattern
|
17
|
+
OPTION_PARAMETER = /^-./.freeze
|
18
|
+
|
7
19
|
# Check if value looks like an argument
|
8
20
|
#
|
9
21
|
# @param [String] value
|
@@ -12,7 +24,7 @@ module TTY
|
|
12
24
|
#
|
13
25
|
# @api public
|
14
26
|
def argument?(value)
|
15
|
-
!value.match(
|
27
|
+
!value.match(ARGUMENT_PARAMETER).nil?
|
16
28
|
end
|
17
29
|
|
18
30
|
# Check if value is an environment variable
|
@@ -23,7 +35,7 @@ module TTY
|
|
23
35
|
#
|
24
36
|
# @api public
|
25
37
|
def env_var?(value)
|
26
|
-
!value.match(
|
38
|
+
!value.match(ENV_VAR_PARAMETER).nil?
|
27
39
|
end
|
28
40
|
|
29
41
|
# Check to see if value is a keyword
|
@@ -32,7 +44,7 @@ module TTY
|
|
32
44
|
#
|
33
45
|
# @api public
|
34
46
|
def keyword?(value)
|
35
|
-
!value.to_s.match(
|
47
|
+
!value.to_s.match(KEYWORD_PARAMETER).nil?
|
36
48
|
end
|
37
49
|
|
38
50
|
# Check if value looks like an option
|
@@ -43,7 +55,7 @@ module TTY
|
|
43
55
|
#
|
44
56
|
# @api public
|
45
57
|
def option?(value)
|
46
|
-
!value.match(
|
58
|
+
!value.match(OPTION_PARAMETER).nil?
|
47
59
|
end
|
48
60
|
end # ParamTypes
|
49
61
|
end # Parser
|
data/lib/tty/option/pipeline.rb
CHANGED
data/lib/tty/option/result.rb
CHANGED
@@ -18,29 +18,51 @@ module TTY
|
|
18
18
|
Failure.new(value)
|
19
19
|
end
|
20
20
|
|
21
|
+
# Wrapped value
|
22
|
+
#
|
23
|
+
# @api public
|
21
24
|
attr_reader :value
|
22
25
|
|
26
|
+
# Reason for failure
|
27
|
+
#
|
28
|
+
# @api public
|
23
29
|
attr_reader :error
|
24
30
|
|
31
|
+
# Check whether or not a result is a success monad
|
32
|
+
#
|
33
|
+
# @return [Boolean]
|
34
|
+
#
|
35
|
+
# @api public
|
25
36
|
def success?
|
26
37
|
is_a?(Success)
|
27
38
|
end
|
28
39
|
|
40
|
+
# Check whether or not a result is a failure class
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
#
|
44
|
+
# @api public
|
29
45
|
def failure?
|
30
46
|
is_a?(Failure)
|
31
47
|
end
|
32
48
|
|
49
|
+
# Success monad containing a value
|
50
|
+
#
|
51
|
+
# @api private
|
33
52
|
class Success < Result
|
34
53
|
def initialize(value)
|
35
54
|
@value = value
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
58
|
+
# Failure monad containing an error
|
59
|
+
#
|
60
|
+
# @api private
|
39
61
|
class Failure < Result
|
40
62
|
def initialize(error)
|
41
63
|
@error = error
|
42
64
|
end
|
43
65
|
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
66
|
+
end # Result
|
67
|
+
end # Option
|
68
|
+
end # TTY
|
data/lib/tty/option/usage.rb
CHANGED
@@ -17,8 +17,11 @@ module TTY
|
|
17
17
|
# @api public
|
18
18
|
def initialize(**properties, &block)
|
19
19
|
@properties = {}
|
20
|
+
@no_command = false
|
20
21
|
properties.each do |key, val|
|
21
22
|
case key.to_sym
|
23
|
+
when :command
|
24
|
+
key, val = :command, Array(val)
|
22
25
|
when :desc, :description
|
23
26
|
key, val = :desc, [Array(val)]
|
24
27
|
when :header, :footer
|
@@ -34,8 +37,10 @@ module TTY
|
|
34
37
|
|
35
38
|
# Program name for display in help and error messages
|
36
39
|
#
|
40
|
+
# @param [String] name
|
41
|
+
#
|
37
42
|
# @api public
|
38
|
-
def program(name = (not_set = true)
|
43
|
+
def program(name = (not_set = true))
|
39
44
|
if not_set
|
40
45
|
@properties.fetch(:program) { ::File.basename($0, ".*") }
|
41
46
|
else
|
@@ -45,6 +50,8 @@ module TTY
|
|
45
50
|
|
46
51
|
# Action name for display in help and error messages
|
47
52
|
#
|
53
|
+
# @param [Array<String>] values
|
54
|
+
#
|
48
55
|
# @api public
|
49
56
|
def command(*values)
|
50
57
|
if values.empty?
|
@@ -60,15 +67,32 @@ module TTY
|
|
60
67
|
#
|
61
68
|
# @api public
|
62
69
|
def no_command
|
70
|
+
@no_command = true
|
63
71
|
@properties[:command] = []
|
64
72
|
end
|
65
73
|
|
74
|
+
# Whether or not to show command in usage
|
75
|
+
#
|
76
|
+
# @retrun [Boolean]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
def no_command?
|
80
|
+
@no_command
|
81
|
+
end
|
82
|
+
|
83
|
+
# Check for command definition
|
84
|
+
#
|
85
|
+
# @return [Boolean]
|
86
|
+
#
|
87
|
+
# @api public
|
66
88
|
def command?
|
67
89
|
@properties.key?(:command) && !@properties[:command].empty?
|
68
90
|
end
|
69
91
|
|
70
92
|
# Display info before anything else in the usage help
|
71
93
|
#
|
94
|
+
# @param [Array<String>] values
|
95
|
+
#
|
72
96
|
# @api public
|
73
97
|
def header(*values)
|
74
98
|
if values.empty?
|
@@ -78,12 +102,19 @@ module TTY
|
|
78
102
|
end
|
79
103
|
end
|
80
104
|
|
105
|
+
# Whether or not to show header in usage
|
106
|
+
#
|
107
|
+
# @return [Boolean]
|
108
|
+
#
|
109
|
+
# @api public
|
81
110
|
def header?
|
82
111
|
@properties.key?(:header) && !@properties[:header].empty?
|
83
112
|
end
|
84
113
|
|
85
114
|
# Main way to show how all parameters can be used
|
86
115
|
#
|
116
|
+
# @param [String] value
|
117
|
+
#
|
87
118
|
# @api public
|
88
119
|
def banner(value = (not_set = true))
|
89
120
|
if not_set
|
@@ -93,12 +124,19 @@ module TTY
|
|
93
124
|
end
|
94
125
|
end
|
95
126
|
|
127
|
+
# Whether or not to show banner in usage
|
128
|
+
#
|
129
|
+
# @return [Boolean]
|
130
|
+
#
|
131
|
+
# @api public
|
96
132
|
def banner?
|
97
133
|
@properties.key?(:banner) && !@properties[:banner].nil?
|
98
134
|
end
|
99
135
|
|
100
136
|
# Description
|
101
137
|
#
|
138
|
+
# @param [Array<String>] values
|
139
|
+
#
|
102
140
|
# @api public
|
103
141
|
def desc(*values)
|
104
142
|
if values.empty?
|
@@ -109,6 +147,11 @@ module TTY
|
|
109
147
|
end
|
110
148
|
alias description desc
|
111
149
|
|
150
|
+
# Whether or not to show description in usage
|
151
|
+
#
|
152
|
+
# @return [Boolean]
|
153
|
+
#
|
154
|
+
# @api public
|
112
155
|
def desc?
|
113
156
|
@properties.key?(:desc) && !@properties[:desc].empty?
|
114
157
|
end
|
@@ -116,6 +159,8 @@ module TTY
|
|
116
159
|
|
117
160
|
# Collects usage examples
|
118
161
|
#
|
162
|
+
# @param [Array<String>] values
|
163
|
+
#
|
119
164
|
# @api public
|
120
165
|
def example(*values)
|
121
166
|
if values.empty?
|
@@ -126,6 +171,11 @@ module TTY
|
|
126
171
|
end
|
127
172
|
alias examples example
|
128
173
|
|
174
|
+
# Whether or not to show example in usage
|
175
|
+
#
|
176
|
+
# @return [Boolean]
|
177
|
+
#
|
178
|
+
# @api public
|
129
179
|
def example?
|
130
180
|
@properties.key?(:example) && !@properties[:example].empty?
|
131
181
|
end
|
@@ -133,6 +183,8 @@ module TTY
|
|
133
183
|
|
134
184
|
# Display info after everyting else in the usage help
|
135
185
|
#
|
186
|
+
# @param [Array<String>] values
|
187
|
+
#
|
136
188
|
# @api public
|
137
189
|
def footer(*values)
|
138
190
|
if values.empty?
|
@@ -142,6 +194,11 @@ module TTY
|
|
142
194
|
end
|
143
195
|
end
|
144
196
|
|
197
|
+
# Whether or not to show footer in usage
|
198
|
+
#
|
199
|
+
# @return [Boolean]
|
200
|
+
#
|
201
|
+
# @api public
|
145
202
|
def footer?
|
146
203
|
@properties.key?(:footer) && !@properties[:footer].empty?
|
147
204
|
end
|
@@ -14,13 +14,14 @@ module TTY
|
|
14
14
|
def wrap(text, width: 80, indent: 2, indent_first: false)
|
15
15
|
wrap = width - indent
|
16
16
|
lines = []
|
17
|
+
indentation = " " * indent
|
17
18
|
|
18
19
|
line, rest = *next_line(text, wrap: wrap)
|
19
|
-
lines << (indent_first ?
|
20
|
+
lines << (indent_first ? indentation : "") + line
|
20
21
|
|
21
22
|
while !rest.nil?
|
22
23
|
line, rest = *next_line(rest, wrap: wrap)
|
23
|
-
lines <<
|
24
|
+
lines << indentation + line.strip
|
24
25
|
end
|
25
26
|
|
26
27
|
lines.join("\n")
|
data/lib/tty/option/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty-option
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- lib/tty-option.rb
|
56
56
|
- lib/tty/option.rb
|
57
57
|
- lib/tty/option/aggregate_errors.rb
|
58
|
+
- lib/tty/option/const.rb
|
58
59
|
- lib/tty/option/conversions.rb
|
59
60
|
- lib/tty/option/converter.rb
|
60
61
|
- lib/tty/option/deep_dup.rb
|
@@ -100,7 +101,7 @@ metadata:
|
|
100
101
|
documentation_uri: https://www.rubydoc.info/gems/tty-option
|
101
102
|
homepage_uri: https://ttytoolkit.org
|
102
103
|
source_code_uri: https://github.com/piotrmurach/tty-option
|
103
|
-
post_install_message:
|
104
|
+
post_install_message:
|
104
105
|
rdoc_options: []
|
105
106
|
require_paths:
|
106
107
|
- lib
|
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
117
|
version: '0'
|
117
118
|
requirements: []
|
118
119
|
rubygems_version: 3.1.2
|
119
|
-
signing_key:
|
120
|
+
signing_key:
|
120
121
|
specification_version: 4
|
121
|
-
summary: An intuitive and flexible command line parser
|
122
|
+
summary: An intuitive and flexible command line parser.
|
122
123
|
test_files: []
|