clasp-ruby 0.17.0 → 0.18.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/README.md +4 -4
- data/examples/cr-example.rb +4 -4
- data/examples/flag_and_option_aliases.md +7 -7
- data/examples/flag_and_option_aliases.rb +7 -7
- data/examples/show_usage_and_version.md +6 -6
- data/examples/show_usage_and_version.rb +6 -6
- data/lib/clasp/aliases.rb +18 -15
- data/lib/clasp/arguments.rb +34 -31
- data/lib/clasp/cli.rb +25 -24
- data/lib/clasp/version.rb +1 -1
- data/test/scratch/test_aliases.rb +5 -5
- data/test/scratch/test_list_command_line.rb +2 -2
- data/test/scratch/test_usage.rb +4 -4
- data/test/scratch/test_usage_with_duplicate_aliases.rb +4 -4
- data/test/unit/tc_aliases.rb +1 -1
- data/test/unit/tc_cli.rb +2 -2
- data/test/unit/tc_examples_Arguments.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 119fcad10a9c01d575d47bc9f495fda5bb1869d1
|
4
|
+
data.tar.gz: 3a4c4edbf579ce92c968833ba2f13a857a7f69dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7aa695f6ef62302ac3fb64a815017e8f256130c29abcbf9b81aeb82f378cd4233f8435b0355acc91d2c24c35107809c6fa9fbcfb171f28c50b5ed5aa3018277
|
7
|
+
data.tar.gz: f0347ac65f0a4ba087c486ba2d5492890fd3f69240e547c1c3b7371d59c5c178417179fa86592a786b9816bc5b296af17bc23a23adba5d3ff85830c473751d66
|
data/README.md
CHANGED
@@ -96,7 +96,7 @@ like the following:
|
|
96
96
|
|
97
97
|
PROGRAM_VERSION = '0.1.2'
|
98
98
|
|
99
|
-
|
99
|
+
Specifications = [
|
100
100
|
|
101
101
|
CLASP.Flag('--all', alias: '-a', help: 'processes all item types'),
|
102
102
|
CLASP.Flag('-c', help: 'count the processed items'),
|
@@ -109,7 +109,7 @@ Aliases = [
|
|
109
109
|
]
|
110
110
|
|
111
111
|
# assuming the command-line `myprog -acv infile outfile`
|
112
|
-
Args = CLASP::Arguments.new(ARGV,
|
112
|
+
Args = CLASP::Arguments.new(ARGV, Specifications)
|
113
113
|
|
114
114
|
puts Args.flags.size # => 2
|
115
115
|
puts Args.flags[0].name # => "--all"
|
@@ -136,10 +136,10 @@ Args.flags.each do |f|
|
|
136
136
|
case f.name
|
137
137
|
when CLASP::Flag.Help.name
|
138
138
|
|
139
|
-
CLASP.show_usage(
|
139
|
+
CLASP.show_usage(Specifications, exit: 0, values: '<input-file> <output-file>')
|
140
140
|
when CLASP::Flag.Version.name
|
141
141
|
|
142
|
-
CLASP.show_version(
|
142
|
+
CLASP.show_version(Specifications, exit: 0, version: PROGRAM_VERSION)
|
143
143
|
when '--all'
|
144
144
|
|
145
145
|
# do something appropriate to `--all`
|
data/examples/cr-example.rb
CHANGED
@@ -18,7 +18,7 @@ require 'clasp'
|
|
18
18
|
|
19
19
|
PROGRAM_VERSION = '0.1.2'
|
20
20
|
|
21
|
-
|
21
|
+
Specifications = [
|
22
22
|
|
23
23
|
CLASP.Flag('--all', alias: '-a', help: 'processes all item types'),
|
24
24
|
CLASP.Flag('-c', help: 'count the processed items'),
|
@@ -30,17 +30,17 @@ Aliases = [
|
|
30
30
|
CLASP::Flag.Version,
|
31
31
|
]
|
32
32
|
|
33
|
-
Args = CLASP::Arguments.new(ARGV,
|
33
|
+
Args = CLASP::Arguments.new(ARGV, Specifications)
|
34
34
|
|
35
35
|
Args.flags.each do |f|
|
36
36
|
|
37
37
|
case f.name
|
38
38
|
when CLASP::Flag.Help.name
|
39
39
|
|
40
|
-
CLASP.show_usage(
|
40
|
+
CLASP.show_usage(Specifications, exit: 0, values: '<input-file> <output-file>')
|
41
41
|
when CLASP::Flag.Version.name
|
42
42
|
|
43
|
-
CLASP.show_version(
|
43
|
+
CLASP.show_version(Specifications, exit: 0, version: PROGRAM_VERSION)
|
44
44
|
when '--all'
|
45
45
|
|
46
46
|
;
|
@@ -33,26 +33,26 @@ Flag_Debug = CLASP.Flag('--debug', alias: '-d', help: 'runs in Debug mode')
|
|
33
33
|
Option_Verbosity = CLASP.Option('--verbosity', alias: '-v', help: 'specifies the verbosity', values: [ 'terse', 'quiet', 'silent', 'chatty' ])
|
34
34
|
Flag_Chatty = CLASP.Flag('--verbosity=chatty', alias: '-c')
|
35
35
|
|
36
|
-
|
36
|
+
Specifications = [
|
37
37
|
|
38
38
|
Flag_Debug,
|
39
39
|
Option_Verbosity,
|
40
40
|
Flag_Chatty,
|
41
41
|
|
42
|
-
CLASP::
|
43
|
-
CLASP::
|
42
|
+
CLASP::FlagSpecification.Help,
|
43
|
+
CLASP::FlagSpecification.Version,
|
44
44
|
]
|
45
45
|
|
46
|
-
args = CLASP::Arguments.new ARGV,
|
46
|
+
args = CLASP::Arguments.new ARGV, Specifications
|
47
47
|
|
48
|
-
if args.flags.include?(CLASP::
|
48
|
+
if args.flags.include?(CLASP::FlagSpecification.Help)
|
49
49
|
|
50
|
-
CLASP.show_usage(
|
50
|
+
CLASP.show_usage(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout, info_lines: InfoLines)
|
51
51
|
end
|
52
52
|
|
53
53
|
if args.flags.include?('--version')
|
54
54
|
|
55
|
-
CLASP.show_version(
|
55
|
+
CLASP.show_version(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout)
|
56
56
|
end
|
57
57
|
|
58
58
|
|
@@ -24,26 +24,26 @@ Flag_Debug = CLASP.Flag('--debug', alias: '-d', help: 'runs in Debug mode')
|
|
24
24
|
Option_Verbosity = CLASP.Option('--verbosity', alias: '-v', help: 'specifies the verbosity', values: [ 'terse', 'quiet', 'silent', 'chatty' ])
|
25
25
|
Flag_Chatty = CLASP.Flag('--verbosity=chatty', alias: '-c')
|
26
26
|
|
27
|
-
|
27
|
+
Specifications = [
|
28
28
|
|
29
29
|
Flag_Debug,
|
30
30
|
Option_Verbosity,
|
31
31
|
Flag_Chatty,
|
32
32
|
|
33
|
-
CLASP::
|
34
|
-
CLASP::
|
33
|
+
CLASP::FlagSpecification.Help,
|
34
|
+
CLASP::FlagSpecification.Version,
|
35
35
|
]
|
36
36
|
|
37
|
-
args = CLASP::Arguments.new ARGV,
|
37
|
+
args = CLASP::Arguments.new ARGV, Specifications
|
38
38
|
|
39
|
-
if args.flags.include?(CLASP::
|
39
|
+
if args.flags.include?(CLASP::FlagSpecification.Help)
|
40
40
|
|
41
|
-
CLASP.show_usage(
|
41
|
+
CLASP.show_usage(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout, info_lines: InfoLines)
|
42
42
|
end
|
43
43
|
|
44
44
|
if args.flags.include?('--version')
|
45
45
|
|
46
|
-
CLASP.show_version(
|
46
|
+
CLASP.show_version(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout)
|
47
47
|
end
|
48
48
|
|
49
49
|
|
@@ -29,22 +29,22 @@ InfoLines = [
|
|
29
29
|
|
30
30
|
# Specify aliases, parse, and checking standard flags
|
31
31
|
|
32
|
-
|
32
|
+
Specifications = [
|
33
33
|
|
34
|
-
CLASP::
|
35
|
-
CLASP::
|
34
|
+
CLASP::FlagSpecification.Help,
|
35
|
+
CLASP::FlagSpecification.Version,
|
36
36
|
]
|
37
37
|
|
38
|
-
args = CLASP::Arguments.new ARGV,
|
38
|
+
args = CLASP::Arguments.new ARGV, Specifications
|
39
39
|
|
40
40
|
if args.flags.include?('--help')
|
41
41
|
|
42
|
-
CLASP.show_usage(
|
42
|
+
CLASP.show_usage(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout, info_lines: InfoLines)
|
43
43
|
end
|
44
44
|
|
45
45
|
if args.flags.include?('--version')
|
46
46
|
|
47
|
-
CLASP.show_version(
|
47
|
+
CLASP.show_version(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout)
|
48
48
|
end
|
49
49
|
|
50
50
|
|
@@ -20,22 +20,22 @@ InfoLines = [
|
|
20
20
|
|
21
21
|
# Specify aliases, parse, and checking standard flags
|
22
22
|
|
23
|
-
|
23
|
+
Specifications = [
|
24
24
|
|
25
|
-
CLASP::
|
26
|
-
CLASP::
|
25
|
+
CLASP::FlagSpecification.Help,
|
26
|
+
CLASP::FlagSpecification.Version,
|
27
27
|
]
|
28
28
|
|
29
|
-
args = CLASP::Arguments.new ARGV,
|
29
|
+
args = CLASP::Arguments.new ARGV, Specifications
|
30
30
|
|
31
31
|
if args.flags.include?('--help')
|
32
32
|
|
33
|
-
CLASP.show_usage(
|
33
|
+
CLASP.show_usage(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout, info_lines: InfoLines)
|
34
34
|
end
|
35
35
|
|
36
36
|
if args.flags.include?('--version')
|
37
37
|
|
38
|
-
CLASP.show_version(
|
38
|
+
CLASP.show_version(Specifications, exit_code: 0, version: ProgramVersion, stream: $stdout)
|
39
39
|
end
|
40
40
|
|
41
41
|
|
data/lib/clasp/aliases.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# ######################################################################## #
|
3
3
|
# File: clasp/aliases.rb
|
4
4
|
#
|
5
|
-
# Purpose:
|
5
|
+
# Purpose: Argument specification classes
|
6
6
|
#
|
7
7
|
# Created: 25th October 2014
|
8
8
|
# Updated: 10th April 2019
|
@@ -58,9 +58,9 @@ module CLASP
|
|
58
58
|
# classes
|
59
59
|
|
60
60
|
# A class that represents the specification for a command-line flag
|
61
|
-
class
|
61
|
+
class FlagSpecification
|
62
62
|
|
63
|
-
# Creates a
|
63
|
+
# Creates a FlagSpecification instance from the given name, aliases, and help
|
64
64
|
#
|
65
65
|
# === Signature
|
66
66
|
#
|
@@ -96,7 +96,7 @@ class FlagAlias
|
|
96
96
|
@@Help_ = self.new('--help', [], 'shows this help and terminates')
|
97
97
|
@@Version_ = self.new('--version', [], 'shows version and terminates')
|
98
98
|
public
|
99
|
-
# An instance of
|
99
|
+
# An instance of FlagSpecification that provides default '--help' information
|
100
100
|
def self.Help(extras = nil)
|
101
101
|
|
102
102
|
h = @@Help_
|
@@ -106,7 +106,7 @@ class FlagAlias
|
|
106
106
|
h
|
107
107
|
end
|
108
108
|
|
109
|
-
# An instance of
|
109
|
+
# An instance of FlagSpecification that provides default '--version' information
|
110
110
|
def self.Version(extras = nil)
|
111
111
|
|
112
112
|
h = @@Version_
|
@@ -118,9 +118,9 @@ class FlagAlias
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# A class that represents the specification for a command-line option
|
121
|
-
class
|
121
|
+
class OptionSpecification
|
122
122
|
|
123
|
-
# Creates an
|
123
|
+
# Creates an OptionSpecification instance from the given name, aliases, help,
|
124
124
|
# values_range, and default_value
|
125
125
|
#
|
126
126
|
# === Signature
|
@@ -198,7 +198,7 @@ class OptionAlias
|
|
198
198
|
end
|
199
199
|
|
200
200
|
# A class that represents an explicit alias for a flag or an option
|
201
|
-
class
|
201
|
+
class Specification
|
202
202
|
|
203
203
|
def initialize(name, aliases)
|
204
204
|
|
@@ -227,7 +227,7 @@ end
|
|
227
227
|
# ######################################################################## #
|
228
228
|
# functions
|
229
229
|
|
230
|
-
# Generator method that obtains a CLASP::
|
230
|
+
# Generator method that obtains a CLASP::FlagSpecification according to the given
|
231
231
|
# parameters
|
232
232
|
#
|
233
233
|
# === Signature
|
@@ -277,10 +277,10 @@ def CLASP.Flag(name, options = {})
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
-
CLASP::
|
280
|
+
CLASP::FlagSpecification.new(name, aliases, help, extras)
|
281
281
|
end
|
282
282
|
|
283
|
-
# Generator method that obtains a CLASP::
|
283
|
+
# Generator method that obtains a CLASP::OptionSpecification according to the given
|
284
284
|
# parameters
|
285
285
|
#
|
286
286
|
# === Signature
|
@@ -360,7 +360,7 @@ def CLASP.Option(name, options = {})
|
|
360
360
|
end
|
361
361
|
end
|
362
362
|
|
363
|
-
CLASP::
|
363
|
+
CLASP::OptionSpecification.new(name, aliases, help, values_range, default_value, required, require_message, extras)
|
364
364
|
end
|
365
365
|
|
366
366
|
def CLASP.Alias(name, *args)
|
@@ -379,14 +379,17 @@ def CLASP.Alias(name, *args)
|
|
379
379
|
aliases = args
|
380
380
|
end
|
381
381
|
|
382
|
-
CLASP::
|
382
|
+
CLASP::Specification.new name, aliases
|
383
383
|
end
|
384
384
|
|
385
385
|
# ######################################################################## #
|
386
386
|
# backwards-compatible
|
387
387
|
|
388
|
-
|
389
|
-
|
388
|
+
Alias = Specification
|
389
|
+
Flag = FlagSpecification
|
390
|
+
FlagAlias = FlagSpecification
|
391
|
+
Option = OptionSpecification
|
392
|
+
OptionAlias = OptionSpecification
|
390
393
|
|
391
394
|
# ######################################################################## #
|
392
395
|
# module
|
data/lib/clasp/arguments.rb
CHANGED
@@ -226,13 +226,13 @@ class Arguments
|
|
226
226
|
end
|
227
227
|
end
|
228
228
|
|
229
|
-
|
229
|
+
specifications = []
|
230
230
|
|
231
231
|
_clasp = h['clasp'] or raise ArgumentError, "missing top-level 'clasp' element in load configuration"
|
232
232
|
::Hash === _clasp or raise ArgumentError, "top-level 'clasp' element must be a #{::Hash}"
|
233
233
|
|
234
|
-
_specs = (_clasp['arg-specs'] || _clasp['aliases']) or raise ArgumentError, "missing element 'clasp/
|
235
|
-
::Array === _specs or raise ArgumentError, "top-level '
|
234
|
+
_specs = (_clasp['arg-specs'] || _clasp['specifications'] || _clasp['aliases']) or raise ArgumentError, "missing element 'clasp/specifications'"
|
235
|
+
::Array === _specs or raise ArgumentError, "top-level 'specifications' element must be a #{::Hash}"
|
236
236
|
|
237
237
|
_specs.each do |_spec|
|
238
238
|
|
@@ -250,14 +250,14 @@ class Arguments
|
|
250
250
|
|
251
251
|
unless _name
|
252
252
|
|
253
|
-
warn "flag
|
253
|
+
warn "flag specification missing required 'name' field"
|
254
254
|
else
|
255
255
|
|
256
256
|
_alias = _details['alias']
|
257
257
|
_aliases = _details['aliases']
|
258
258
|
_help = _details['help'] || _details['description']
|
259
259
|
|
260
|
-
|
260
|
+
specifications << CLASP.Flag(_name, alias: _alias, aliases: _aliases, help: _help)
|
261
261
|
end
|
262
262
|
when 'option', :option
|
263
263
|
|
@@ -265,7 +265,7 @@ class Arguments
|
|
265
265
|
|
266
266
|
unless _name
|
267
267
|
|
268
|
-
warn "option
|
268
|
+
warn "option specification missing required 'name' field"
|
269
269
|
else
|
270
270
|
|
271
271
|
_alias = _details['alias']
|
@@ -276,7 +276,7 @@ class Arguments
|
|
276
276
|
_required_message = _details['required_message']
|
277
277
|
_values_range = _details['values_range'] || _details['values']
|
278
278
|
|
279
|
-
|
279
|
+
specifications << CLASP.Option(_name, alias: _alias, aliases: _aliases, default_value: _default_value, help: _help, required: _required, required_message: _required_message, values_range: _values_range)
|
280
280
|
end
|
281
281
|
when 'alias', :alias
|
282
282
|
|
@@ -284,7 +284,7 @@ class Arguments
|
|
284
284
|
|
285
285
|
unless _resolved
|
286
286
|
|
287
|
-
warn "alias
|
287
|
+
warn "alias specification missing required 'resolved' field"
|
288
288
|
else
|
289
289
|
|
290
290
|
_alias = _details['alias']
|
@@ -292,10 +292,10 @@ class Arguments
|
|
292
292
|
|
293
293
|
unless _alias || _aliases
|
294
294
|
|
295
|
-
warn "alias
|
295
|
+
warn "alias specification missing required 'alias' or 'aliases' field"
|
296
296
|
else
|
297
297
|
|
298
|
-
|
298
|
+
specifications << CLASP.Flag(_resolved, alias: _alias, aliases: _aliases)
|
299
299
|
end
|
300
300
|
end
|
301
301
|
else
|
@@ -305,11 +305,11 @@ class Arguments
|
|
305
305
|
end
|
306
306
|
else
|
307
307
|
|
308
|
-
warn "non-#{::Hash} element in 'clasp/
|
308
|
+
warn "non-#{::Hash} element in 'clasp/specifications': #{_spec} (of type #{_spec.class})"
|
309
309
|
end
|
310
310
|
end
|
311
311
|
|
312
|
-
self.new argv,
|
312
|
+
self.new argv, specifications, options
|
313
313
|
end
|
314
314
|
|
315
315
|
# Constructs an instance of the class, according to the given parameters
|
@@ -320,13 +320,13 @@ class Arguments
|
|
320
320
|
#
|
321
321
|
# * *Parameters*:
|
322
322
|
# - +argv+:: (+Array+) The arguments array. May not be +nil+. Defaults to +ARGV+.
|
323
|
-
# - +
|
323
|
+
# - +specifications+:: (+Array+) The specifications array. Defaults to +nil+. If none supplied, no aliasing will be performed.
|
324
324
|
# - +options+:: An options hash, containing any of the following options.
|
325
325
|
#
|
326
326
|
# * *Options*:
|
327
327
|
# - +mutate_argv:+:: (+Boolean+) Determines if the library should mutate +argv+. Defaults to +true+. This is essential when using CLASP in conjunction with <tt>$\<</tt>.
|
328
328
|
#
|
329
|
-
def initialize(argv = ARGV,
|
329
|
+
def initialize(argv = ARGV, specifications = nil, options = {})
|
330
330
|
|
331
331
|
# have to do this name-swap, as 'options' has CLASP-specific
|
332
332
|
# meaning
|
@@ -340,11 +340,11 @@ class Arguments
|
|
340
340
|
argv = argv.dup
|
341
341
|
@argv_original_copy = argv.dup.freeze
|
342
342
|
|
343
|
-
@
|
343
|
+
@specifications = specifications
|
344
344
|
|
345
|
-
|
345
|
+
specifications = nil if specifications and specifications.empty?
|
346
346
|
|
347
|
-
flags, options, values = Arguments.parse(argv,
|
347
|
+
flags, options, values = Arguments.parse(argv, specifications)
|
348
348
|
|
349
349
|
[ flags, options, values ].each do |ar|
|
350
350
|
|
@@ -403,7 +403,7 @@ class Arguments
|
|
403
403
|
$0
|
404
404
|
end
|
405
405
|
|
406
|
-
def self.parse(argv,
|
406
|
+
def self.parse(argv, specifications)
|
407
407
|
|
408
408
|
flags = []
|
409
409
|
options = []
|
@@ -433,7 +433,7 @@ class Arguments
|
|
433
433
|
argument_alias = nil
|
434
434
|
resolved_name = nil
|
435
435
|
|
436
|
-
(
|
436
|
+
(specifications || []).each do |a|
|
437
437
|
|
438
438
|
if a.name == given_name or a.aliases.include? given_name
|
439
439
|
|
@@ -454,7 +454,7 @@ class Arguments
|
|
454
454
|
end
|
455
455
|
|
456
456
|
# Here we intercept and (potentially) cater to grouped flags
|
457
|
-
if not argument_alias and not value and
|
457
|
+
if not argument_alias and not value and specifications and 1 == hyphens.size
|
458
458
|
|
459
459
|
# Must match all
|
460
460
|
flag_aliases = []
|
@@ -465,10 +465,10 @@ class Arguments
|
|
465
465
|
flag_alias = nil
|
466
466
|
|
467
467
|
# special case where the flag's actual name is short form and found here
|
468
|
-
flag_alias ||=
|
468
|
+
flag_alias ||= specifications.detect { |a| a.is_a?(CLASP::FlagSpecification) && a.name == new_flag }
|
469
469
|
|
470
|
-
# if not found as a flag, look in each
|
471
|
-
flag_alias ||=
|
470
|
+
# if not found as a flag, look in each specifications' aliases
|
471
|
+
flag_alias ||= specifications.detect { |a| a.aliases.include? new_flag }
|
472
472
|
|
473
473
|
if not flag_alias
|
474
474
|
|
@@ -489,7 +489,7 @@ class Arguments
|
|
489
489
|
# convert to argv and invoke
|
490
490
|
flags_argv = flag_aliases.map { |a| a.name }
|
491
491
|
|
492
|
-
grp_flags, grp_options, grp_value = Arguments.parse flags_argv,
|
492
|
+
grp_flags, grp_options, grp_value = Arguments.parse flags_argv, specifications
|
493
493
|
|
494
494
|
grp_flags.map! { |f| FlagArgument.new(arg, index, given_name, f.name, f.argument_alias, hyphens.size, given_label, argument_alias ? argument_alias.extras : nil) }
|
495
495
|
grp_options.map! { |o| OptionArgument.new(arg, index, given_name, o.name, o.argument_alias, hyphens.size, given_label, o.value, argument_alias ? argument_alias.extras : nil) }
|
@@ -502,7 +502,7 @@ class Arguments
|
|
502
502
|
end
|
503
503
|
end
|
504
504
|
|
505
|
-
if argument_alias and argument_alias.is_a? CLASP::
|
505
|
+
if argument_alias and argument_alias.is_a? CLASP::OptionSpecification and not value
|
506
506
|
|
507
507
|
want_option_value = true
|
508
508
|
options << OptionArgument.new(arg, index, given_name, resolved_name, argument_alias, hyphens.size, given_label, nil, argument_alias ? argument_alias.extras : nil)
|
@@ -544,8 +544,11 @@ class Arguments
|
|
544
544
|
# Attributes
|
545
545
|
|
546
546
|
public
|
547
|
-
# an immutable array of
|
548
|
-
attr_reader :
|
547
|
+
# an immutable array of specifications
|
548
|
+
attr_reader :specifications
|
549
|
+
|
550
|
+
# [DEPRECATED] Instead refer to +specifications+
|
551
|
+
def aliases; @specifications; end
|
549
552
|
|
550
553
|
# an immutable array of flags
|
551
554
|
attr_reader :flags
|
@@ -572,18 +575,18 @@ class Arguments
|
|
572
575
|
|
573
576
|
raise ArgumentError, "options must be nil or Hash - #{option.class} given" unless options.is_a? ::Hash
|
574
577
|
|
575
|
-
|
578
|
+
specifications = options[:aliases] || @specifications
|
576
579
|
|
577
|
-
raise ArgumentError, "
|
580
|
+
raise ArgumentError, "specifications may not be nil" if specifications.nil?
|
578
581
|
|
579
582
|
flags.each do |f|
|
580
583
|
|
581
|
-
return f unless
|
584
|
+
return f unless specifications.any? { |al| al.is_a?(::CLASP::FlagSpecification) && al.name == f.name }
|
582
585
|
end
|
583
586
|
|
584
587
|
self.options.each do |o|
|
585
588
|
|
586
|
-
return o unless
|
589
|
+
return o unless specifications.any? { |al| al.is_a?(::CLASP::OptionSpecification) && al.name == o.name }
|
587
590
|
end
|
588
591
|
|
589
592
|
nil
|
data/lib/clasp/cli.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# Purpose: Command-line interface
|
6
6
|
#
|
7
7
|
# Created: 27th July 2015
|
8
|
-
# Updated:
|
8
|
+
# Updated: 10th April 2019
|
9
9
|
#
|
10
10
|
# Home: http://github.com/synesissoftware/CLASP.Ruby
|
11
11
|
#
|
@@ -64,7 +64,7 @@ module CLI_helpers_
|
|
64
64
|
|
65
65
|
module Constants
|
66
66
|
|
67
|
-
VALID_ALIAS_TYPES = [
|
67
|
+
VALID_ALIAS_TYPES = [ FlagSpecification, OptionSpecification, Specification ]
|
68
68
|
VALID_ALIAS_TYPES_STRING = VALID_ALIAS_TYPES[0...-1].join(', ') + ', or ' + VALID_ALIAS_TYPES[-1].to_s
|
69
69
|
end # module Constants
|
70
70
|
|
@@ -109,12 +109,12 @@ end # module CLI_helpers_
|
|
109
109
|
|
110
110
|
# :startdoc:
|
111
111
|
|
112
|
-
# Displays usage for the program according to the given
|
112
|
+
# Displays usage for the program according to the given specifications and options
|
113
113
|
#
|
114
114
|
# === Signature
|
115
115
|
#
|
116
116
|
# * *Parameters*:
|
117
|
-
# - +
|
117
|
+
# - +specifications+:: (+Array+) The arguments array. May not be +nil+. Defaults to +ARGV+.
|
118
118
|
# - +options+:: An options hash, containing any of the following options.
|
119
119
|
#
|
120
120
|
# * *Options*:
|
@@ -125,18 +125,18 @@ end # module CLI_helpers_
|
|
125
125
|
# - +:values+:: appends this string to USAGE line if specified.
|
126
126
|
# - +:flags_and_options+:: inserts a custom string instead of the default string <tt>'[ ... flags and options ... ]'</tt>.
|
127
127
|
# - +:info_lines+:: inserts 0+ information lines prior to the usage.
|
128
|
-
def self.show_usage
|
128
|
+
def self.show_usage specifications, options={}
|
129
129
|
|
130
130
|
options ||= {}
|
131
131
|
|
132
|
-
raise ArgumentError, "
|
133
|
-
raise TypeError, "
|
132
|
+
raise ArgumentError, "specifications may not be nil" if specifications.nil?
|
133
|
+
raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
|
134
134
|
|
135
135
|
constants = CLI_helpers_::Constants
|
136
|
-
|
136
|
+
specifications.each { |a| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === a } }
|
137
137
|
|
138
138
|
alias_dups = {}
|
139
|
-
|
139
|
+
specifications.each { |a| a.aliases.each { |aa| warn "WARNING: alias '#{aa}' is already used for alias '#{a}'" if alias_dups.has_key? aa; alias_dups[aa] = a; } }
|
140
140
|
|
141
141
|
suppress_blanks = options[:suppress_blank_lines_between_options] || ENV['SUPPRESS_BLANK_LINES_BETWEEN_OPTIONS']
|
142
142
|
|
@@ -173,11 +173,12 @@ def self.show_usage aliases, options={}
|
|
173
173
|
flags_and_options = options[:flags_and_options] || ' [ ... flags and options ... ]'
|
174
174
|
flags_and_options = " #{flags_and_options}" if !flags_and_options.empty? && ' ' != flags_and_options[0]
|
175
175
|
|
176
|
-
# sift the
|
176
|
+
# sift the specifications to sort out which are value-option
|
177
|
+
# specifications (VOAs)
|
177
178
|
|
178
179
|
voas = {}
|
179
180
|
|
180
|
-
|
181
|
+
specifications.select { |a| a.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }.each do |a|
|
181
182
|
|
182
183
|
a.name =~ /^(-+[a-zA-Z0-3_-]+)[=:](.+)$/
|
183
184
|
|
@@ -187,30 +188,30 @@ def self.show_usage aliases, options={}
|
|
187
188
|
|
188
189
|
fas = {}
|
189
190
|
|
190
|
-
|
191
|
+
specifications.select { |a| Specification === a }.each do |a|
|
191
192
|
|
192
193
|
fas[a.name] = [] unless fas.has_key? $1
|
193
194
|
fas[a.name] << a
|
194
195
|
end
|
195
196
|
|
196
|
-
|
197
|
+
specifications = specifications.reject { |a| a.name =~ /^-+[a-zA-Z0-3_-]+[=:].+/ }
|
197
198
|
|
198
199
|
info_lines.each { |info_line| stream.puts info_line } unless info_lines.empty?
|
199
200
|
|
200
201
|
stream.puts "USAGE: #{program_name}#{flags_and_options}#{values}"
|
201
202
|
stream.puts
|
202
203
|
|
203
|
-
unless
|
204
|
+
unless specifications.empty?
|
204
205
|
|
205
206
|
stream.puts "flags/options:"
|
206
207
|
stream.puts
|
207
|
-
|
208
|
+
specifications.each do |a|
|
208
209
|
|
209
210
|
case a
|
210
|
-
when
|
211
|
+
when Specification
|
211
212
|
|
212
213
|
next
|
213
|
-
when
|
214
|
+
when FlagSpecification
|
214
215
|
|
215
216
|
if fas.has_key? a.name
|
216
217
|
|
@@ -222,7 +223,7 @@ def self.show_usage aliases, options={}
|
|
222
223
|
a.aliases.each { |al| stream.puts "\t#{al}" }
|
223
224
|
stream.puts "\t#{a.name}"
|
224
225
|
stream.puts "\t\t#{a.help}"
|
225
|
-
when
|
226
|
+
when OptionSpecification
|
226
227
|
|
227
228
|
if voas.has_key? a.name
|
228
229
|
|
@@ -249,12 +250,12 @@ def self.show_usage aliases, options={}
|
|
249
250
|
exit exit_code if exit_code
|
250
251
|
end
|
251
252
|
|
252
|
-
# Displays version for the program according to the given
|
253
|
+
# Displays version for the program according to the given specifications and options
|
253
254
|
#
|
254
255
|
# === Signature
|
255
256
|
#
|
256
257
|
# * *Parameters*:
|
257
|
-
# - +
|
258
|
+
# - +specifications+:: (+Array+) The arguments array. May not be +nil+. Defaults to +ARGV+.
|
258
259
|
# - +options+:: An options hash, containing any of the following options.
|
259
260
|
#
|
260
261
|
# * *Options*:
|
@@ -267,15 +268,15 @@ end
|
|
267
268
|
# - +:version_revision+:: a number or string. Only considered if +:version+ is not.
|
268
269
|
# - +:version_build+:: a number or string. Only considered if +:version+ is not.
|
269
270
|
# - +:version_prefix+:: optional string to prefix the version number(s).
|
270
|
-
def self.show_version
|
271
|
+
def self.show_version specifications, options = {}
|
271
272
|
|
272
273
|
options ||= {}
|
273
274
|
|
274
|
-
raise ArgumentError, "
|
275
|
-
raise TypeError, "
|
275
|
+
raise ArgumentError, "specifications may not be nil" if specifications.nil?
|
276
|
+
raise TypeError, "specifications must be an array or must respond to each, reject and select" unless ::Array === specifications || (specifications.respond_to?(:each) && specifications.respond_to?(:reject) && specifications.respond_to?(:select))
|
276
277
|
|
277
278
|
constants = CLI_helpers_::Constants
|
278
|
-
|
279
|
+
specifications.each { |a| raise ::TypeError, "each element in specifications array must be one of the types #{constants::VALID_ALIAS_TYPES_STRING}" unless constants::VALID_ALIAS_TYPES.any? { |c| c === a } }
|
279
280
|
|
280
281
|
stream = options[:stream] || $stdout
|
281
282
|
|
data/lib/clasp/version.rb
CHANGED
@@ -4,27 +4,27 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
|
4
4
|
|
5
5
|
require 'clasp'
|
6
6
|
|
7
|
-
|
7
|
+
Specifications = [
|
8
8
|
|
9
9
|
CLASP.Flag('--help', help: 'shows this help and quits'),
|
10
10
|
CLASP.Flag('--version', alias: '-v', help: 'shows this version and quits'),
|
11
|
-
CLASP.
|
11
|
+
CLASP.Specification('--version', aliases: [ '-ver', '-V' ]),
|
12
12
|
|
13
13
|
CLASP.Option('--directory', alias: '-d', help: 'a directory within which to process'),
|
14
14
|
CLASP.Option('--patterns', alias: '-p', help: "one or more patterns against which the entries will be matched, separated by '|' or the platform-specific separator - ':' UNIX, ';' Windows"),
|
15
15
|
|
16
16
|
CLASP.Option('--case-sensitive', alias: '-c', help: 'determines whether case sensitive', values_range: %W{ yes no true false }, default_value: false),
|
17
|
-
CLASP.
|
17
|
+
CLASP.Specification('--case-sensitive=false', alias: '-I'),
|
18
18
|
]
|
19
19
|
|
20
|
-
Arguments = CLASP::Arguments.new(ARGV,
|
20
|
+
Arguments = CLASP::Arguments.new(ARGV, Specifications)
|
21
21
|
Flags = Arguments.flags
|
22
22
|
Options = Arguments.options
|
23
23
|
Values = Arguments.values
|
24
24
|
|
25
25
|
if Flags.include? '--help'
|
26
26
|
|
27
|
-
CLASP.show_usage
|
27
|
+
CLASP.show_usage Specifications, exit: 0
|
28
28
|
end
|
29
29
|
|
30
30
|
Flags.each do |f|
|
@@ -4,7 +4,7 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
|
4
4
|
|
5
5
|
require 'clasp'
|
6
6
|
|
7
|
-
|
7
|
+
Specifications = [
|
8
8
|
|
9
9
|
CLASP.Flag('--help', help: 'shows this help and quits'),
|
10
10
|
CLASP.Flag('--version', alias: '-v', help: 'shows this version and quits'),
|
@@ -12,7 +12,7 @@ Aliases = [
|
|
12
12
|
CLASP.Option('--verbosity', aliases: %w{ -V --verbose }),
|
13
13
|
]
|
14
14
|
|
15
|
-
Args = CLASP::Arguments.new(ARGV,
|
15
|
+
Args = CLASP::Arguments.new(ARGV, Specifications)
|
16
16
|
|
17
17
|
puts
|
18
18
|
puts "flags #{Args.flags.size}:"
|
data/test/scratch/test_usage.rb
CHANGED
@@ -4,7 +4,7 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
|
4
4
|
|
5
5
|
require 'clasp'
|
6
6
|
|
7
|
-
|
7
|
+
Specifications = [
|
8
8
|
|
9
9
|
CLASP.Flag('--version', alias: '-v', help: 'shows the program version and quits'),
|
10
10
|
|
@@ -14,17 +14,17 @@ Aliases = [
|
|
14
14
|
CLASP.Flag('--verbosity=verbose', alias: '--verbose'),
|
15
15
|
]
|
16
16
|
|
17
|
-
Arguments = CLASP::Arguments.new(ARGV,
|
17
|
+
Arguments = CLASP::Arguments.new(ARGV, Specifications)
|
18
18
|
|
19
19
|
puts
|
20
20
|
puts '*' * 40
|
21
21
|
puts 'usage:'
|
22
22
|
puts
|
23
|
-
CLASP.show_usage(
|
23
|
+
CLASP.show_usage(Specifications)
|
24
24
|
puts '*' * 40
|
25
25
|
|
26
26
|
puts 'version:'
|
27
27
|
puts
|
28
|
-
CLASP.show_version
|
28
|
+
CLASP.show_version Specifications, version: [ 1, 2, 3 ]
|
29
29
|
puts '*' * 40
|
30
30
|
|
@@ -4,7 +4,7 @@ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
|
4
4
|
|
5
5
|
require 'clasp'
|
6
6
|
|
7
|
-
|
7
|
+
Specifications = [
|
8
8
|
|
9
9
|
CLASP.Flag('--version', alias: '-v', help: 'shows the program version and quits'),
|
10
10
|
|
@@ -14,17 +14,17 @@ Aliases = [
|
|
14
14
|
CLASP.Flag('--verbosity=verbose', aliases: [ '--verbose', '-v' ]),
|
15
15
|
]
|
16
16
|
|
17
|
-
Arguments = CLASP::Arguments.new(ARGV,
|
17
|
+
Arguments = CLASP::Arguments.new(ARGV, Specifications)
|
18
18
|
|
19
19
|
puts
|
20
20
|
puts '*' * 40
|
21
21
|
puts 'usage:'
|
22
22
|
puts
|
23
|
-
CLASP.show_usage(
|
23
|
+
CLASP.show_usage(Specifications)
|
24
24
|
puts '*' * 40
|
25
25
|
|
26
26
|
puts 'version:'
|
27
27
|
puts
|
28
|
-
CLASP.show_version
|
28
|
+
CLASP.show_version Specifications, version: [ 1, 2, 3 ]
|
29
29
|
puts '*' * 40
|
30
30
|
|
data/test/unit/tc_aliases.rb
CHANGED
data/test/unit/tc_cli.rb
CHANGED
@@ -14,9 +14,9 @@ class Test_CLI < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
def test_invalid_aliases_types
|
16
16
|
|
17
|
-
assert_raise_with_message(::TypeError,
|
17
|
+
assert_raise_with_message(::TypeError, /each element in (?:aliases|specifications) array must be one of the types CLASP::FlagSpecification, CLASP::OptionSpecification, or CLASP::Specification/) { CLASP.show_usage([ 'abc', :def ]) }
|
18
18
|
|
19
|
-
assert_raise_with_message(::TypeError,
|
19
|
+
assert_raise_with_message(::TypeError, /each element in (?:aliases|specifications) array must be one of the types CLASP::FlagSpecification, CLASP::OptionSpecification, or CLASP::Specification/) { CLASP.show_version([ 'abc', :def ]) }
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -8,7 +8,7 @@ require 'test/unit'
|
|
8
8
|
|
9
9
|
class Test_Examples < Test::Unit::TestCase
|
10
10
|
|
11
|
-
def
|
11
|
+
def test_SimpleCommandLineNoSpecifications
|
12
12
|
|
13
13
|
argv = %w{ --show-all=true infile -c outfile }
|
14
14
|
|
@@ -116,7 +116,7 @@ class Test_Examples < Test::Unit::TestCase
|
|
116
116
|
assert_equal "outfile", args.values[1]
|
117
117
|
end
|
118
118
|
|
119
|
-
def
|
119
|
+
def test_UseOfFlagsAsSpecificationsForOption
|
120
120
|
|
121
121
|
aliases = [
|
122
122
|
|