opt_parse_builder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +35 -0
  8. data/LICENSE +23 -0
  9. data/README.md +434 -0
  10. data/Rakefile +13 -0
  11. data/examples/hello_world.rb +20 -0
  12. data/lib/opt_parse_builder.rb +156 -0
  13. data/lib/opt_parse_builder/argument.rb +62 -0
  14. data/lib/opt_parse_builder/argument_builder.rb +193 -0
  15. data/lib/opt_parse_builder/argument_bundle.rb +30 -0
  16. data/lib/opt_parse_builder/argument_bundle_builder.rb +34 -0
  17. data/lib/opt_parse_builder/argument_values.rb +60 -0
  18. data/lib/opt_parse_builder/banner_argument.rb +11 -0
  19. data/lib/opt_parse_builder/constant_argument.rb +16 -0
  20. data/lib/opt_parse_builder/errors.rb +10 -0
  21. data/lib/opt_parse_builder/formats_operand_name.rb +9 -0
  22. data/lib/opt_parse_builder/has_value.rb +21 -0
  23. data/lib/opt_parse_builder/null_argument.rb +4 -0
  24. data/lib/opt_parse_builder/option_argument.rb +33 -0
  25. data/lib/opt_parse_builder/optional_operand_argument.rb +29 -0
  26. data/lib/opt_parse_builder/parser.rb +345 -0
  27. data/lib/opt_parse_builder/parser_builder.rb +17 -0
  28. data/lib/opt_parse_builder/required_operand_argument.rb +32 -0
  29. data/lib/opt_parse_builder/separator_argument.rb +11 -0
  30. data/lib/opt_parse_builder/splat_operand_argument.rb +22 -0
  31. data/lib/opt_parse_builder/stable_sort.rb +13 -0
  32. data/lib/opt_parse_builder/version.rb +6 -0
  33. data/opt_parse_builder.gemspec +35 -0
  34. data/rake/bundler.rake +1 -0
  35. data/rake/default.rake +1 -0
  36. data/rake/rdoc.rake +7 -0
  37. data/rake/spec.rake +3 -0
  38. data/rake/test.rake +2 -0
  39. metadata +126 -0
@@ -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
@@ -0,0 +1,2 @@
1
+ html
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1 @@
1
+ ruby-2.7.2
@@ -0,0 +1,5 @@
1
+ # -*- mode: fundamental -*-
2
+
3
+ # Development
4
+
5
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in opt_parse_builder.gemspec
8
+ gemspec
@@ -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.
@@ -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.