optimist_xl 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +9 -8
- data/{History.txt → History.md} +37 -32
- data/LICENSE +25 -0
- data/README.md +23 -5
- data/examples/alt_names.rb +15 -0
- data/examples/banners1.rb +1 -1
- data/examples/banners2.rb +1 -1
- data/examples/banners3.rb +1 -1
- data/examples/permitted.rb +0 -0
- data/examples/subcommands.rb +0 -0
- data/examples/types.rb +0 -0
- data/examples/types_custom.rb +0 -0
- data/lib/optimist_xl.rb +102 -45
- data/optimist_xl.gemspec +5 -3
- data/test/optimist_xl/alt_names_test.rb +146 -0
- data/test/optimist_xl/parser_test.rb +8 -7
- data/test/optimist_xl/permitted_test.rb +5 -5
- data/test/test_helper.rb +1 -1
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f71228547d0536054a7e674aa46cedde06fc46ea310e46076f4beb19585f9f5
|
4
|
+
data.tar.gz: 948058a857b01c3939866fbb5b484131f5d104083c4ca4800c7072ce8eba8de7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8f594f3eb28c433b9b34b81ae452060d0cd2f5cb1302b6167da58358e1c2cbf3749792918ce1f96da6c02112fb9f4f30ee85c00eb38a7cfd46372387dd37446
|
7
|
+
data.tar.gz: 6fcabc7018c7660aa0fdc3c79d1d020a0a352b76fe22655c9d02bed4eb8556ec40503e6e349ba2bd968504e3cedf13ca54d4c9f8598b59f06c25121579f1b328
|
data/.travis.yml
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
language: ruby
|
2
|
-
|
2
|
+
cache: bundler
|
3
3
|
rvm:
|
4
|
-
-
|
5
|
-
-
|
6
|
-
-
|
7
|
-
-
|
8
|
-
-
|
4
|
+
- 2.2
|
5
|
+
- 2.3
|
6
|
+
- 2.4
|
7
|
+
- 2.5
|
8
|
+
- 2.6
|
9
|
+
- 2.7
|
9
10
|
- jruby-head
|
10
11
|
matrix:
|
11
12
|
allow_failures:
|
12
|
-
- rvm: jruby-head
|
13
|
-
fast_finish: true
|
13
|
+
# - rvm: jruby-head
|
14
|
+
# fast_finish: true
|
data/{History.txt → History.md}
RENAMED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
# [3.2.0] / 2020-03-02
|
2
|
+
|
3
|
+
* Added alternate-named long options using `:alt`
|
4
|
+
* Added alternate-named short-options by allowing `:short` to take an Array.
|
5
|
+
* Refactored some short/long handling code into ShortNames and LongNames classes.
|
6
|
+
# [3.1.1] / 2020-01-20
|
2
7
|
|
3
8
|
* The gem has been forked from optimist to optimist_xl
|
4
9
|
* Added "native" subcommands support
|
@@ -7,11 +12,11 @@
|
|
7
12
|
* ability to globally prevent short-options by default
|
8
13
|
* permitted and permitted_response keywords now available
|
9
14
|
|
10
|
-
|
15
|
+
# [3.0.0] / 2018-08-24
|
11
16
|
|
12
17
|
* The gem has been officially renamed to optimist
|
13
18
|
|
14
|
-
|
19
|
+
# [2.1.3] / 2018-07-05
|
15
20
|
|
16
21
|
* Refactor each option type into subclasses of Option. Define a registry for the registration of each option. This makes the code more modular and facilitates extension by allowing additional Option subclasses. (thanks @clxy)
|
17
22
|
* Fixed implementation of ignore_invalid_options. (thanks @metcalf)
|
@@ -20,18 +25,18 @@
|
|
20
25
|
* fixed default (thanks @nanobowers)
|
21
26
|
* Change from ruby license to MIT license in the code.
|
22
27
|
|
23
|
-
|
28
|
+
# [2.1.2] / 2015-03-10
|
24
29
|
* loosen mime-types requirements (for better ruby 1.8.7 support)
|
25
30
|
* use io/console gem instead of curses (for better jruby support)
|
26
31
|
* fix parsing bug when chronic gem is not available
|
27
32
|
* allow default array to be empty if a type is specified
|
28
33
|
* better specified license and better spec coverage
|
29
34
|
|
30
|
-
|
35
|
+
# [2.1.1] / 2015-01-03
|
31
36
|
* Remove curses as a hard dependency. It is optional. This can leverage the gem if it is present.
|
32
37
|
* Fix ruby -w warnings
|
33
38
|
|
34
|
-
|
39
|
+
# 2.1.0 / 2015-01-02
|
35
40
|
* Integer parser now supports underscore separator.
|
36
41
|
* Add Parser#usage and Parser#synopsis commands for creating a standard banner
|
37
42
|
message. Using Parser#banner directly will override both of those.
|
@@ -46,7 +51,7 @@
|
|
46
51
|
* Fix handling of newlines inside descriptions
|
47
52
|
* Documentation and other fixes.
|
48
53
|
|
49
|
-
|
54
|
+
# 2.0 / 2012-08-11
|
50
55
|
* Change flag logic: --no-X will always be false, and --X will always be true,
|
51
56
|
regardless of default.
|
52
57
|
* For flags that default to true, display --no-X instead of --X in the help
|
@@ -55,55 +60,55 @@
|
|
55
60
|
* Update Rakefile to 1.9
|
56
61
|
* Minor documentation fixes
|
57
62
|
|
58
|
-
|
63
|
+
# 1.16.2 / 2010-04-06
|
59
64
|
* Bugfix in Optimist::options. Thanks to Brian C. Thomas for pointing it out.
|
60
65
|
|
61
|
-
|
66
|
+
# 1.16.1 / 2010-04-05
|
62
67
|
* Bugfix in Optimist::die method introduced in last release.
|
63
68
|
|
64
|
-
|
69
|
+
# 1.16 / 2010-04-01
|
65
70
|
* Add Optimist::with_standard_exception_handling method for easing the use of Parser directly.
|
66
71
|
* Handle scientific notation in float arguments, thanks to Will Fitzgerald.
|
67
72
|
* Drop hoe dependency.
|
68
73
|
|
69
|
-
|
74
|
+
# 1.15 / 2009-09-30
|
70
75
|
* Don't raise an exception when out of short arguments (thanks to Rafael
|
71
76
|
Sevilla for pointing out how dumb this behavior was).
|
72
77
|
|
73
|
-
|
78
|
+
# 1.14 / 2009-06-19
|
74
79
|
* Make :multi arguments default to [], not nil, when not set on the commandline.
|
75
80
|
* Minor commenting and error message improvements
|
76
81
|
|
77
|
-
|
82
|
+
# 1.13 / 2009-03-16
|
78
83
|
* Fix parsing of "--longarg=<value with spaces>".
|
79
84
|
|
80
|
-
|
85
|
+
# 1.12 / 2009-01-30
|
81
86
|
* Fix some unit test failures in the last release. Should be more careful.
|
82
87
|
* Make default short options only be assigned *after* all user-specified
|
83
88
|
short options. Now there's a little less juggling to do when you just
|
84
89
|
want to specify a few short options.
|
85
90
|
|
86
|
-
|
91
|
+
# 1.11 / 2009-01-29
|
87
92
|
* Set <opt>_given keys in the results hash for options that were specified
|
88
93
|
on the commandline.
|
89
94
|
|
90
|
-
|
95
|
+
# 1.10.2 / 2008-10-23
|
91
96
|
* No longer try `stty size` for screen size detection. Just use curses, and
|
92
97
|
screen users will have to deal with the screen clearing.
|
93
98
|
|
94
|
-
|
99
|
+
# 1.10.1 / 2008-10-22
|
95
100
|
* Options hash now responds to method calls as well as standard hash lookup.
|
96
101
|
* Default values for multi-occurrence parameters now autoboxed.
|
97
102
|
* The relationship between multi-value, multi-occurrence, and default values
|
98
103
|
improved and explained.
|
99
104
|
* Documentation improvements.
|
100
105
|
|
101
|
-
|
106
|
+
# 1.10 / 2008-10-21
|
102
107
|
* Added :io type for parameters that point to IO streams (filenames, URIs, etc).
|
103
108
|
* For screen size detection, first try `stty size` before loading Curses.
|
104
109
|
* Improved documentation.
|
105
110
|
|
106
|
-
|
111
|
+
# 1.9 / 2008-08-20
|
107
112
|
* Added 'stop_on_unknown' command to stop parsing on any unknown argument.
|
108
113
|
This is useful for handling sub-commands when you don't know the entire
|
109
114
|
set of commands up front. (E.g. if the initial arguments can change it.)
|
@@ -112,51 +117,51 @@
|
|
112
117
|
* Added :ints, :strings, :doubles, and :floats option types, which can take
|
113
118
|
multiple arguments.
|
114
119
|
|
115
|
-
|
120
|
+
# 1.8.2 / 2008-06-25
|
116
121
|
* Bugfix for #conflicts and #depends error messages
|
117
122
|
|
118
|
-
|
123
|
+
# 1.8.1 / 2008-06-24
|
119
124
|
* Bugfix for short option autocreation
|
120
125
|
* More aggressive documentation
|
121
126
|
|
122
|
-
|
127
|
+
# 1.8 / 2008-06-16
|
123
128
|
* Sub-command support via Parser#stop_on
|
124
129
|
|
125
|
-
|
130
|
+
# 1.7.2 / 2008-01-16
|
126
131
|
* Ruby 1.9-ify. Apparently this means replacing :'s with ;'s.
|
127
132
|
|
128
|
-
|
133
|
+
# 1.7.1 / 2008-01-07
|
129
134
|
* Documentation improvements
|
130
135
|
|
131
|
-
|
136
|
+
# 1.7 / 2007-06-17
|
132
137
|
* Fix incorrect error message for multiple missing required arguments
|
133
138
|
(thanks to Neill Zero)
|
134
139
|
|
135
|
-
|
140
|
+
# 1.6 / 2007-04-01
|
136
141
|
* Don't attempt curses screen-width magic unless running on a terminal.
|
137
142
|
|
138
|
-
|
143
|
+
# 1.5 / 2007-03-31
|
139
144
|
* --help and --version do the right thing even if the rest of the
|
140
145
|
command line is incorrect.
|
141
146
|
* Added #conflicts and #depends to model dependencies and exclusivity
|
142
147
|
between arguments.
|
143
148
|
* Minor bugfixes.
|
144
149
|
|
145
|
-
|
150
|
+
# 1.4 / 2007-03-26
|
146
151
|
* Disable short options with :short => :none.
|
147
152
|
* Minor bugfixes and error message improvements.
|
148
153
|
|
149
|
-
|
154
|
+
# 1.3 / 2007-01-31
|
150
155
|
* Wrap at (screen width - 1) instead of screen width.
|
151
156
|
* User can override --help and --version.
|
152
157
|
* Bugfix in handling of -v and -h.
|
153
158
|
* More tests to confirm the above.
|
154
159
|
|
155
|
-
|
160
|
+
# 1.2 / 2007-01-31
|
156
161
|
* Minor documentation tweaks.
|
157
162
|
* Removed hoe dependency.
|
158
163
|
|
159
|
-
|
164
|
+
# 1.1 / 2007-01-30
|
160
165
|
* Optimist::options now passes any arguments as block arguments. Since
|
161
166
|
instance variables are not properly captured by the block, this
|
162
167
|
makes it slightly less noisy to pass them in as local variables.
|
@@ -169,7 +174,7 @@
|
|
169
174
|
in the help text.
|
170
175
|
* Slightly more indicative formatting for parameterized arguments.
|
171
176
|
|
172
|
-
|
177
|
+
# 1.0 / 2007-01-29
|
173
178
|
* Initial release.
|
174
179
|
|
175
180
|
[2.1.3]: https://github.com/ManageIQ/optimist/compare/v2.1.2...v2.1.3
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2008-2014 William Morgan (http://masanjin.net/).
|
4
|
+
|
5
|
+
Copyright (c) 2014 Red Hat, Inc.
|
6
|
+
|
7
|
+
Copyright (c) 2019 Ben Bowers
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
17
|
+
copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
25
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -17,15 +17,19 @@ One line of code per option is all you need to write. For that, you get a nice
|
|
17
17
|
automatically-generated help page, robust option parsing, and sensible defaults
|
18
18
|
for everything you don't specify.
|
19
19
|
|
20
|
+
This code is a feature-fork of Optimist: https://github.com/ManageIQ/optimist
|
21
|
+
|
22
|
+
See the **Extended Features** section below for the differences/enhancements
|
23
|
+
|
20
24
|
## Features
|
21
25
|
|
22
|
-
-
|
26
|
+
- Simple usage.
|
23
27
|
- Sensible defaults. No tweaking necessary, much tweaking possible.
|
24
28
|
- Support for long options, short options, subcommands, and automatic type validation and
|
25
29
|
conversion.
|
26
30
|
- Automatic help message generation, wrapped to current screen width.
|
27
31
|
|
28
|
-
## Extended
|
32
|
+
## Extended Features
|
29
33
|
|
30
34
|
### Parser Settings
|
31
35
|
- Automatic suggestions whens incorrect options are given
|
@@ -37,16 +41,30 @@ for everything you don't specify.
|
|
37
41
|
|
38
42
|
### Option Settings
|
39
43
|
|
44
|
+
#### Permitted
|
45
|
+
|
40
46
|
Permitted options allow specifying valid choices for an option using lists, ranges or regexp's
|
41
47
|
- `permitted:` to specify a allow lists, ranges or regexp filtering of options.
|
42
48
|
- `permitted_response:` can be added to provide more explicit output when incorrect choices are given.
|
43
49
|
- see [example](examples/permitted.rb)
|
44
50
|
- concept and code via @akhoury6
|
45
51
|
|
52
|
+
#### Alternate named options
|
53
|
+
|
54
|
+
Short options can now take be provided as an Array of list of alternate short-option characters.
|
55
|
+
- `opt :cat, 'desc', short: ['c', 't']`
|
56
|
+
- Previously `short:` only accepted a single character.
|
57
|
+
|
58
|
+
Long options can be given alternate names using `alt:`
|
59
|
+
- `opt :length, 'desc', alt: ['size']`
|
60
|
+
- Note that `long: 'othername'` still exists to _override_ the named option and can be used in addition to the alt names.
|
61
|
+
|
62
|
+
See [example](examples/alt_names.rb)
|
63
|
+
|
46
64
|
### Subcommands
|
47
|
-
"Native" subcommand support
|
48
|
-
-
|
49
|
-
-
|
65
|
+
"Native" subcommand support - similar to sub-commands in Git.
|
66
|
+
- See [example](examples/subcommands.rb)
|
67
|
+
- Ideas borrowed from https://github.com/jwliechty/trollop-subcommands
|
50
68
|
|
51
69
|
## Requirements
|
52
70
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/optimist_xl'
|
3
|
+
|
4
|
+
opts = OptimistXL::options do
|
5
|
+
# 'short:' can now take more than one short-option character
|
6
|
+
# you can specify 'short:' as a string/symbol or an array of strings/symbols
|
7
|
+
# 'alt:' adds additional long-opt choices (over the original name or the long: name)
|
8
|
+
# you can specify 'alt:' as a string/symbol or an array of strings/symbols.
|
9
|
+
#
|
10
|
+
opt :concat, 'concatenate flag', short: ['-C', 'A'], alt: ['cat', '--append']
|
11
|
+
opt :array_len, 'set Array length', long: 'size', alt: 'length', type: Integer
|
12
|
+
end
|
13
|
+
|
14
|
+
p opts
|
15
|
+
|
data/examples/banners1.rb
CHANGED
data/examples/banners2.rb
CHANGED
data/examples/banners3.rb
CHANGED
data/examples/permitted.rb
CHANGED
File without changes
|
data/examples/subcommands.rb
CHANGED
File without changes
|
data/examples/types.rb
CHANGED
File without changes
|
data/examples/types_custom.rb
CHANGED
File without changes
|
data/lib/optimist_xl.rb
CHANGED
@@ -9,7 +9,7 @@ require 'date'
|
|
9
9
|
module OptimistXL
|
10
10
|
# note: this is duplicated in gemspec
|
11
11
|
# please change over there too
|
12
|
-
VERSION = "3.
|
12
|
+
VERSION = "3.2.0"
|
13
13
|
|
14
14
|
## Thrown by Parser in the event of a commandline error. Not needed if
|
15
15
|
## you're using the OptimistXL::options entry.
|
@@ -76,8 +76,6 @@ class Parser
|
|
76
76
|
return @registry[lookup].new
|
77
77
|
end
|
78
78
|
|
79
|
-
INVALID_SHORT_ARG_REGEX = /[\d-]/ #:nodoc:
|
80
|
-
|
81
79
|
## The values from the commandline that were not interpreted by #parse.
|
82
80
|
attr_reader :leftovers
|
83
81
|
|
@@ -174,11 +172,18 @@ class Parser
|
|
174
172
|
o = Option.create(name, desc, opts)
|
175
173
|
|
176
174
|
raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? o.name
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
175
|
+
o.long.names.each do |lng|
|
176
|
+
raise ArgumentError, "long option name #{lng.inspect} is already taken; please specify a (different) :long/:alt" if @long[lng]
|
177
|
+
@long[lng] = o.name
|
178
|
+
end
|
179
|
+
|
180
|
+
raise ArgumentError, "permitted values for option #{o.long.long.inspect} must be either nil, Range, Regexp or an Array;" unless o.permitted_type_valid?
|
181
|
+
|
182
|
+
o.short.chars.each do |short|
|
183
|
+
raise ArgumentError, "short option name #{short.inspect} is already taken; please specify a (different) :short" if @short[short]
|
184
|
+
@short[short] = o.name
|
185
|
+
end
|
186
|
+
|
182
187
|
@specs[o.name] = o
|
183
188
|
@order << [:opt, o.name]
|
184
189
|
end
|
@@ -429,7 +434,7 @@ class Parser
|
|
429
434
|
end
|
430
435
|
end
|
431
436
|
|
432
|
-
required.each do |sym,
|
437
|
+
required.each do |sym, _val|
|
433
438
|
raise CommandlineError, "option --#{@specs[sym].long} must be specified" unless given_args.include? sym
|
434
439
|
end
|
435
440
|
|
@@ -586,7 +591,7 @@ class Parser
|
|
586
591
|
exit(error_code || -1)
|
587
592
|
end
|
588
593
|
|
589
|
-
private
|
594
|
+
private
|
590
595
|
|
591
596
|
## yield successive arg, parameter pairs
|
592
597
|
def each_arg(args)
|
@@ -679,11 +684,11 @@ private
|
|
679
684
|
def resolve_default_short_options!
|
680
685
|
@order.each do |type, name|
|
681
686
|
opts = @specs[name]
|
682
|
-
next if type != :opt || opts.
|
687
|
+
next if type != :opt || opts.doesnt_need_autogen_short
|
683
688
|
|
684
|
-
c = opts.long.split(//).find { |d| d !~
|
689
|
+
c = opts.long.long.split(//).find { |d| d !~ OptimistXL::ShortNames::INVALID_ARG_REGEX && !@short.member?(d) }
|
685
690
|
if c # found a character to use
|
686
|
-
opts.short
|
691
|
+
opts.short.add c
|
687
692
|
@short[c] = name
|
688
693
|
end
|
689
694
|
end
|
@@ -757,14 +762,84 @@ class SubcommandParser < Parser
|
|
757
762
|
|
758
763
|
end
|
759
764
|
|
765
|
+
class LongNames
|
766
|
+
def initialize
|
767
|
+
@truename = nil
|
768
|
+
@long = nil
|
769
|
+
@alts = []
|
770
|
+
end
|
771
|
+
|
772
|
+
def make_valid(lopt)
|
773
|
+
return nil if lopt.nil?
|
774
|
+
case lopt.to_s
|
775
|
+
when /^--([^-].*)$/ then $1
|
776
|
+
when /^[^-]/ then lopt.to_s
|
777
|
+
else raise ArgumentError, "invalid long option name #{lopt.inspect}"
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
def set(name, lopt, alts)
|
782
|
+
@truename = name
|
783
|
+
lopt = lopt ? lopt.to_s : name.to_s.gsub("_", "-")
|
784
|
+
@long = make_valid(lopt)
|
785
|
+
alts = [alts] unless alts.is_a?(Array) # box the value
|
786
|
+
@alts = alts.map { |alt| make_valid(alt) }.compact
|
787
|
+
end
|
788
|
+
|
789
|
+
# long specified with :long has precedence over the true-name
|
790
|
+
def long ; @long || @truename ; end
|
791
|
+
|
792
|
+
# all valid names, including alts
|
793
|
+
def names
|
794
|
+
[long] + @alts
|
795
|
+
end
|
796
|
+
|
797
|
+
end
|
798
|
+
|
799
|
+
class ShortNames
|
800
|
+
|
801
|
+
INVALID_ARG_REGEX = /[\d-]/ #:nodoc:
|
802
|
+
|
803
|
+
def initialize
|
804
|
+
@chars = []
|
805
|
+
@auto = true
|
806
|
+
end
|
807
|
+
|
808
|
+
attr_reader :chars, :auto
|
809
|
+
|
810
|
+
def add(values)
|
811
|
+
values = [values] unless values.is_a?(Array) # box the value
|
812
|
+
values.compact.each do |val|
|
813
|
+
if val == :none
|
814
|
+
@auto = false
|
815
|
+
raise "Cannot set short to :none if short-chars have been defined '#{@chars}'" unless chars.empty?
|
816
|
+
next
|
817
|
+
end
|
818
|
+
strval = val.to_s
|
819
|
+
sopt = case strval
|
820
|
+
when /^-(.)$/ then $1
|
821
|
+
when /^.$/ then strval
|
822
|
+
else raise ArgumentError, "invalid short option name '#{val.inspect}'"
|
823
|
+
end
|
824
|
+
|
825
|
+
if sopt =~ INVALID_ARG_REGEX
|
826
|
+
raise ArgumentError, "short option name '#{sopt}' can't be a number or a dash"
|
827
|
+
end
|
828
|
+
@chars << sopt
|
829
|
+
end
|
830
|
+
end
|
831
|
+
|
832
|
+
end
|
833
|
+
|
760
834
|
class Option
|
761
835
|
|
762
|
-
|
836
|
+
attr_reader :short
|
837
|
+
attr_accessor :name, :long, :default, :permitted, :permitted_response
|
763
838
|
attr_writer :multi_given
|
764
839
|
|
765
840
|
def initialize
|
766
|
-
@long =
|
767
|
-
@short = nil
|
841
|
+
@long = LongNames.new
|
842
|
+
@short = ShortNames.new # can be an Array of one-char strings, a one-char String, nil or :none
|
768
843
|
@name = nil
|
769
844
|
@multi_given = false
|
770
845
|
@hidden = false
|
@@ -797,7 +872,7 @@ class Option
|
|
797
872
|
|
798
873
|
def array_default? ; self.default.kind_of?(Array) ; end
|
799
874
|
|
800
|
-
def
|
875
|
+
def doesnt_need_autogen_short ; !short.auto || !short.chars.empty? ; end
|
801
876
|
|
802
877
|
def callback ; opts(:callback) ; end
|
803
878
|
def desc ; opts(:desc) ; end
|
@@ -812,7 +887,10 @@ class Option
|
|
812
887
|
def type_format ; "" ; end
|
813
888
|
|
814
889
|
def educate
|
815
|
-
|
890
|
+
optionlist = []
|
891
|
+
optionlist.concat(short.chars.map { |o| "-#{o}" })
|
892
|
+
optionlist.concat(long.names.map { |o| "--#{o}" })
|
893
|
+
optionlist.compact.join(', ') + type_format + (flag? && default ? ", --no-#{long}" : "")
|
816
894
|
end
|
817
895
|
|
818
896
|
## Format the educate-line description including the default and permitted value(s)
|
@@ -865,7 +943,7 @@ class Option
|
|
865
943
|
when Array
|
866
944
|
return "one of: " + permitted.to_a.map(&:to_s).join(', ')
|
867
945
|
when Range
|
868
|
-
return "value in range of: #{permitted
|
946
|
+
return "value in range of: #{permitted}"
|
869
947
|
when Regexp
|
870
948
|
return "value matching: #{permitted.inspect}"
|
871
949
|
end
|
@@ -916,7 +994,7 @@ class Option
|
|
916
994
|
# to +OptimistXL::opt+. This is trickier in OptimistXL, than other cmdline
|
917
995
|
# parsers (e.g. Slop) because we allow the +default:+ to be able to
|
918
996
|
# set the option's type.
|
919
|
-
def self.create(name,
|
997
|
+
def self.create(name, _desc="", opts={}, _settings={})
|
920
998
|
|
921
999
|
opttype = OptimistXL::Parser.registry_getopttype(opts[:type])
|
922
1000
|
opttype_from_default = get_klass_from_default(opts, opttype)
|
@@ -926,10 +1004,10 @@ class Option
|
|
926
1004
|
opt_inst = (opttype || opttype_from_default || OptimistXL::BooleanOption.new)
|
927
1005
|
|
928
1006
|
## fill in :long
|
929
|
-
opt_inst.long
|
1007
|
+
opt_inst.long.set(name, opts[:long], opts[:alt])
|
930
1008
|
|
931
1009
|
## fill in :short
|
932
|
-
opt_inst.short
|
1010
|
+
opt_inst.short.add opts[:short]
|
933
1011
|
|
934
1012
|
## fill in :multi
|
935
1013
|
multi_given = opts[:multi] || false
|
@@ -951,7 +1029,6 @@ class Option
|
|
951
1029
|
opt_inst
|
952
1030
|
end
|
953
1031
|
|
954
|
-
private
|
955
1032
|
|
956
1033
|
def self.get_type_from_disdef(optdef, opttype, disambiguated_default)
|
957
1034
|
if disambiguated_default.is_a? Array
|
@@ -983,28 +1060,8 @@ class Option
|
|
983
1060
|
return OptimistXL::Parser.registry_getopttype(type_from_default)
|
984
1061
|
end
|
985
1062
|
|
986
|
-
|
987
|
-
|
988
|
-
lopt = case lopt
|
989
|
-
when /^--([^-].*)$/ then $1
|
990
|
-
when /^[^-]/ then lopt
|
991
|
-
else raise ArgumentError, "invalid long option name #{lopt.inspect}"
|
992
|
-
end
|
993
|
-
end
|
994
|
-
|
995
|
-
def self.handle_short_opt(sopt)
|
996
|
-
sopt = sopt.to_s if sopt && sopt != :none
|
997
|
-
sopt = case sopt
|
998
|
-
when /^-(.)$/ then $1
|
999
|
-
when nil, :none, /^.$/ then sopt
|
1000
|
-
else raise ArgumentError, "invalid short option name '#{sopt.inspect}'"
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
if sopt
|
1004
|
-
raise ArgumentError, "a short option name can't be a number or a dash" if sopt =~ ::OptimistXL::Parser::INVALID_SHORT_ARG_REGEX
|
1005
|
-
end
|
1006
|
-
return sopt
|
1007
|
-
end
|
1063
|
+
private_class_method :get_type_from_disdef
|
1064
|
+
private_class_method :get_klass_from_default
|
1008
1065
|
|
1009
1066
|
end
|
1010
1067
|
|
data/optimist_xl.gemspec
CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.version = OptimistXL::VERSION
|
10
10
|
spec.authors = ["William Morgan", "Keenan Brock", "Jason Frey", "Ben Bowers"]
|
11
11
|
spec.email = "nanobowers@gmail.com"
|
12
|
-
spec.summary = "OptimistXL is
|
13
|
-
spec.description = "OptimistXL is
|
14
|
-
|
12
|
+
spec.summary = "OptimistXL is feature fork of the Optimist commandline option parser."
|
13
|
+
spec.description = "OptimistXL is feature filled but lightweight commandline option parser.
|
14
|
+
One line of code per option is all you typically need to write.
|
15
15
|
For that, you get a nice automatically-generated help page, robust option
|
16
16
|
parsing, command subcompletion, and sensible defaults for everything you don't
|
17
17
|
specify. This gem is an enhanced-feature fork of the Optimist gem."
|
@@ -29,6 +29,8 @@ specify. This gem is an enhanced-feature fork of the Optimist gem."
|
|
29
29
|
|
30
30
|
spec.require_paths = ["lib"]
|
31
31
|
|
32
|
+
spec.required_ruby_version = '>= 2.2'
|
33
|
+
|
32
34
|
spec.add_development_dependency "minitest", "~> 5.4.3"
|
33
35
|
spec.add_development_dependency "rake", "~> 10.0"
|
34
36
|
spec.add_development_dependency "chronic"
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module OptimistXL
|
4
|
+
|
5
|
+
class AlternateNamesTest < ::MiniTest::Test
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@p = Parser.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_help_string
|
12
|
+
err = assert_raises(OptimistXL::HelpNeeded) do
|
13
|
+
@p.parse(%w(--help))
|
14
|
+
end
|
15
|
+
sio = StringIO.new "w"
|
16
|
+
err.parser.educate sio
|
17
|
+
sio.string
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_altshort
|
21
|
+
@p.opt :catarg, "desc", :short => ["c", "-C"]
|
22
|
+
opts = @p.parse %w(-c)
|
23
|
+
assert_equal true, opts[:catarg]
|
24
|
+
opts = @p.parse %w(-C)
|
25
|
+
assert_equal true, opts[:catarg]
|
26
|
+
assert_raises(CommandlineError) { @p.parse %w(-c -C) }
|
27
|
+
assert_raises(CommandlineError) { @p.parse %w(-cC) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_altshort_with_multi
|
31
|
+
@p.opt :flag, "desc", :short => ["-c", "C", :x], :multi => true
|
32
|
+
@p.opt :num, "desc", :short => ["-n", "N"], :multi => true, type: Integer
|
33
|
+
@p.parse %w(-c)
|
34
|
+
@p.parse %w(-C -c -x)
|
35
|
+
@p.parse %w(-c -C)
|
36
|
+
@p.parse %w(-c -C -c -C)
|
37
|
+
opts = @p.parse %w(-ccCx)
|
38
|
+
assert_equal true, opts[:flag]
|
39
|
+
@p.parse %w(-c)
|
40
|
+
@p.parse %w(-N 1 -n 3)
|
41
|
+
@p.parse %w(-n 2 -N 4)
|
42
|
+
opts = @p.parse %w(-n 4 -N 3 -n 2 -N 1)
|
43
|
+
assert_equal [4, 3, 2, 1], opts[:num]
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_altlong
|
47
|
+
@p.opt "goodarg0", "desc", :alt => "zero"
|
48
|
+
@p.opt "goodarg1", "desc", :long => "newone", :alt => "one"
|
49
|
+
@p.opt "goodarg2", "desc", :alt => "--two"
|
50
|
+
@p.opt "goodarg3", "desc", :alt => ["three", "--four", :five]
|
51
|
+
|
52
|
+
[%w[--goodarg0], %w[--zero]].each do |a|
|
53
|
+
opts = @p.parse(a)
|
54
|
+
assert opts.goodarg0
|
55
|
+
end
|
56
|
+
|
57
|
+
[%w[--newone], %w[-n], %w[--one]].each do |a|
|
58
|
+
opts = @p.parse(a)
|
59
|
+
assert opts.goodarg1
|
60
|
+
end
|
61
|
+
|
62
|
+
[%w[--two]].each do |a|
|
63
|
+
opts = @p.parse(a)
|
64
|
+
assert opts.goodarg2
|
65
|
+
end
|
66
|
+
|
67
|
+
[%w[--three], %w[--four], %w[--five]].each do |a|
|
68
|
+
opts = @p.parse(a)
|
69
|
+
assert opts.goodarg3
|
70
|
+
end
|
71
|
+
|
72
|
+
[%w[--goodarg1], %w[--missing], %w[-a]].each do |a|
|
73
|
+
assert_raises(OptimistXL::CommandlineError) { @p.parse(a) }
|
74
|
+
end
|
75
|
+
|
76
|
+
["", '--', '-bad', '---threedash'].each do |altitem|
|
77
|
+
assert_raises(ArgumentError) { @p.opt "badarg", "desc", :alt => altitem }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_altshort_help
|
82
|
+
@p.opt :cat, 'cat', short: ['c','C','a','T']
|
83
|
+
outstring = get_help_string
|
84
|
+
# expect mutliple short-opts to be in the help
|
85
|
+
assert_match(/-c, -C, -a, -T, --cat/, outstring)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def test_altlong_help
|
90
|
+
@p.opt :cat, 'a cat', alt: :feline
|
91
|
+
@p.opt :dog, 'a dog', alt: ['Pooch', :canine]
|
92
|
+
@p.opt :fruit, 'a fruit', long: :fig, alt: ['peach', :pear, "--apple"], short: :none
|
93
|
+
|
94
|
+
outstring = get_help_string
|
95
|
+
|
96
|
+
assert_match(/^\s*-c, --cat, --feline/, outstring)
|
97
|
+
assert_match(/^\s*-d, --dog, --Pooch, --canine/, outstring)
|
98
|
+
|
99
|
+
# expect long-opt to shadow the actual name
|
100
|
+
assert_match(/^\s*--fig, --peach, --pear, --apple/, outstring)
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_alt_duplicates
|
105
|
+
# alt duplicates named option
|
106
|
+
assert_raises(ArgumentError) {
|
107
|
+
@p.opt :cat, 'desc', :alt => :cat
|
108
|
+
}
|
109
|
+
# alt duplicates :long
|
110
|
+
assert_raises(ArgumentError) {
|
111
|
+
@p.opt :cat, 'desc', :long => :feline, :alt => [:feline]
|
112
|
+
}
|
113
|
+
# alt duplicates itself
|
114
|
+
assert_raises(ArgumentError) {
|
115
|
+
@p.opt :abc, 'desc', :alt => [:aaa, :aaa]
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_altlong_collisions
|
120
|
+
@p.opt :fat, 'desc'
|
121
|
+
@p.opt :raton, 'desc', :long => :rat
|
122
|
+
@p.opt :bat, 'desc', :alt => [:baton, :twirl]
|
123
|
+
|
124
|
+
# :alt collision with named option
|
125
|
+
assert_raises(ArgumentError) {
|
126
|
+
@p.opt :cat, 'desc', :alt => :fat
|
127
|
+
}
|
128
|
+
|
129
|
+
# :alt collision with :long option
|
130
|
+
assert_raises(ArgumentError) {
|
131
|
+
@p.opt :cat, 'desc', :alt => :rat
|
132
|
+
}
|
133
|
+
|
134
|
+
# :named option collision with existing :alt option
|
135
|
+
assert_raises(ArgumentError) {
|
136
|
+
@p.opt :baton, 'desc'
|
137
|
+
}
|
138
|
+
|
139
|
+
# :long option collision with existing :alt option
|
140
|
+
assert_raises(ArgumentError) {
|
141
|
+
@p.opt :whirl, 'desc', :long => 'twirl'
|
142
|
+
}
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -273,10 +273,7 @@ class ParserTest < ::MiniTest::Test
|
|
273
273
|
end
|
274
274
|
|
275
275
|
def test_flag_with_no_defaults_and_no_args_act_as_switches_array
|
276
|
-
opts = nil
|
277
|
-
|
278
276
|
@p.opt :argd, "desc", :type => :strings, :default => ["default_string"]
|
279
|
-
|
280
277
|
opts = @p.parse(%w(--argd))
|
281
278
|
assert_equal ["default_string"], opts[:argd]
|
282
279
|
end
|
@@ -571,7 +568,11 @@ Options:
|
|
571
568
|
assert_raises(ArgumentError) { @p.opt :arg, "desc", :short => "-1" }
|
572
569
|
@p.opt :a1b, "desc"
|
573
570
|
@p.opt :a2b, "desc"
|
574
|
-
|
571
|
+
@p.parse []
|
572
|
+
# testing private interface to ensure default
|
573
|
+
# short options did not become numeric
|
574
|
+
assert_equal @p.specs[:a1b].short.chars.first, 'a'
|
575
|
+
assert_equal @p.specs[:a2b].short.chars.first, 'b'
|
575
576
|
end
|
576
577
|
|
577
578
|
def test_short_options_can_be_weird
|
@@ -748,7 +749,7 @@ Options:
|
|
748
749
|
|
749
750
|
def test_auto_generated_long_names_convert_underscores_to_hyphens
|
750
751
|
@p.opt :hello_there
|
751
|
-
assert_equal "hello-there", @p.specs[:hello_there].long
|
752
|
+
assert_equal "hello-there", @p.specs[:hello_there].long.long
|
752
753
|
end
|
753
754
|
|
754
755
|
def test_arguments_passed_through_block
|
@@ -1305,7 +1306,7 @@ Options:
|
|
1305
1306
|
|
1306
1307
|
def test_supports_callback_inline
|
1307
1308
|
assert_raises(RuntimeError, "good") do
|
1308
|
-
@p.opt :cb1 do |
|
1309
|
+
@p.opt :cb1 do |_vals|
|
1309
1310
|
raise "good"
|
1310
1311
|
end
|
1311
1312
|
@p.parse(%w(--cb1))
|
@@ -1314,7 +1315,7 @@ Options:
|
|
1314
1315
|
|
1315
1316
|
def test_supports_callback_param
|
1316
1317
|
assert_raises(RuntimeError, "good") do
|
1317
|
-
@p.opt :cb1, "with callback", :callback => lambda { |
|
1318
|
+
@p.opt :cb1, "with callback", :callback => lambda { |_vals| raise "good" }
|
1318
1319
|
@p.parse(%w(--cb1))
|
1319
1320
|
end
|
1320
1321
|
end
|
@@ -13,15 +13,15 @@ class PermittedTest < ::MiniTest::Test
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_permitted_invalid_value
|
16
|
-
err_regexp = /permitted values for option "bad" must be either nil, Range, Regexp or an Array/
|
17
|
-
assert_raises(ArgumentError) {
|
16
|
+
err_regexp = /permitted values for option "(bad|mad|sad)" must be either nil, Range, Regexp or an Array/
|
17
|
+
assert_raises(ArgumentError, err_regexp) {
|
18
18
|
@p.opt 'bad', 'desc', :permitted => 1
|
19
19
|
}
|
20
|
-
assert_raises(ArgumentError) {
|
21
|
-
@p.opt '
|
20
|
+
assert_raises(ArgumentError, err_regexp) {
|
21
|
+
@p.opt 'mad', 'desc', :permitted => "A"
|
22
22
|
}
|
23
23
|
assert_raises_errmatch(ArgumentError, err_regexp) {
|
24
|
-
@p.opt '
|
24
|
+
@p.opt 'sad', 'desc', :permitted => :abcd
|
25
25
|
}
|
26
26
|
end
|
27
27
|
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optimist_xl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Morgan
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-03-07 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: minitest
|
@@ -56,8 +56,8 @@ dependencies:
|
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0'
|
58
58
|
description: |-
|
59
|
-
OptimistXL is
|
60
|
-
|
59
|
+
OptimistXL is feature filled but lightweight commandline option parser.
|
60
|
+
One line of code per option is all you typically need to write.
|
61
61
|
For that, you get a nice automatically-generated help page, robust option
|
62
62
|
parsing, command subcompletion, and sensible defaults for everything you don't
|
63
63
|
specify. This gem is an enhanced-feature fork of the Optimist gem.
|
@@ -70,10 +70,12 @@ files:
|
|
70
70
|
- ".travis.yml"
|
71
71
|
- FAQ.txt
|
72
72
|
- Gemfile
|
73
|
-
- History.
|
73
|
+
- History.md
|
74
|
+
- LICENSE
|
74
75
|
- README.md
|
75
76
|
- Rakefile
|
76
77
|
- examples/a_basic_example.rb
|
78
|
+
- examples/alt_names.rb
|
77
79
|
- examples/banners1.rb
|
78
80
|
- examples/banners2.rb
|
79
81
|
- examples/banners3.rb
|
@@ -85,6 +87,7 @@ files:
|
|
85
87
|
- lib/optimist_xl.rb
|
86
88
|
- lib/optimist_xl/chronic.rb
|
87
89
|
- optimist_xl.gemspec
|
90
|
+
- test/optimist_xl/alt_names_test.rb
|
88
91
|
- test/optimist_xl/command_line_error_test.rb
|
89
92
|
- test/optimist_xl/help_needed_test.rb
|
90
93
|
- test/optimist_xl/parser_educate_test.rb
|
@@ -112,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
115
|
requirements:
|
113
116
|
- - ">="
|
114
117
|
- !ruby/object:Gem::Version
|
115
|
-
version: '
|
118
|
+
version: '2.2'
|
116
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
120
|
requirements:
|
118
121
|
- - ">="
|
@@ -123,9 +126,9 @@ rubyforge_project:
|
|
123
126
|
rubygems_version: 2.7.4
|
124
127
|
signing_key:
|
125
128
|
specification_version: 4
|
126
|
-
summary: OptimistXL is
|
127
|
-
your way.
|
129
|
+
summary: OptimistXL is feature fork of the Optimist commandline option parser.
|
128
130
|
test_files:
|
131
|
+
- test/optimist_xl/alt_names_test.rb
|
129
132
|
- test/optimist_xl/command_line_error_test.rb
|
130
133
|
- test/optimist_xl/help_needed_test.rb
|
131
134
|
- test/optimist_xl/parser_educate_test.rb
|