optimist_xl 3.1.1 → 3.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/.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
|