opt_parse_builder 0.1.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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +35 -0
- data/LICENSE +23 -0
- data/README.md +434 -0
- data/Rakefile +13 -0
- data/examples/hello_world.rb +20 -0
- data/lib/opt_parse_builder.rb +156 -0
- data/lib/opt_parse_builder/argument.rb +62 -0
- data/lib/opt_parse_builder/argument_builder.rb +193 -0
- data/lib/opt_parse_builder/argument_bundle.rb +30 -0
- data/lib/opt_parse_builder/argument_bundle_builder.rb +34 -0
- data/lib/opt_parse_builder/argument_values.rb +60 -0
- data/lib/opt_parse_builder/banner_argument.rb +11 -0
- data/lib/opt_parse_builder/constant_argument.rb +16 -0
- data/lib/opt_parse_builder/errors.rb +10 -0
- data/lib/opt_parse_builder/formats_operand_name.rb +9 -0
- data/lib/opt_parse_builder/has_value.rb +21 -0
- data/lib/opt_parse_builder/null_argument.rb +4 -0
- data/lib/opt_parse_builder/option_argument.rb +33 -0
- data/lib/opt_parse_builder/optional_operand_argument.rb +29 -0
- data/lib/opt_parse_builder/parser.rb +345 -0
- data/lib/opt_parse_builder/parser_builder.rb +17 -0
- data/lib/opt_parse_builder/required_operand_argument.rb +32 -0
- data/lib/opt_parse_builder/separator_argument.rb +11 -0
- data/lib/opt_parse_builder/splat_operand_argument.rb +22 -0
- data/lib/opt_parse_builder/stable_sort.rb +13 -0
- data/lib/opt_parse_builder/version.rb +6 -0
- data/opt_parse_builder.gemspec +35 -0
- data/rake/bundler.rake +1 -0
- data/rake/default.rake +1 -0
- data/rake/rdoc.rake +7 -0
- data/rake/spec.rake +3 -0
- data/rake/test.rake +2 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 28f64f160f1a3940a3884f5f56ecba366ba6078be1c3032b625f0cded4124259
|
4
|
+
data.tar.gz: d81a3b030a5e8b60b97577148c5e91810c7a9125e0f08c6ad01e68f76a0d58ff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d48ea90e1d556a24a649124d33ca1329c743384066da239472c240aec47b9b113785a9e321365b2fac1b4f90ef08e9a370664693c330b326e0a510f666d650d4
|
7
|
+
data.tar.gz: 68ccc121fe7a7703f16d2bac471a69abcf0af241a7c85aef53554de9c1609bb464e2a8a5eba3ad1fd39a382d91d5f433cab554e55be6a072347ed96d24fb2f27
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.7.2
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
opt_parse_builder (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.4.4)
|
10
|
+
rake (13.0.1)
|
11
|
+
rspec (3.10.0)
|
12
|
+
rspec-core (~> 3.10.0)
|
13
|
+
rspec-expectations (~> 3.10.0)
|
14
|
+
rspec-mocks (~> 3.10.0)
|
15
|
+
rspec-core (3.10.0)
|
16
|
+
rspec-support (~> 3.10.0)
|
17
|
+
rspec-expectations (3.10.0)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.10.0)
|
20
|
+
rspec-mocks (3.10.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.10.0)
|
23
|
+
rspec-support (3.10.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
bundler (~> 2.1)
|
30
|
+
opt_parse_builder!
|
31
|
+
rake (~> 13.0)
|
32
|
+
rspec (~> 3.10)
|
33
|
+
|
34
|
+
BUNDLED WITH
|
35
|
+
2.1.4
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright 2020 Wayne Conrad
|
2
|
+
|
3
|
+
This software is distributed under the [MIT
|
4
|
+
License](http://opensource.org/licenses/MIT):
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,434 @@
|
|
1
|
+
# opt_parse_builder
|
2
|
+
|
3
|
+
A Ruby Gem for processing CLI arguments using optparse. Adds to
|
4
|
+
optparse a compact builder-style DSL, operand (positional argument)
|
5
|
+
parsing, and composability for sharing argument definitions within a
|
6
|
+
suite of commands.
|
7
|
+
|
8
|
+
Features:
|
9
|
+
|
10
|
+
* A compact, simple [builder style DSL](#label-Terminology)
|
11
|
+
|
12
|
+
* Composability - Arguments can be [defined separately from their
|
13
|
+
use](#label-Composability), allowing common arguments to be shared
|
14
|
+
shared within a suite of programs.
|
15
|
+
|
16
|
+
* Operand parsing - Adds [parsing of
|
17
|
+
operands](#label-Required+Operand)) (aka positional arguments)
|
18
|
+
|
19
|
+
* Builds on solid ground - Uses tried and true OptParse.
|
20
|
+
|
21
|
+
* Familiarity - Arguments to OptParse#on are passed through with very
|
22
|
+
little change, so you don't have to learn a new syntax for defining
|
23
|
+
options.
|
24
|
+
|
25
|
+
* Not a framework - This library provides _only_ improved argument
|
26
|
+
parsing. There is no base class for your program to inherit from,
|
27
|
+
no module for it to include, and no imposed structure.
|
28
|
+
|
29
|
+
* No magic, no surprises - Plain and explicit.
|
30
|
+
|
31
|
+
* Cohesion - Everything about an argument is defined in one place.
|
32
|
+
You don't have to define the argument's help text in one place, the
|
33
|
+
default value in another, etc.
|
34
|
+
|
35
|
+
* Narrow API - Simple and easy to use.
|
36
|
+
|
37
|
+
* Fully documented - Includes full code documentation and examples.
|
38
|
+
|
39
|
+
* Stable API - Uses [semantic
|
40
|
+
versioning](ttps://semver.org/spec/v2.0.0.html). Promises not to
|
41
|
+
break your program without incrementing the major version number.
|
42
|
+
|
43
|
+
* Programmed simply - Easy to understand and modify.
|
44
|
+
|
45
|
+
* Fully tested - Extensive unit test suite.
|
46
|
+
|
47
|
+
# Hello, World
|
48
|
+
|
49
|
+
It is valuable to provide a simple example which can be modified and
|
50
|
+
expanded upon:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require "opt_parse_builder"
|
54
|
+
|
55
|
+
arg_parser = OptParseBuilder.build_parser do |args|
|
56
|
+
args.banner "A simple example"
|
57
|
+
args.add do |arg|
|
58
|
+
arg.key :path
|
59
|
+
arg.required_operand
|
60
|
+
end
|
61
|
+
args.add do |arg|
|
62
|
+
arg.key :verbose
|
63
|
+
arg.on "-v", "--verbose", "Be verbose"
|
64
|
+
end
|
65
|
+
args.separator "Some explanatory text at the bottom"
|
66
|
+
end
|
67
|
+
|
68
|
+
arg_values = arg_parser.parse!
|
69
|
+
p arg_values.verbose
|
70
|
+
p arg_values.path
|
71
|
+
```
|
72
|
+
|
73
|
+
# Installation
|
74
|
+
|
75
|
+
Add this line to your application's Gemfile:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
gem 'opt_parse_builder'
|
79
|
+
```
|
80
|
+
|
81
|
+
And then execute:
|
82
|
+
|
83
|
+
$ bundle
|
84
|
+
|
85
|
+
Or install it yourself as:
|
86
|
+
|
87
|
+
$ gem install opt_parse_builder
|
88
|
+
|
89
|
+
# Explanation of some features
|
90
|
+
|
91
|
+
## Builder style DSL
|
92
|
+
|
93
|
+
You build an argument parser using a builder style DSL, like this:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
arg_parser = OptParseBuilder.build_parser do |args|
|
97
|
+
args.add do |arg|
|
98
|
+
arg.key :verbose
|
99
|
+
arg.on "-v", "--verbose", "Be verbose"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
Once built, a parser is normally used like this:
|
105
|
+
|
106
|
+
arg_values = arg_parser.parse!
|
107
|
+
|
108
|
+
and argument values retrieved using struct or hash notation:
|
109
|
+
|
110
|
+
p arg_values.verbose
|
111
|
+
p arg_values[:verbose]
|
112
|
+
|
113
|
+
## Composability
|
114
|
+
|
115
|
+
An argument definition can be created separately from its use:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
VERBOSE = OptParseBuilder.build_argument do |arg|
|
119
|
+
arg.key :verbose
|
120
|
+
arg.on "-v", "--verbose", "Print extra output"
|
121
|
+
end
|
122
|
+
|
123
|
+
parser = OptParseBuilder.build_parser do |args|
|
124
|
+
args.add VERBOSE
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
This is especially useful where a suite of programs share some
|
129
|
+
arguments in common. Instead of defining common arguments over and
|
130
|
+
over, you can define them once and then reuse them in each program:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
# common_arguments.rb
|
134
|
+
|
135
|
+
require "opt_parse_builder"
|
136
|
+
|
137
|
+
module CommonArguments
|
138
|
+
VERBOSE = OptParseBuilder.build_argument do |arg|
|
139
|
+
arg.key :verbose
|
140
|
+
arg.on "-v", "--verbose", "Print extra output"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
```
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
# read_input.rb
|
147
|
+
|
148
|
+
require_relative "common_arguments"
|
149
|
+
|
150
|
+
ARG_PARSER = OptParseBuilder.build_parser do |args|
|
151
|
+
args.banner "Read and store the input data"
|
152
|
+
args.add do |arg|
|
153
|
+
arg.key
|
154
|
+
arg.required_operand
|
155
|
+
end
|
156
|
+
args.add CommonArguments::VERBOSE
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
# write_report.rb
|
162
|
+
|
163
|
+
require_relative "common_arguments"
|
164
|
+
|
165
|
+
ARG_PARSER = OptParseBuilder.build_parser do |args|
|
166
|
+
args.banner "Print a report based on data previously read"
|
167
|
+
args.add CommonArguments::VERBOSE
|
168
|
+
args.add do |arg|
|
169
|
+
arg.key :detail
|
170
|
+
arg.on "-d", "--detail", "Add the detail section to the report"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
When adding a pre-built operand to a parser, you can change change
|
176
|
+
it from required to optional:
|
177
|
+
|
178
|
+
```
|
179
|
+
PATH = OptParseBuilder.build_argument do |arg|
|
180
|
+
arg.key :path
|
181
|
+
arg.required_operand
|
182
|
+
end
|
183
|
+
|
184
|
+
ARG_PARSER = OptParser.build_parser do |args|
|
185
|
+
args.add PATH.optional
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
or from optional to required:
|
190
|
+
|
191
|
+
```
|
192
|
+
PATH = OptParseBuilder.build_argument do |arg|
|
193
|
+
arg.key :path
|
194
|
+
arg.optional_operand
|
195
|
+
end
|
196
|
+
|
197
|
+
ARG_PARSER = OptParser.build_parser do |args|
|
198
|
+
args.add PATH.required
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
# Argument Building Examples
|
203
|
+
|
204
|
+
Most of these examples use a shorthand where the surrounding code
|
205
|
+
is not shown:
|
206
|
+
|
207
|
+
arg.key = :foo
|
208
|
+
arg.on "-f"
|
209
|
+
|
210
|
+
With the surrounding code, that would be this:
|
211
|
+
|
212
|
+
parser = OptparserBuilder.new do |args|
|
213
|
+
args.add do |arg|
|
214
|
+
arg.key = :foo
|
215
|
+
arg.on = "-f"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
or this:
|
220
|
+
|
221
|
+
arg = OptParseBuilder.build_argument do |arg|
|
222
|
+
arg.key = :foo
|
223
|
+
arg.on = "-f"
|
224
|
+
end
|
225
|
+
|
226
|
+
## Null argument
|
227
|
+
|
228
|
+
A null argument, having no value or visible effect:
|
229
|
+
|
230
|
+
OptParseBuilder.build_argument do |arg|
|
231
|
+
end
|
232
|
+
|
233
|
+
This has little value to you, but it fell out of the design for
|
234
|
+
free, and it is useful in the implementation.
|
235
|
+
|
236
|
+
## Banner only
|
237
|
+
|
238
|
+
An argument with only banner text (but see OptParseBuilder#banner
|
239
|
+
for the usual way to do this). "Banner" is how OptParse describes
|
240
|
+
text that appears at the top of the --help output.
|
241
|
+
|
242
|
+
OptParseBuilder.build_argument do |arg|
|
243
|
+
arg.banner "Some banner text"
|
244
|
+
arg.banner "A second line of banner text"
|
245
|
+
arg.banner <<~BANNER
|
246
|
+
A third line
|
247
|
+
A fourth line
|
248
|
+
BANNER
|
249
|
+
end
|
250
|
+
|
251
|
+
Applicable builder methods:
|
252
|
+
|
253
|
+
* banner
|
254
|
+
|
255
|
+
Banner text can be added to any argument.
|
256
|
+
|
257
|
+
## Separator only
|
258
|
+
|
259
|
+
An argument with only separator text (but see
|
260
|
+
OptParseBuilder#banner for the usual way to do this). "Separator"
|
261
|
+
is how OptParse describes text that appears at the bottom of the
|
262
|
+
--help output.
|
263
|
+
|
264
|
+
OptParseBuilder.build_argument do |arg|
|
265
|
+
arg.serparator "Separator text"
|
266
|
+
arg.serparator "A second line of separator text"
|
267
|
+
arg.serparator <<~SERPARATOR
|
268
|
+
A third line
|
269
|
+
A fourth line
|
270
|
+
SERPARATOR
|
271
|
+
end
|
272
|
+
|
273
|
+
Applicable builder methods:
|
274
|
+
|
275
|
+
* separator
|
276
|
+
|
277
|
+
Separator text can be added to any argument.
|
278
|
+
|
279
|
+
## Constant value
|
280
|
+
|
281
|
+
An argument with a constant value.
|
282
|
+
|
283
|
+
OptParseBuilder.build_argument do |arg|
|
284
|
+
arg.key :limit
|
285
|
+
arg.default 12345
|
286
|
+
end
|
287
|
+
|
288
|
+
Applicable builder methods:
|
289
|
+
|
290
|
+
* key
|
291
|
+
* default
|
292
|
+
* banner (optional)
|
293
|
+
* separator (optional)
|
294
|
+
|
295
|
+
This is of limited value, but it fell out of the design for free.
|
296
|
+
|
297
|
+
## Simple option
|
298
|
+
|
299
|
+
A simple option parsed by OptParse:
|
300
|
+
|
301
|
+
OptParseBuilder.build_argument do |arg|
|
302
|
+
arg.key :quiet
|
303
|
+
arg.on "-q", "--quiet", "Suppress normal output"
|
304
|
+
end
|
305
|
+
|
306
|
+
Applicable builder methods:
|
307
|
+
|
308
|
+
* key
|
309
|
+
* on
|
310
|
+
* default (optional)
|
311
|
+
* handler (optional)
|
312
|
+
* banner (optional)
|
313
|
+
* separator (optional)
|
314
|
+
|
315
|
+
## Option with value
|
316
|
+
|
317
|
+
A value option parsed by OptParse:
|
318
|
+
|
319
|
+
OptParseBuilder.build_argument do |arg|
|
320
|
+
arg.key :iterations
|
321
|
+
arg.default 100
|
322
|
+
arg.on "-i", "--iterations=N",
|
323
|
+
arg.on "Number of iterations (default _DEFAULT_)"
|
324
|
+
end
|
325
|
+
|
326
|
+
Applicable builder methods:
|
327
|
+
|
328
|
+
* key
|
329
|
+
* on
|
330
|
+
* default (optional)
|
331
|
+
* handler (optional)
|
332
|
+
* banner (optional)
|
333
|
+
* separator (optional)
|
334
|
+
|
335
|
+
## Required Operand
|
336
|
+
|
337
|
+
A required operand consumes one argument, with an error if there
|
338
|
+
isn't one to consume.
|
339
|
+
|
340
|
+
This example overrides the help name, which is used to describe
|
341
|
+
the operand in the --help text. Optional and splat arguments can
|
342
|
+
also have a help name override.
|
343
|
+
|
344
|
+
OptParseBuilder.build_argument do |arg|
|
345
|
+
arg.key :group
|
346
|
+
arg.required_operand help_name: "resource group"
|
347
|
+
arg.optional_operand
|
348
|
+
end
|
349
|
+
|
350
|
+
Applicable builder methods:
|
351
|
+
|
352
|
+
* key
|
353
|
+
* required_operand
|
354
|
+
* default (optional)
|
355
|
+
* banner (optional)
|
356
|
+
* separator (optional)
|
357
|
+
|
358
|
+
## Optional operand
|
359
|
+
|
360
|
+
An optional operand consumes one argument. If there isn't an
|
361
|
+
argument to consume, then the value is either nil (if no default
|
362
|
+
was specified), or the specified default value.
|
363
|
+
|
364
|
+
OptParseBuilder.build_argument do |arg|
|
365
|
+
arg.key :group_name
|
366
|
+
arg.default "main"
|
367
|
+
arg.optional_operand
|
368
|
+
end
|
369
|
+
|
370
|
+
Applicable builder methods:
|
371
|
+
|
372
|
+
* key
|
373
|
+
* optional_operand
|
374
|
+
* default (optional)
|
375
|
+
* banner (optional)
|
376
|
+
* separator (optional)
|
377
|
+
|
378
|
+
## Splat Operand
|
379
|
+
|
380
|
+
A "splat" operand consumes all remaining arguments. Its value is
|
381
|
+
always an array.
|
382
|
+
|
383
|
+
OptParseBuilder.build_argument do |arg|
|
384
|
+
arg.key :input_path
|
385
|
+
arg.optional_operand
|
386
|
+
end
|
387
|
+
|
388
|
+
Applicable builder methods:
|
389
|
+
|
390
|
+
* key
|
391
|
+
* splat_operand
|
392
|
+
* default (optional)
|
393
|
+
* banner (optional)
|
394
|
+
* separator (optional)
|
395
|
+
|
396
|
+
# Development
|
397
|
+
|
398
|
+
After checking out the repo, run `bundle` to install dependencies.
|
399
|
+
Then run `rake test` to run the tests.
|
400
|
+
|
401
|
+
To install this gem onto your local machine, run `bundle exec rake
|
402
|
+
install`. To release a new version, update the version number in
|
403
|
+
`version.rb`, and then run `bundle exec rake release`, which will
|
404
|
+
create a git tag for the version, push git commits and tags, and push
|
405
|
+
the `.gem` file to [rubygems.org](https://rubygems.org).
|
406
|
+
|
407
|
+
# Contributing
|
408
|
+
|
409
|
+
Bug reports and pull requests are welcome on GitHub at
|
410
|
+
https://github.com/wconrad/opt_parse_builder.
|
411
|
+
|
412
|
+
# Terminology
|
413
|
+
|
414
|
+
These terms are used in this library's code and documentation:
|
415
|
+
|
416
|
+
* Argument - An option or operand; a single element of ARGV
|
417
|
+
|
418
|
+
* Option - An argument parsed by optparse, like `-v` or `--size=12`
|
419
|
+
|
420
|
+
* Switch - An option that is either present or not, like `-v`
|
421
|
+
|
422
|
+
* Value option - An option with a value, like `--size=12`
|
423
|
+
|
424
|
+
* Operand - An argument not parsed by optparse, like
|
425
|
+
`/path/to/my/file`. Also called a "positional argument."
|
426
|
+
|
427
|
+
* Required operand - An operand that must be present or an error
|
428
|
+
results.
|
429
|
+
|
430
|
+
* Optional operand - An operand that may be present or not; if not
|
431
|
+
present, it receives either `nil` or a default that you set.
|
432
|
+
|
433
|
+
* Splat operand - An operand that consumes all remaining operands,
|
434
|
+
resulting in an array (possibly empty) of strings.
|