libclimate-ruby 0.17.0 → 0.17.0.1

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.
@@ -5,13 +5,13 @@
5
5
  # Purpose: Definition of the ::LibCLImate::Climate class
6
6
  #
7
7
  # Created: 13th July 2015
8
- # Updated: 10th August 2024
8
+ # Updated: 6th March 2025
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/libCLImate.Ruby
11
11
  #
12
12
  # Author: Matthew Wilson
13
13
  #
14
- # Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
14
+ # Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
15
15
  # Copyright (c) 2015-2019, Matthew Wilson and Synesis Software
16
16
  # All rights reserved.
17
17
  #
@@ -55,13 +55,13 @@ require 'yaml'
55
55
  # TODO: Need to work with other colouring libraries, too
56
56
  if !defined? Colcon # :nodoc:
57
57
 
58
- begin
58
+ begin
59
59
 
60
- require 'colcon'
61
- rescue LoadError #=> x
60
+ require 'colcon'
61
+ rescue LoadError #=> x
62
62
 
63
- warn "could not load colcon library" if $DEBUG
64
- end
63
+ warn "could not load colcon library" if $DEBUG
64
+ end
65
65
  end
66
66
 
67
67
  # We monkey-patch CLASP module's Flag and Option generator methods by
@@ -70,66 +70,66 @@ end
70
70
 
71
71
  class << CLASP
72
72
 
73
- alias_method :Flag_old, :Flag # :nodoc:
74
- alias_method :Option_old, :Option # :nodoc:
73
+ alias_method :Flag_old, :Flag # :nodoc:
74
+ alias_method :Option_old, :Option # :nodoc:
75
75
 
76
- # Defines a flag, attaching the given block
77
- def Flag(name, options={}, &blk)
76
+ # Defines a flag, attaching the given block
77
+ def Flag(name, options={}, &blk)
78
78
 
79
- f = self.Flag_old(name, options)
79
+ f = self.Flag_old(name, options)
80
80
 
81
- # anticipate this functionality being added to CLASP
82
- unless f.respond_to? :action
81
+ # anticipate this functionality being added to CLASP
82
+ unless f.respond_to? :action
83
83
 
84
- class << f
84
+ class << f
85
85
 
86
- attr_accessor :action
87
- end
88
- end
86
+ attr_accessor :action
87
+ end
88
+ end
89
89
 
90
- if blk
90
+ if blk
91
91
 
92
- case blk.arity
93
- when 0, 1, 2
94
- else
92
+ case blk.arity
93
+ when 0, 1, 2
94
+ else
95
95
 
96
- warn "wrong arity for flag"
97
- end
96
+ warn "wrong arity for flag"
97
+ end
98
98
 
99
- f.action = blk
100
- end
99
+ f.action = blk
100
+ end
101
101
 
102
- f
103
- end
102
+ f
103
+ end
104
104
 
105
- # Defines an option, attaching the given block
106
- def Option(name, options={}, &blk)
105
+ # Defines an option, attaching the given block
106
+ def Option(name, options={}, &blk)
107
107
 
108
- o = self.Option_old(name, options)
108
+ o = self.Option_old(name, options)
109
109
 
110
- # anticipate this functionality being added to CLASP
111
- unless o.respond_to? :action
110
+ # anticipate this functionality being added to CLASP
111
+ unless o.respond_to? :action
112
112
 
113
- class << o
113
+ class << o
114
114
 
115
- attr_accessor :action
116
- end
117
- end
115
+ attr_accessor :action
116
+ end
117
+ end
118
118
 
119
- if blk
119
+ if blk
120
120
 
121
- case blk.arity
122
- when 0, 1, 2
123
- else
121
+ case blk.arity
122
+ when 0, 1, 2
123
+ else
124
124
 
125
- warn "wrong arity for option"
126
- end
125
+ warn "wrong arity for option"
126
+ end
127
127
 
128
- o.action = blk
129
- end
128
+ o.action = blk
129
+ end
130
130
 
131
- o
132
- end
131
+ o
132
+ end
133
133
  end
134
134
 
135
135
  #:startdoc:
@@ -171,1261 +171,1261 @@ module LibCLImate
171
171
  #
172
172
  class Climate
173
173
 
174
- include ::Xqsr3::Quality::ParameterChecking
174
+ include ::Xqsr3::Quality::ParameterChecking
175
175
 
176
- # Represents the results obtained from +Climate#parse()+
177
- class ParseResults
176
+ # Represents the results obtained from +Climate#parse()+
177
+ class ParseResults
178
178
 
179
- def initialize(climate, arguments, options)
179
+ def initialize(climate, arguments, options)
180
180
 
181
- @climate = climate
181
+ @climate = climate
182
182
 
183
- @arguments = arguments
183
+ @arguments = arguments
184
184
 
185
- @argv = arguments.argv
186
- @argv_original_copy = arguments.argv_original_copy
187
- @specifications = arguments.specifications
188
- @program_name = climate.program_name
189
- @flags = arguments.flags
190
- @options = arguments.options
191
- @values = arguments.values
192
- @double_slash_index = arguments.double_slash_index
193
- end
185
+ @argv = arguments.argv
186
+ @argv_original_copy = arguments.argv_original_copy
187
+ @specifications = arguments.specifications
188
+ @program_name = climate.program_name
189
+ @flags = arguments.flags
190
+ @options = arguments.options
191
+ @values = arguments.values
192
+ @double_slash_index = arguments.double_slash_index
193
+ end
194
194
 
195
- # (Climate) The +Climate+ instance from which this instance was obtained
196
- attr_reader :climate
195
+ # (Climate) The +Climate+ instance from which this instance was obtained
196
+ attr_reader :climate
197
197
 
198
- # ([String]) The original arguments passed into the +Climate#parse()+ method
199
- attr_reader :argv
198
+ # ([String]) The original arguments passed into the +Climate#parse()+ method
199
+ attr_reader :argv
200
200
 
201
- # (Array) unchanged copy of the original array of arguments passed to parse
202
- attr_reader :argv_original_copy
201
+ # (Array) unchanged copy of the original array of arguments passed to parse
202
+ attr_reader :argv_original_copy
203
203
 
204
- # (Array) a frozen array of specifications
205
- attr_reader :specifications
204
+ # (Array) a frozen array of specifications
205
+ attr_reader :specifications
206
206
 
207
- # (String) The program name
208
- attr_reader :program_name
207
+ # (String) The program name
208
+ attr_reader :program_name
209
209
 
210
- # (String) A (frozen) array of flags
211
- attr_reader :flags
210
+ # (String) A (frozen) array of flags
211
+ attr_reader :flags
212
212
 
213
- # (String) A (frozen) array of options
214
- attr_reader :options
213
+ # (String) A (frozen) array of options
214
+ attr_reader :options
215
215
 
216
- # (String) A (frozen) array of values
217
- attr_reader :values
216
+ # (String) A (frozen) array of values
217
+ attr_reader :values
218
218
 
219
- attr_reader :double_slash_index
219
+ attr_reader :double_slash_index
220
220
 
221
- # Verifies the initiating command-line against the specifications,
222
- # raising an exception if any missing, unused, or unrecognised flags,
223
- # options, or values are found
224
- def verify(**options)
221
+ # Verifies the initiating command-line against the specifications,
222
+ # raising an exception if any missing, unused, or unrecognised flags,
223
+ # options, or values are found
224
+ def verify(**options)
225
225
 
226
- if v = options[:raise]
226
+ if v = options[:raise]
227
227
 
228
- hm = {}
228
+ hm = {}
229
229
 
230
- hm[:raise_on_required] = v unless options.has_key?(:raise_on_required)
231
- hm[:raise_on_unrecognised] = v unless options.has_key?(:raise_on_unrecognised)
232
- hm[:raise_on_unused] = v unless options.has_key?(:raise_on_unused)
230
+ hm[:raise_on_required] = v unless options.has_key?(:raise_on_required)
231
+ hm[:raise_on_unrecognised] = v unless options.has_key?(:raise_on_unrecognised)
232
+ hm[:raise_on_unused] = v unless options.has_key?(:raise_on_unused)
233
233
 
234
- options = options.merge hm
235
- end
234
+ options = options.merge hm
235
+ end
236
236
 
237
- raise_on_required = options[:raise_on_required]
238
- raise_on_unrecognised = options[:raise_on_unrecognised]
239
- raise_on_unused = options[:raise_on_unused]
237
+ raise_on_required = options[:raise_on_required]
238
+ raise_on_unrecognised = options[:raise_on_unrecognised]
239
+ raise_on_unused = options[:raise_on_unused]
240
240
 
241
241
 
242
- # Verification:
243
- #
244
- # 1. Check arguments recognised
245
- # 1.a Flags
246
- # 1.b Options
247
- # 2. police any required options
248
- # 3. Check values
242
+ # Verification:
243
+ #
244
+ # 1. Check arguments recognised
245
+ # 1.a Flags
246
+ # 1.b Options
247
+ # 2. police any required options
248
+ # 3. Check values
249
249
 
250
- # 1.a Flags
250
+ # 1.a Flags
251
251
 
252
- self.flags.each do |flag|
252
+ self.flags.each do |flag|
253
253
 
254
- spec = specifications.detect do |sp|
254
+ spec = specifications.detect do |sp|
255
255
 
256
- sp.kind_of?(::CLASP::FlagSpecification) && flag.name == sp.name
257
- end
256
+ sp.kind_of?(::CLASP::FlagSpecification) && flag.name == sp.name
257
+ end
258
258
 
259
- if spec
259
+ if spec
260
260
 
261
- if spec.respond_to?(:action) && !spec.action.nil?
261
+ if spec.respond_to?(:action) && !spec.action.nil?
262
262
 
263
- spec.action.call(flag, spec)
264
- end
265
- else
263
+ spec.action.call(flag, spec)
264
+ end
265
+ else
266
266
 
267
- message = make_abort_message_("unrecognised flag '#{f}'")
267
+ message = make_abort_message_("unrecognised flag '#{f}'")
268
268
 
269
- if false
269
+ if false
270
270
 
271
- elsif climate.ignore_unknown
271
+ elsif climate.ignore_unknown
272
272
 
273
- ;
274
- elsif raise_on_unrecognised
273
+ ;
274
+ elsif raise_on_unrecognised
275
275
 
276
- if raise_on_unrecognised.is_a?(Class)
276
+ if raise_on_unrecognised.is_a?(Class)
277
277
 
278
- raise raise_on_unrecognised, message
279
- else
278
+ raise raise_on_unrecognised, message
279
+ else
280
280
 
281
- raise RuntimeError, message
282
- end
283
- elsif climate.exit_on_unknown
281
+ raise RuntimeError, message
282
+ end
283
+ elsif climate.exit_on_unknown
284
284
 
285
- climate.abort message
286
- else
285
+ climate.abort message
286
+ else
287
287
 
288
- if program_name && !program_name.empty?
288
+ if program_name && !program_name.empty?
289
289
 
290
- message = "#{program_name}: #{message}"
291
- end
290
+ message = "#{program_name}: #{message}"
291
+ end
292
292
 
293
- climate.stderr.puts message
294
- end
295
- end
296
- end
293
+ climate.stderr.puts message
294
+ end
295
+ end
296
+ end
297
297
 
298
- # 1.b Options
298
+ # 1.b Options
299
299
 
300
- self.options.each do |option|
300
+ self.options.each do |option|
301
301
 
302
- spec = specifications.detect do |sp|
302
+ spec = specifications.detect do |sp|
303
303
 
304
- sp.kind_of?(::CLASP::OptionSpecification) && option.name == sp.name
305
- end
304
+ sp.kind_of?(::CLASP::OptionSpecification) && option.name == sp.name
305
+ end
306
306
 
307
- if spec
307
+ if spec
308
308
 
309
- if spec.respond_to?(:action) && !spec.action.nil?
309
+ if spec.respond_to?(:action) && !spec.action.nil?
310
310
 
311
- spec.action.call(option, spec)
312
- end
313
- else
311
+ spec.action.call(option, spec)
312
+ end
313
+ else
314
314
 
315
- message = make_abort_message_("unrecognised option '#{f}'")
315
+ message = make_abort_message_("unrecognised option '#{f}'")
316
316
 
317
- if false
317
+ if false
318
318
 
319
- elsif climate.ignore_unknown
319
+ elsif climate.ignore_unknown
320
320
 
321
- ;
322
- elsif raise_on_unrecognised
321
+ ;
322
+ elsif raise_on_unrecognised
323
323
 
324
- if raise_on_unrecognised.is_a?(Class)
324
+ if raise_on_unrecognised.is_a?(Class)
325
325
 
326
- raise raise_on_unrecognised, message
327
- else
326
+ raise raise_on_unrecognised, message
327
+ else
328
328
 
329
- raise RuntimeError, message
330
- end
331
- elsif climate.exit_on_unknown
329
+ raise RuntimeError, message
330
+ end
331
+ elsif climate.exit_on_unknown
332
332
 
333
- climate.abort message
334
- else
333
+ climate.abort message
334
+ else
335
335
 
336
- if program_name && !program_name.empty?
336
+ if program_name && !program_name.empty?
337
337
 
338
- message = "#{program_name}: #{message}"
339
- end
338
+ message = "#{program_name}: #{message}"
339
+ end
340
340
 
341
- climate.stderr.puts message
342
- end
343
- end
344
- end
341
+ climate.stderr.puts message
342
+ end
343
+ end
344
+ end
345
345
 
346
- # 2. police any required options
346
+ # 2. police any required options
347
347
 
348
- climate.check_required_options_(specifications, self.options, [], raise_on_required)
348
+ climate.check_required_options_(specifications, self.options, [], raise_on_required)
349
349
 
350
- # 3. Check values
350
+ # 3. Check values
351
351
 
352
- climate.check_value_constraints_(values)
353
- end
352
+ climate.check_value_constraints_(values)
353
+ end
354
354
 
355
- def flag_is_specified(id)
355
+ def flag_is_specified(id)
356
356
 
357
- !@arguments.find_flag(id).nil?
358
- end
357
+ !@arguments.find_flag(id).nil?
358
+ end
359
359
 
360
- def lookup_flag(id)
360
+ def lookup_flag(id)
361
361
 
362
- @arguments.find_flag(id)
363
- end
362
+ @arguments.find_flag(id)
363
+ end
364
364
 
365
- def lookup_option(id)
365
+ def lookup_option(id)
366
366
 
367
- @arguments.find_option(id)
368
- end
367
+ @arguments.find_option(id)
368
+ end
369
369
 
370
- end # end class ParseResults
370
+ end # end class ParseResults
371
371
 
372
372
 
373
- #:stopdoc:
373
+ #:stopdoc:
374
374
 
375
- private
376
- module Climate_Constants_
375
+ private
376
+ module Climate_Constants_
377
377
 
378
- GIVEN_SPECS_ = "_Given_Specs_01B59422_8407_4c89_9432_8160C52BD5AD"
379
- end # module Climate_Constants_
378
+ GIVEN_SPECS_ = "_Given_Specs_01B59422_8407_4c89_9432_8160C52BD5AD"
379
+ end # module Climate_Constants_
380
380
 
381
- def make_abort_message_(msg)
381
+ def make_abort_message_(msg)
382
382
 
383
- if 0 != (usage_help_suffix || 0).size
383
+ if 0 != (usage_help_suffix || 0).size
384
384
 
385
- "#{msg}; #{usage_help_suffix}"
386
- else
385
+ "#{msg}; #{usage_help_suffix}"
386
+ else
387
387
 
388
- msg
389
- end
390
- end
388
+ msg
389
+ end
390
+ end
391
391
 
392
- def show_usage_()
392
+ def show_usage_()
393
393
 
394
- options = {}
395
- options.merge! stream: stdout, program_name: program_name, version: version, exit: exit_on_usage ? 0 : nil
396
- options[:info_lines] = info_lines if info_lines
397
- options[:values] = usage_values if usage_values
398
- options[:flags_and_options] = flags_and_options if flags_and_options
394
+ options = {}
395
+ options.merge! stream: stdout, program_name: program_name, version: version, exit: exit_on_usage ? 0 : nil
396
+ options[:info_lines] = info_lines if info_lines
397
+ options[:values] = usage_values if usage_values
398
+ options[:flags_and_options] = flags_and_options if flags_and_options
399
399
 
400
- CLASP.show_usage specifications, options
401
- end
400
+ CLASP.show_usage specifications, options
401
+ end
402
402
 
403
- def show_version_()
403
+ def show_version_()
404
404
 
405
- CLASP.show_version specifications, stream: stdout, program_name: program_name, version: version, exit: exit_on_usage ? 0 : nil
406
- end
405
+ CLASP.show_version specifications, stream: stdout, program_name: program_name, version: version, exit: exit_on_usage ? 0 : nil
406
+ end
407
407
 
408
- def infer_version_(ctxt)
408
+ def infer_version_(ctxt)
409
409
 
410
- # algorithm:
411
- #
412
- # 1. PROGRAM_VERSION: loaded from ctxt / global
413
- # 2. PROGRAM_VER(SION)_(MAJOR|MINOR|(PATCH|REVISION)|BUILD): loaded from
414
- # ctxt / global
410
+ # algorithm:
411
+ #
412
+ # 1. PROGRAM_VERSION: loaded from ctxt / global
413
+ # 2. PROGRAM_VER(SION)_(MAJOR|MINOR|(PATCH|REVISION)|BUILD): loaded from
414
+ # ctxt / global
415
415
 
416
- if ctxt
416
+ if ctxt
417
417
 
418
- ctxt = ctxt.class unless ::Class === ctxt
418
+ ctxt = ctxt.class unless ::Class === ctxt
419
419
 
420
- return ctxt.const_get(:PROGRAM_VERSION) if ctxt.const_defined? :PROGRAM_VERSION
420
+ return ctxt.const_get(:PROGRAM_VERSION) if ctxt.const_defined? :PROGRAM_VERSION
421
421
 
422
- ver = []
422
+ ver = []
423
423
 
424
- if ctxt.const_defined? :PROGRAM_VER_MAJOR
424
+ if ctxt.const_defined? :PROGRAM_VER_MAJOR
425
425
 
426
- ver << ctxt.const_get(:PROGRAM_VER_MAJOR)
426
+ ver << ctxt.const_get(:PROGRAM_VER_MAJOR)
427
427
 
428
- if ctxt.const_defined? :PROGRAM_VER_MINOR
428
+ if ctxt.const_defined? :PROGRAM_VER_MINOR
429
429
 
430
- ver << ctxt.const_get(:PROGRAM_VER_MINOR)
430
+ ver << ctxt.const_get(:PROGRAM_VER_MINOR)
431
431
 
432
- if ctxt.const_defined?(:PROGRAM_VER_REVISION) || ctxt.const_defined?(:PROGRAM_VER_PATCH)
432
+ if ctxt.const_defined?(:PROGRAM_VER_REVISION) || ctxt.const_defined?(:PROGRAM_VER_PATCH)
433
433
 
434
- if ctxt.const_defined?(:PROGRAM_VER_PATCH)
434
+ if ctxt.const_defined?(:PROGRAM_VER_PATCH)
435
435
 
436
- ver << ctxt.const_get(:PROGRAM_VER_PATCH)
437
- else
436
+ ver << ctxt.const_get(:PROGRAM_VER_PATCH)
437
+ else
438
438
 
439
- ver << ctxt.const_get(:PROGRAM_VER_REVISION)
440
- end
439
+ ver << ctxt.const_get(:PROGRAM_VER_REVISION)
440
+ end
441
441
 
442
- if ctxt.const_defined? :PROGRAM_VER_BUILD
442
+ if ctxt.const_defined? :PROGRAM_VER_BUILD
443
443
 
444
- ver << ctxt.const_get(:PROGRAM_VER_BUILD)
445
- end
446
- end
447
- end
444
+ ver << ctxt.const_get(:PROGRAM_VER_BUILD)
445
+ end
446
+ end
447
+ end
448
448
 
449
- return ver
450
- end
451
- else
449
+ return ver
450
+ end
451
+ else
452
452
 
453
- return PROGRAM_VERSION if defined? PROGRAM_VERSION
453
+ return PROGRAM_VERSION if defined? PROGRAM_VERSION
454
454
 
455
- ver = []
455
+ ver = []
456
456
 
457
- if defined? PROGRAM_VER_MAJOR
457
+ if defined? PROGRAM_VER_MAJOR
458
458
 
459
- ver << PROGRAM_VER_MAJOR
459
+ ver << PROGRAM_VER_MAJOR
460
460
 
461
- if defined? PROGRAM_VER_MINOR
461
+ if defined? PROGRAM_VER_MINOR
462
462
 
463
- ver << PROGRAM_VER_MINOR
463
+ ver << PROGRAM_VER_MINOR
464
464
 
465
- if defined?(PROGRAM_VER_REVISION) || defined?(PROGRAM_VER_PATCH)
465
+ if defined?(PROGRAM_VER_REVISION) || defined?(PROGRAM_VER_PATCH)
466
466
 
467
- if defined?(PROGRAM_VER_PATCH)
467
+ if defined?(PROGRAM_VER_PATCH)
468
468
 
469
- ver << PROGRAM_VER_PATCH
470
- else
469
+ ver << PROGRAM_VER_PATCH
470
+ else
471
471
 
472
- ver << PROGRAM_VER_REVISION
473
- end
472
+ ver << PROGRAM_VER_REVISION
473
+ end
474
474
 
475
- if defined? PROGRAM_VER_BUILD
475
+ if defined? PROGRAM_VER_BUILD
476
476
 
477
- ver << PROGRAM_VER_BUILD
478
- end
479
- end
480
- end
477
+ ver << PROGRAM_VER_BUILD
478
+ end
479
+ end
480
+ end
481
481
 
482
- return ver
483
- end
484
- end
482
+ return ver
483
+ end
484
+ end
485
485
 
486
- nil
487
- end
486
+ nil
487
+ end
488
488
 
489
- def self.check_type_(v, types)
489
+ def self.check_type_(v, types)
490
490
 
491
- return true if v.nil?
491
+ return true if v.nil?
492
492
 
493
- types = [ types ] unless Array === types
493
+ types = [ types ] unless Array === types
494
494
 
495
- return true if types.empty?
495
+ return true if types.empty?
496
496
 
497
- types.each do |type|
497
+ types.each do |type|
498
498
 
499
- if false
499
+ if false
500
500
 
501
- ;
502
- elsif :boolean == type
501
+ ;
502
+ elsif :boolean == type
503
503
 
504
- return true if [ TrueClass, FalseClass ].include? v.class
505
- elsif type.is_a?(Class)
504
+ return true if [ TrueClass, FalseClass ].include? v.class
505
+ elsif type.is_a?(Class)
506
506
 
507
- return true if v.is_a?(type)
508
- elsif type.is_a?(Array)
507
+ return true if v.is_a?(type)
508
+ elsif type.is_a?(Array)
509
509
 
510
- t0 = type[0]
510
+ t0 = type[0]
511
511
 
512
- if t0
512
+ if t0
513
513
 
514
- #return true if v.is_a?
515
- else
514
+ #return true if v.is_a?
515
+ else
516
516
 
517
- # Can be array of anything
517
+ # Can be array of anything
518
518
 
519
- return true if v.is_a?(Array)
520
- end
521
- else
519
+ return true if v.is_a?(Array)
520
+ end
521
+ else
522
522
 
523
- warn "Cannot validate type of '#{v}' (#{v.class}) against type specification '#{type}'"
524
- end
525
- end
523
+ warn "Cannot validate type of '#{v}' (#{v.class}) against type specification '#{type}'"
524
+ end
525
+ end
526
526
 
527
- false
528
- end
527
+ false
528
+ end
529
529
 
530
- def self.lookup_element_(h, types, name, path)
530
+ def self.lookup_element_(h, types, name, path)
531
531
 
532
- if h.has_key?(name)
532
+ if h.has_key?(name)
533
533
 
534
- r = h[name]
534
+ r = h[name]
535
535
 
536
- unless self.check_type_(r, types)
536
+ unless self.check_type_(r, types)
537
537
 
538
- raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
539
- end
538
+ raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
539
+ end
540
540
 
541
- return r
542
- end
541
+ return r
542
+ end
543
543
 
544
- nil
545
- end
544
+ nil
545
+ end
546
546
 
547
- def self.require_element_(h, types, name, path)
547
+ def self.require_element_(h, types, name, path)
548
548
 
549
- unless h.has_key?(name)
549
+ unless h.has_key?(name)
550
550
 
551
- if (path || '').empty?
551
+ if (path || '').empty?
552
552
 
553
- raise ArgumentError, "missing top-level element '#{name}' in load configuration"
554
- else
553
+ raise ArgumentError, "missing top-level element '#{name}' in load configuration"
554
+ else
555
555
 
556
- raise ArgumentError, "missing element '#{path}/#{name}' in load configuration"
557
- end
558
- else
556
+ raise ArgumentError, "missing element '#{path}/#{name}' in load configuration"
557
+ end
558
+ else
559
559
 
560
- r = h[name]
560
+ r = h[name]
561
561
 
562
- unless self.check_type_(r, types)
562
+ unless self.check_type_(r, types)
563
563
 
564
- raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
565
- end
564
+ raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
565
+ end
566
566
 
567
- return r
568
- end
569
- end
567
+ return r
568
+ end
569
+ end
570
570
 
571
- public
572
- def check_required_options_(specifications, options, missing, raise_on_required)
571
+ public
572
+ def check_required_options_(specifications, options, missing, raise_on_required)
573
573
 
574
- required_specifications = specifications.select do |sp|
574
+ required_specifications = specifications.select do |sp|
575
575
 
576
- sp.kind_of?(::CLASP::OptionSpecification) && sp.required?
577
- end
576
+ sp.kind_of?(::CLASP::OptionSpecification) && sp.required?
577
+ end
578
578
 
579
- required_specifications = Hash[required_specifications.map { |sp| [ sp.name, sp ] }]
579
+ required_specifications = Hash[required_specifications.map { |sp| [ sp.name, sp ] }]
580
580
 
581
- given_options = Hash[options.map { |o| [ o.name, o ]}]
581
+ given_options = Hash[options.map { |o| [ o.name, o ]}]
582
582
 
583
- required_specifications.each do |k, sp|
583
+ required_specifications.each do |k, sp|
584
584
 
585
- unless given_options.has_key? k
585
+ unless given_options.has_key? k
586
586
 
587
- message = sp.required_message
587
+ message = sp.required_message
588
588
 
589
- if false
589
+ if false
590
590
 
591
- ;
592
- elsif raise_on_required
591
+ ;
592
+ elsif raise_on_required
593
593
 
594
- if raise_on_required.is_a?(Class)
594
+ if raise_on_required.is_a?(Class)
595
595
 
596
- raise raise_on_required, message
597
- else
596
+ raise raise_on_required, message
597
+ else
598
598
 
599
- raise RuntimeError, message
600
- end
601
- elsif exit_on_missing
599
+ raise RuntimeError, message
600
+ end
601
+ elsif exit_on_missing
602
602
 
603
- self.abort message
604
- else
603
+ self.abort message
604
+ else
605
605
 
606
- if program_name && !program_name.empty?
606
+ if program_name && !program_name.empty?
607
607
 
608
- message = "#{program_name}: #{message}"
609
- end
608
+ message = "#{program_name}: #{message}"
609
+ end
610
610
 
611
- stderr.puts message
612
- end
611
+ stderr.puts message
612
+ end
613
613
 
614
- missing << sp
615
- #results[:missing_option_aliases] << sp
616
- end
617
- end
618
- end
614
+ missing << sp
615
+ #results[:missing_option_aliases] << sp
616
+ end
617
+ end
618
+ end
619
619
 
620
- def check_value_constraints_(values)
620
+ def check_value_constraints_(values)
621
621
 
622
- # now police the values
622
+ # now police the values
623
623
 
624
- values_constraint = constrain_values
625
- values_constraint = values_constraint.begin if ::Range === values_constraint && values_constraint.end == values_constraint.begin
626
- val_names = ::Array === value_names ? value_names : []
624
+ values_constraint = constrain_values
625
+ values_constraint = values_constraint.begin if ::Range === values_constraint && values_constraint.end == values_constraint.begin
626
+ val_names = ::Array === value_names ? value_names : []
627
627
 
628
- case values_constraint
629
- when nil
628
+ case values_constraint
629
+ when nil
630
630
 
631
- ;
632
- when ::Array
631
+ ;
632
+ when ::Array
633
633
 
634
- warn "value of 'constrain_values' attribute, if an #{::Array}, must not be empty and all elements must be of type #{::Integer}" if values_constraint.empty? || !values_constraint.all? { |v| ::Integer === v }
634
+ warn "value of 'constrain_values' attribute, if an #{::Array}, must not be empty and all elements must be of type #{::Integer}" if values_constraint.empty? || !values_constraint.all? { |v| ::Integer === v }
635
635
 
636
- unless values_constraint.include? values.size
636
+ unless values_constraint.include? values.size
637
637
 
638
- message = make_abort_message_("wrong number of values: #{values.size} given, #{values_constraint} required")
638
+ message = make_abort_message_("wrong number of values: #{values.size} given, #{values_constraint} required")
639
639
 
640
- if exit_on_missing
640
+ if exit_on_missing
641
641
 
642
- self.abort message
643
- else
642
+ self.abort message
643
+ else
644
644
 
645
- if program_name && !program_name.empty?
645
+ if program_name && !program_name.empty?
646
646
 
647
- message = "#{program_name}: #{message}"
648
- end
647
+ message = "#{program_name}: #{message}"
648
+ end
649
649
 
650
- stderr.puts message
651
- end
652
- end
653
- when ::Integer
650
+ stderr.puts message
651
+ end
652
+ end
653
+ when ::Integer
654
654
 
655
- unless values.size == values_constraint
655
+ unless values.size == values_constraint
656
656
 
657
- if name = val_names[values.size]
657
+ if name = val_names[values.size]
658
658
 
659
- message = make_abort_message_(name + ' not specified')
660
- else
659
+ message = make_abort_message_(name + ' not specified')
660
+ else
661
661
 
662
- message = make_abort_message_("wrong number of values: #{values.size} given, #{values_constraint} required")
663
- end
662
+ message = make_abort_message_("wrong number of values: #{values.size} given, #{values_constraint} required")
663
+ end
664
664
 
665
- if exit_on_missing
665
+ if exit_on_missing
666
666
 
667
- self.abort message
668
- else
667
+ self.abort message
668
+ else
669
669
 
670
- if program_name && !program_name.empty?
670
+ if program_name && !program_name.empty?
671
671
 
672
- message = "#{program_name}: #{message}"
673
- end
672
+ message = "#{program_name}: #{message}"
673
+ end
674
674
 
675
- stderr.puts message
676
- end
677
- end
678
- when ::Range
675
+ stderr.puts message
676
+ end
677
+ end
678
+ when ::Range
679
679
 
680
- unless values_constraint.include? values.size
680
+ unless values_constraint.include? values.size
681
681
 
682
- if name = val_names[values.size]
682
+ if name = val_names[values.size]
683
683
 
684
- message = make_abort_message_(name + ' not specified')
685
- else
684
+ message = make_abort_message_(name + ' not specified')
685
+ else
686
686
 
687
- message = make_abort_message_("wrong number of values: #{values.size} givens, #{values_constraint.begin} - #{values_constraint.end - (values_constraint.exclude_end? ? 1 : 0)} required")
688
- end
687
+ message = make_abort_message_("wrong number of values: #{values.size} givens, #{values_constraint.begin} - #{values_constraint.end - (values_constraint.exclude_end? ? 1 : 0)} required")
688
+ end
689
689
 
690
- if exit_on_missing
690
+ if exit_on_missing
691
691
 
692
- self.abort message
693
- else
692
+ self.abort message
693
+ else
694
694
 
695
- if program_name && !program_name.empty?
695
+ if program_name && !program_name.empty?
696
696
 
697
- message = "#{program_name}: #{message}"
698
- end
697
+ message = "#{program_name}: #{message}"
698
+ end
699
699
 
700
- stderr.puts message
701
- end
702
- end
703
- else
700
+ stderr.puts message
701
+ end
702
+ end
703
+ else
704
704
 
705
- warn "value of 'constrain_values' attribute - '#{constrain_values}' (#{constrain_values.class}) - of wrong type : must be #{::Array}, #{::Integer}, #{::Range}, or nil"
706
- end
707
- end
708
- #:startdoc:
705
+ warn "value of 'constrain_values' attribute - '#{constrain_values}' (#{constrain_values.class}) - of wrong type : must be #{::Array}, #{::Integer}, #{::Range}, or nil"
706
+ end
707
+ end
708
+ #:startdoc:
709
709
 
710
- public
710
+ public
711
711
 
712
- # Loads an instance of the class, as specified by +source+, according to the given parameters
713
- #
714
- # === Signature
715
- #
716
- # * *Parameters:*
717
- # - +source+:: (+Hash+, +IO+) The arguments specification, either as a Hash or an instance of an IO-implementing type containing a YAML specification
718
- # - +options+:: An options hash, containing any of the following options
719
- #
720
- # * *Options:*
721
- # - +:no_help_flag+ (boolean) Prevents the use of the +CLASP::Flag.Help+ flag-specification
722
- # - +:no_version_flag+ (boolean) Prevents the use of the +CLASP::Flag.Version+ flag-specification
723
- # - +:program_name+ (::String) An explicit program-name, which is inferred from +$0+ if this is +nil+
724
- # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
725
- # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
726
- #
727
- # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
728
- def self.load(source, options = (options_defaulted_ = {}), &blk) # :yields: climate
712
+ # Loads an instance of the class, as specified by +source+, according to the given parameters
713
+ #
714
+ # === Signature
715
+ #
716
+ # * *Parameters:*
717
+ # - +source+:: (+Hash+, +IO+) The arguments specification, either as a Hash or an instance of an IO-implementing type containing a YAML specification
718
+ # - +options+:: An options hash, containing any of the following options
719
+ #
720
+ # * *Options:*
721
+ # - +:no_help_flag+ (boolean) Prevents the use of the +CLASP::Flag.Help+ flag-specification
722
+ # - +:no_version_flag+ (boolean) Prevents the use of the +CLASP::Flag.Version+ flag-specification
723
+ # - +:program_name+ (::String) An explicit program-name, which is inferred from +$0+ if this is +nil+
724
+ # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
725
+ # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
726
+ #
727
+ # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
728
+ def self.load(source, options = (options_defaulted_ = {}), &blk) # :yields: climate
729
729
 
730
- check_parameter options, 'options', allow_nil: true, type: ::Hash
730
+ check_parameter options, 'options', allow_nil: true, type: ::Hash
731
731
 
732
- options ||= {}
732
+ options ||= {}
733
733
 
734
- h = nil
734
+ h = nil
735
735
 
736
- case source
737
- when ::IO
736
+ case source
737
+ when ::IO
738
738
 
739
- h = YAML.load source.read
740
- when ::Hash
739
+ h = YAML.load source.read
740
+ when ::Hash
741
741
 
742
- h = source
743
- else
742
+ h = source
743
+ else
744
744
 
745
- if source.respond_to?(:to_hash)
745
+ if source.respond_to?(:to_hash)
746
746
 
747
- h = source.to_hash
748
- else
747
+ h = source.to_hash
748
+ else
749
749
 
750
- raise TypeError, "#{self}.#{__method__}() 'source' argument must be a #{::Hash}, or an object implementing #{::IO}, or a type implementing 'to_hash'"
751
- end
752
- end
750
+ raise TypeError, "#{self}.#{__method__}() 'source' argument must be a #{::Hash}, or an object implementing #{::IO}, or a type implementing 'to_hash'"
751
+ end
752
+ end
753
753
 
754
- _libclimate = require_element_(h, Hash, 'libclimate', nil)
755
- _exit_on_missing = lookup_element_(_libclimate, :boolean, 'exit_on_missing', 'libclimate')
756
- _ignore_unknown = lookup_element_(_libclimate, :boolean, 'ignore_unknown', 'libclimate')
757
- _exit_on_unknown = lookup_element_(_libclimate, :boolean, 'exit_on_unknown', 'libclimate')
758
- _exit_on_usage = lookup_element_(_libclimate, :boolean, 'exit_on_usage', 'libclimate')
759
- _info_lines = lookup_element_(_libclimate, Array, 'info_lines', 'libclimate')
760
- _program_name = lookup_element_(_libclimate, String, 'program_name', 'libclimate')
761
- _constrain_values = lookup_element_(_libclimate, [ Integer, Range ], 'constrain_values', 'libclimate')
762
- _flags_and_options = lookup_element_(_libclimate, String, 'flags_and_options', 'libclimate')
763
- _usage_values = lookup_element_(_libclimate, String, 'usage_values', 'libclimate')
764
- _value_names = lookup_element_(_libclimate, Array, 'value_names', 'libclimate')
765
- _version = lookup_element_(_libclimate, [ String, [] ], 'version', 'libclimate')
754
+ _libclimate = require_element_(h, Hash, 'libclimate', nil)
755
+ _exit_on_missing = lookup_element_(_libclimate, :boolean, 'exit_on_missing', 'libclimate')
756
+ _ignore_unknown = lookup_element_(_libclimate, :boolean, 'ignore_unknown', 'libclimate')
757
+ _exit_on_unknown = lookup_element_(_libclimate, :boolean, 'exit_on_unknown', 'libclimate')
758
+ _exit_on_usage = lookup_element_(_libclimate, :boolean, 'exit_on_usage', 'libclimate')
759
+ _info_lines = lookup_element_(_libclimate, Array, 'info_lines', 'libclimate')
760
+ _program_name = lookup_element_(_libclimate, String, 'program_name', 'libclimate')
761
+ _constrain_values = lookup_element_(_libclimate, [ Integer, Range ], 'constrain_values', 'libclimate')
762
+ _flags_and_options = lookup_element_(_libclimate, String, 'flags_and_options', 'libclimate')
763
+ _usage_values = lookup_element_(_libclimate, String, 'usage_values', 'libclimate')
764
+ _value_names = lookup_element_(_libclimate, Array, 'value_names', 'libclimate')
765
+ _version = lookup_element_(_libclimate, [ String, [] ], 'version', 'libclimate')
766
766
 
767
- specs = CLASP::Arguments.load_specifications _libclimate, options
767
+ specs = CLASP::Arguments.load_specifications _libclimate, options
768
768
 
769
- cl = Climate.new(options.merge(Climate_Constants_::GIVEN_SPECS_ => specs), &blk)
769
+ cl = Climate.new(options.merge(Climate_Constants_::GIVEN_SPECS_ => specs), &blk)
770
770
 
771
- cl.exit_on_missing = _exit_on_missing unless _exit_on_missing.nil?
772
- cl.ignore_unknown = _ignore_unknown unless _ignore_unknown.nil?
773
- cl.exit_on_unknown = _exit_on_unknown unless _exit_on_unknown.nil?
774
- cl.exit_on_usage = _exit_on_usage unless _exit_on_usage.nil?
775
- cl.info_lines = _info_lines unless _info_lines.nil?
776
- cl.program_name = _program_name unless _program_name.nil?
777
- cl.constrain_values = _constrain_values unless _constrain_values.nil?
778
- cl.flags_and_options = _flags_and_options unless _flags_and_options.nil?
779
- cl.usage_values = _usage_values unless _usage_values.nil?
780
- cl.value_names = _value_names unless _value_names.nil?
781
- cl.version = _version unless _version.nil?
771
+ cl.exit_on_missing = _exit_on_missing unless _exit_on_missing.nil?
772
+ cl.ignore_unknown = _ignore_unknown unless _ignore_unknown.nil?
773
+ cl.exit_on_unknown = _exit_on_unknown unless _exit_on_unknown.nil?
774
+ cl.exit_on_usage = _exit_on_usage unless _exit_on_usage.nil?
775
+ cl.info_lines = _info_lines unless _info_lines.nil?
776
+ cl.program_name = _program_name unless _program_name.nil?
777
+ cl.constrain_values = _constrain_values unless _constrain_values.nil?
778
+ cl.flags_and_options = _flags_and_options unless _flags_and_options.nil?
779
+ cl.usage_values = _usage_values unless _usage_values.nil?
780
+ cl.value_names = _value_names unless _value_names.nil?
781
+ cl.version = _version unless _version.nil?
782
782
 
783
- cl
784
- end
783
+ cl
784
+ end
785
785
 
786
- # Creates an instance of the Climate class.
787
- #
788
- # === Signature
789
- #
790
- # * *Parameters:*
791
- # - +options:+ (Hash) An options hash, containing any of the following options.
792
- #
793
- # * *Options:*
794
- # - +:no_help_flag+ (boolean) Prevents the use of the +CLASP::Flag.Help+ flag-specification
795
- # - +:no_version_flag+ (boolean) Prevents the use of the +CLASP::Flag.Version+ flag-specification
796
- # - +:program_name+ (::String) An explicit program-name, which is inferred from +$0+ if this is +nil+
797
- # - +:value_attributes+ (boolean) Causes any possible value-names, as described in `#value_names`, to be applied as attributes with the given values, if any, on the command-line
798
- # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
799
- # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
800
- #
801
- # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
802
- def initialize(options={}, &blk) # :yields: climate
803
-
804
- check_parameter options, 'options', allow_nil: true, type: ::Hash
805
-
806
- options ||= {}
807
-
808
- check_option options, :no_help_flag, type: :boolean, allow_nil: true
809
- check_option options, :no_version_flag, type: :boolean, allow_nil: true
810
- check_option options, :program_name, type: ::String, allow_nil: true
811
-
812
- pr_name = options[:program_name]
813
-
814
- unless pr_name
815
-
816
- pr_name = File.basename($0)
817
- pr_name = (pr_name =~ /\.(?:bat|cmd|rb|sh)$/) ? "#$`(#$&)" : pr_name
818
- end
819
-
820
- given_specs = options[Climate_Constants_::GIVEN_SPECS_]
821
-
822
- @specifications = []
823
- @ignore_unknown = false
824
- @exit_on_unknown = true
825
- @exit_on_missing = true
826
- @exit_on_usage = true
827
- @info_lines = nil
828
- set_program_name pr_name
829
- @stdout = $stdout
830
- @stderr = $stderr
831
- @constrain_values = nil
832
- @flags_and_options = flags_and_options
833
- @usage_help_suffix = 'use --help for usage'
834
- @usage_values = usage_values
835
- @value_names = []
836
- version_context = options[:version_context]
837
- @version = options[:version] || infer_version_(version_context)
838
-
839
- @value_attributes = options[:value_attributes]
840
-
841
- unless options[:no_help_flag]
842
-
843
- f = CLASP::Flag.Help()
844
-
845
- unless f.respond_to?(:action)
846
-
847
- class << f
848
-
849
- attr_accessor :action
850
- end
851
- end
852
-
853
- f.action = Proc.new { show_usage_ }
854
-
855
- @specifications << f
856
- end
857
-
858
- unless options[:no_version_flag]
859
-
860
- f = CLASP::Flag.Version()
861
-
862
- unless f.respond_to?(:action)
863
-
864
- class << f
865
-
866
- attr_accessor :action
867
- end
868
- end
869
-
870
- f.action = Proc.new { show_version_ }
871
-
872
- @specifications << f
873
- end
874
-
875
- @specifications = @specifications + given_specs if given_specs
876
-
877
- yield self if block_given?
878
- end
879
-
880
- # [DEPRECATED] This method is now deprecated. Instead use +program_name=+
881
- def set_program_name(name)
882
-
883
- @program_name = name
884
- end
885
-
886
- # ([CLASP::Specification]) An array of specifications attached to the climate instance, whose contents should be modified by adding (or removing) CLASP specifications
887
- attr_reader :specifications
888
- # [DEPRECATED] Instead, use +specifications+
889
- def aliases; specifications; end
890
- # (boolean) Indicates whether exit will be called (with non-zero exit code) when a required command-line option is missing. Defaults to +true+
891
- attr_accessor :exit_on_missing
892
- # (boolean) Indicates whether unknown flags or options will be ignored. This overrides +:exit_on_unknown+. Defaults to +false+
893
- attr_accessor :ignore_unknown
894
- # (boolean) Indicates whether exit will be called (with non-zero exit code) when an unknown command-line flag or option is encountered. Defaults to +true+
895
- attr_accessor :exit_on_unknown
896
- # (boolean) Indicates whether exit will be called (with zero exit code) when usage/version is requested on the command-line. Defaults to +true+
897
- attr_accessor :exit_on_usage
898
- # ([String]) Optional array of string of program-information that will be written before the rest of the usage block when usage is requested on the command-line
899
- attr_accessor :info_lines
900
- # (String) A program name; defaults to the name of the executing script
901
- def program_name
902
-
903
- name = @program_name
904
-
905
- if defined?(Colcon) && @stdout.tty?
906
-
907
- name = "#{::Colcon::Decorations::Bold}#{name}#{::Colcon::Decorations::Unbold}"
908
- end
909
-
910
- name
911
- end
912
- # Sets the +program_name+ attribute
913
- attr_writer :program_name
914
- # @return (::IO) The output stream for normative output; defaults to $stdout
915
- attr_accessor :stdout
916
- # @return (::IO) The output stream for contingent output; defaults to $stderr
917
- attr_accessor :stderr
918
- # (Integer, Range) Optional constraint on the values that must be provided to the program
919
- attr_accessor :constrain_values
920
- # (String) Optional string to describe the flags and options section. Defaults to "[ +...+ +flags+ +and+ +options+ +...+ ]"
921
- attr_accessor :flags_and_options
922
- # (String) The string that is appended to #abort calls made during #run. Defaults to "use --help for usage"
923
- attr_accessor :usage_help_suffix
924
- # @return (::String) Optional string to describe the program values, eg \<xyz "[ { <<directory> | &lt;file> } ]"
925
- attr_accessor :usage_values
926
- # ([String]) Zero-based array of names for values to be used when that value is not present (according to the +:constrain_values+ attribute)
927
- attr_accessor :value_names
928
- # (String, [String], [Integer]) A version string or an array of integers/strings representing the version component(s)
929
- attr_accessor :version
930
-
931
- # Parse the given command-line (passed as +argv+) by the given instance
932
- #
933
- # === Signature
934
- #
935
- # * *Parameters:*
936
- # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
937
- #
938
- # === Returns
939
- # (ParseResults) Results
940
- def parse(argv = ARGV, **options) # :yields: ParseResults
941
-
942
- raise ArgumentError, "argv may not be nil" if argv.nil?
943
-
944
- arguments = CLASP::Arguments.new argv, specifications
945
-
946
- ParseResults.new(self, arguments, argv)
947
- end
948
-
949
- # Parse the given command-line (passed as +argv+) by the given instance,
950
- # and verifies it
951
- #
952
- # === Signature
953
- #
954
- # * *Parameters:*
955
- # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
956
- # - +options+ (Hash) Options
957
- #
958
- # * *Options:*
959
- # - +:raise_on_required+ (boolean, Exception) Causes an/the given exception to be raised if any required options are not specified in the command-line
960
- # - +:raise_on_unrecognised+ (boolean, Exception) Causes an/the given exception to be raised if any unrecognised flags/options are specified in the command-line
961
- # - +:raise_on_unused+ (boolean, Exception) Causes an/the given exception to be raised if any given flags/options are not used
962
- # - +:raise+ (boolean, Exception) Causes an/the given exception to be raised in all conditions
963
- #
964
- # === Returns
965
- # (ParseResults) Results
966
- def parse_and_verify(argv = ARGV, **options) # :yields: ParseResults
967
-
968
- r = parse argv, **options
969
-
970
- r.verify(**options)
971
-
972
- r
973
- end
974
-
975
- # [DEPRECATED] Use +Climate#parse_and_verify()+ (but be aware that the
976
- # returned result is of a different type
977
- #
978
- # === Signature
979
- #
980
- # * *Parameters:*
981
- # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
982
- #
983
- # === Returns
984
- # an instance of a type derived from +::Hash+ with the additional
985
- # attributes +flags+, +options+, +values+, +double_slash_index+ and
986
- # +argv+.
987
- def run(argv = ARGV, **options) # :yields: customised +::Hash+
786
+ # Creates an instance of the Climate class.
787
+ #
788
+ # === Signature
789
+ #
790
+ # * *Parameters:*
791
+ # - +options:+ (Hash) An options hash, containing any of the following options.
792
+ #
793
+ # * *Options:*
794
+ # - +:no_help_flag+ (boolean) Prevents the use of the +CLASP::Flag.Help+ flag-specification
795
+ # - +:no_version_flag+ (boolean) Prevents the use of the +CLASP::Flag.Version+ flag-specification
796
+ # - +:program_name+ (::String) An explicit program-name, which is inferred from +$0+ if this is +nil+
797
+ # - +:value_attributes+ (boolean) Causes any possible value-names, as described in `#value_names`, to be applied as attributes with the given values, if any, on the command-line
798
+ # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
799
+ # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
800
+ #
801
+ # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
802
+ def initialize(options={}, &blk) # :yields: climate
803
+
804
+ check_parameter options, 'options', allow_nil: true, type: ::Hash
805
+
806
+ options ||= {}
807
+
808
+ check_option options, :no_help_flag, type: :boolean, allow_nil: true
809
+ check_option options, :no_version_flag, type: :boolean, allow_nil: true
810
+ check_option options, :program_name, type: ::String, allow_nil: true
811
+
812
+ pr_name = options[:program_name]
813
+
814
+ unless pr_name
815
+
816
+ pr_name = File.basename($0)
817
+ pr_name = (pr_name =~ /\.(?:bat|cmd|rb|sh)$/) ? "#$`(#$&)" : pr_name
818
+ end
819
+
820
+ given_specs = options[Climate_Constants_::GIVEN_SPECS_]
821
+
822
+ @specifications = []
823
+ @ignore_unknown = false
824
+ @exit_on_unknown = true
825
+ @exit_on_missing = true
826
+ @exit_on_usage = true
827
+ @info_lines = nil
828
+ set_program_name pr_name
829
+ @stdout = $stdout
830
+ @stderr = $stderr
831
+ @constrain_values = nil
832
+ @flags_and_options = flags_and_options
833
+ @usage_help_suffix = 'use --help for usage'
834
+ @usage_values = usage_values
835
+ @value_names = []
836
+ version_context = options[:version_context]
837
+ @version = options[:version] || infer_version_(version_context)
838
+
839
+ @value_attributes = options[:value_attributes]
840
+
841
+ unless options[:no_help_flag]
842
+
843
+ f = CLASP::Flag.Help()
844
+
845
+ unless f.respond_to?(:action)
846
+
847
+ class << f
848
+
849
+ attr_accessor :action
850
+ end
851
+ end
852
+
853
+ f.action = Proc.new { show_usage_ }
854
+
855
+ @specifications << f
856
+ end
857
+
858
+ unless options[:no_version_flag]
859
+
860
+ f = CLASP::Flag.Version()
861
+
862
+ unless f.respond_to?(:action)
863
+
864
+ class << f
865
+
866
+ attr_accessor :action
867
+ end
868
+ end
869
+
870
+ f.action = Proc.new { show_version_ }
871
+
872
+ @specifications << f
873
+ end
874
+
875
+ @specifications = @specifications + given_specs if given_specs
876
+
877
+ yield self if block_given?
878
+ end
879
+
880
+ # [DEPRECATED] This method is now deprecated. Instead use +program_name=+
881
+ def set_program_name(name)
882
+
883
+ @program_name = name
884
+ end
885
+
886
+ # ([CLASP::Specification]) An array of specifications attached to the climate instance, whose contents should be modified by adding (or removing) CLASP specifications
887
+ attr_reader :specifications
888
+ # [DEPRECATED] Instead, use +specifications+
889
+ def aliases; specifications; end
890
+ # (boolean) Indicates whether exit will be called (with non-zero exit code) when a required command-line option is missing. Defaults to +true+
891
+ attr_accessor :exit_on_missing
892
+ # (boolean) Indicates whether unknown flags or options will be ignored. This overrides +:exit_on_unknown+. Defaults to +false+
893
+ attr_accessor :ignore_unknown
894
+ # (boolean) Indicates whether exit will be called (with non-zero exit code) when an unknown command-line flag or option is encountered. Defaults to +true+
895
+ attr_accessor :exit_on_unknown
896
+ # (boolean) Indicates whether exit will be called (with zero exit code) when usage/version is requested on the command-line. Defaults to +true+
897
+ attr_accessor :exit_on_usage
898
+ # ([String]) Optional array of string of program-information that will be written before the rest of the usage block when usage is requested on the command-line
899
+ attr_accessor :info_lines
900
+ # (String) A program name; defaults to the name of the executing script
901
+ def program_name
902
+
903
+ name = @program_name
904
+
905
+ if defined?(Colcon) && @stdout.tty?
906
+
907
+ name = "#{::Colcon::Decorations::Bold}#{name}#{::Colcon::Decorations::Unbold}"
908
+ end
909
+
910
+ name
911
+ end
912
+ # Sets the +program_name+ attribute
913
+ attr_writer :program_name
914
+ # @return (::IO) The output stream for normative output; defaults to $stdout
915
+ attr_accessor :stdout
916
+ # @return (::IO) The output stream for contingent output; defaults to $stderr
917
+ attr_accessor :stderr
918
+ # (Integer, Range) Optional constraint on the values that must be provided to the program
919
+ attr_accessor :constrain_values
920
+ # (String) Optional string to describe the flags and options section. Defaults to "[ +...+ +flags+ +and+ +options+ +...+ ]"
921
+ attr_accessor :flags_and_options
922
+ # (String) The string that is appended to #abort calls made during #run. Defaults to "use --help for usage"
923
+ attr_accessor :usage_help_suffix
924
+ # @return (::String) Optional string to describe the program values, eg \<xyz "[ { <<directory> | &lt;file> } ]"
925
+ attr_accessor :usage_values
926
+ # ([String]) Zero-based array of names for values to be used when that value is not present (according to the +:constrain_values+ attribute)
927
+ attr_accessor :value_names
928
+ # (String, [String], [Integer]) A version string or an array of integers/strings representing the version component(s)
929
+ attr_accessor :version
930
+
931
+ # Parse the given command-line (passed as +argv+) by the given instance
932
+ #
933
+ # === Signature
934
+ #
935
+ # * *Parameters:*
936
+ # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
937
+ #
938
+ # === Returns
939
+ # (ParseResults) Results
940
+ def parse(argv = ARGV, **options) # :yields: ParseResults
941
+
942
+ raise ArgumentError, "argv may not be nil" if argv.nil?
943
+
944
+ arguments = CLASP::Arguments.new argv, specifications
945
+
946
+ ParseResults.new(self, arguments, argv)
947
+ end
948
+
949
+ # Parse the given command-line (passed as +argv+) by the given instance,
950
+ # and verifies it
951
+ #
952
+ # === Signature
953
+ #
954
+ # * *Parameters:*
955
+ # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
956
+ # - +options+ (Hash) Options
957
+ #
958
+ # * *Options:*
959
+ # - +:raise_on_required+ (boolean, Exception) Causes an/the given exception to be raised if any required options are not specified in the command-line
960
+ # - +:raise_on_unrecognised+ (boolean, Exception) Causes an/the given exception to be raised if any unrecognised flags/options are specified in the command-line
961
+ # - +:raise_on_unused+ (boolean, Exception) Causes an/the given exception to be raised if any given flags/options are not used
962
+ # - +:raise+ (boolean, Exception) Causes an/the given exception to be raised in all conditions
963
+ #
964
+ # === Returns
965
+ # (ParseResults) Results
966
+ def parse_and_verify(argv = ARGV, **options) # :yields: ParseResults
967
+
968
+ r = parse argv, **options
969
+
970
+ r.verify(**options)
971
+
972
+ r
973
+ end
974
+
975
+ # [DEPRECATED] Use +Climate#parse_and_verify()+ (but be aware that the
976
+ # returned result is of a different type
977
+ #
978
+ # === Signature
979
+ #
980
+ # * *Parameters:*
981
+ # - +argv+ ([String]) The array of arguments; defaults to <tt>ARGV</tt>
982
+ #
983
+ # === Returns
984
+ # an instance of a type derived from +::Hash+ with the additional
985
+ # attributes +flags+, +options+, +values+, +double_slash_index+ and
986
+ # +argv+.
987
+ def run(argv = ARGV, **options) # :yields: customised +::Hash+
988
988
 
989
- raise ArgumentError, "argv may not be nil" if argv.nil?
989
+ raise ArgumentError, "argv may not be nil" if argv.nil?
990
990
 
991
- arguments = CLASP::Arguments.new argv, specifications
991
+ arguments = CLASP::Arguments.new argv, specifications
992
992
 
993
- run_ argv, arguments, **options
994
- end
993
+ run_ argv, arguments, **options
994
+ end
995
995
 
996
- private
997
- def run_(argv, arguments, **opts) # :nodoc:
996
+ private
997
+ def run_(argv, arguments, **opts) # :nodoc:
998
998
 
999
- flags = arguments.flags
1000
- options = arguments.options
1001
- values = arguments.values.to_a
999
+ flags = arguments.flags
1000
+ options = arguments.options
1001
+ values = arguments.values.to_a
1002
1002
 
1003
- double_slash_index = arguments.double_slash_index
1003
+ double_slash_index = arguments.double_slash_index
1004
1004
 
1005
- results = {
1005
+ results = {
1006
1006
 
1007
- flags: {
1007
+ flags: {
1008
1008
 
1009
- given: flags,
1010
- handled: [],
1011
- unhandled: [],
1012
- unknown: [],
1013
- },
1009
+ given: flags,
1010
+ handled: [],
1011
+ unhandled: [],
1012
+ unknown: [],
1013
+ },
1014
1014
 
1015
- options: {
1015
+ options: {
1016
1016
 
1017
- given: options,
1018
- handled: [],
1019
- unhandled: [],
1020
- unknown: [],
1021
- },
1017
+ given: options,
1018
+ handled: [],
1019
+ unhandled: [],
1020
+ unknown: [],
1021
+ },
1022
1022
 
1023
- values: values,
1023
+ values: values,
1024
1024
 
1025
- missing_option_aliases: [],
1026
- }
1025
+ missing_option_aliases: [],
1026
+ }
1027
1027
 
1028
- # Verification:
1029
- #
1030
- # 1. Check arguments recognised
1031
- # 1.a Flags
1032
- # 1.b Options
1033
- # 2. police any required options
1034
- # 3. Check values
1028
+ # Verification:
1029
+ #
1030
+ # 1. Check arguments recognised
1031
+ # 1.a Flags
1032
+ # 1.b Options
1033
+ # 2. police any required options
1034
+ # 3. Check values
1035
1035
 
1036
- # 1.a Flags
1036
+ # 1.a Flags
1037
1037
 
1038
- flags.each do |f|
1038
+ flags.each do |f|
1039
1039
 
1040
- spec = specifications.detect do |sp|
1040
+ spec = specifications.detect do |sp|
1041
1041
 
1042
- sp.kind_of?(::CLASP::FlagSpecification) && f.name == sp.name
1043
- end
1042
+ sp.kind_of?(::CLASP::FlagSpecification) && f.name == sp.name
1043
+ end
1044
1044
 
1045
- if spec
1045
+ if spec
1046
1046
 
1047
- selector = :unhandled
1047
+ selector = :unhandled
1048
1048
 
1049
- if spec.respond_to?(:action) && !spec.action.nil?
1049
+ if spec.respond_to?(:action) && !spec.action.nil?
1050
1050
 
1051
- spec.action.call(f, spec)
1051
+ spec.action.call(f, spec)
1052
1052
 
1053
- selector = :handled
1054
- end
1053
+ selector = :handled
1054
+ end
1055
1055
 
1056
- results[:flags][selector] << f
1057
- else
1056
+ results[:flags][selector] << f
1057
+ else
1058
1058
 
1059
- message = make_abort_message_("unrecognised flag '#{f}'")
1059
+ message = make_abort_message_("unrecognised flag '#{f}'")
1060
1060
 
1061
- if false
1061
+ if false
1062
1062
 
1063
- elsif ignore_unknown
1063
+ elsif ignore_unknown
1064
1064
 
1065
- ;
1066
- elsif exit_on_unknown
1065
+ ;
1066
+ elsif exit_on_unknown
1067
1067
 
1068
- self.abort message
1069
- else
1068
+ self.abort message
1069
+ else
1070
1070
 
1071
- if program_name && !program_name.empty?
1071
+ if program_name && !program_name.empty?
1072
1072
 
1073
- message = "#{program_name}: #{message}"
1074
- end
1073
+ message = "#{program_name}: #{message}"
1074
+ end
1075
1075
 
1076
- stderr.puts message
1077
- end
1076
+ stderr.puts message
1077
+ end
1078
1078
 
1079
- results[:flags][:unknown] << f
1080
- end
1081
- end
1079
+ results[:flags][:unknown] << f
1080
+ end
1081
+ end
1082
1082
 
1083
- # 1.b Options
1083
+ # 1.b Options
1084
1084
 
1085
- options.each do |o|
1085
+ options.each do |o|
1086
1086
 
1087
- spec = specifications.detect do |sp|
1087
+ spec = specifications.detect do |sp|
1088
1088
 
1089
- sp.kind_of?(::CLASP::OptionSpecification) && o.name == sp.name
1090
- end
1089
+ sp.kind_of?(::CLASP::OptionSpecification) && o.name == sp.name
1090
+ end
1091
1091
 
1092
- if spec
1092
+ if spec
1093
1093
 
1094
- selector = :unhandled
1094
+ selector = :unhandled
1095
1095
 
1096
- if spec.respond_to?(:action) && !spec.action.nil?
1096
+ if spec.respond_to?(:action) && !spec.action.nil?
1097
1097
 
1098
- spec.action.call(o, spec)
1098
+ spec.action.call(o, spec)
1099
1099
 
1100
- selector = :handled
1101
- end
1100
+ selector = :handled
1101
+ end
1102
1102
 
1103
- results[:options][selector] << o
1104
- else
1103
+ results[:options][selector] << o
1104
+ else
1105
1105
 
1106
- message = make_abort_message_("unrecognised option '#{o}'")
1106
+ message = make_abort_message_("unrecognised option '#{o}'")
1107
1107
 
1108
- if false
1108
+ if false
1109
1109
 
1110
- elsif ignore_unknown
1110
+ elsif ignore_unknown
1111
1111
 
1112
- ;
1113
- elsif exit_on_unknown
1112
+ ;
1113
+ elsif exit_on_unknown
1114
1114
 
1115
- self.abort message
1116
- else
1115
+ self.abort message
1116
+ else
1117
1117
 
1118
- if program_name && !program_name.empty?
1118
+ if program_name && !program_name.empty?
1119
1119
 
1120
- message = "#{program_name}: #{message}"
1121
- end
1120
+ message = "#{program_name}: #{message}"
1121
+ end
1122
1122
 
1123
- stderr.puts message
1124
- end
1123
+ stderr.puts message
1124
+ end
1125
1125
 
1126
- results[:options][:unknown] << o
1127
- end
1128
- end
1126
+ results[:options][:unknown] << o
1127
+ end
1128
+ end
1129
1129
 
1130
- # 2. police any required options
1130
+ # 2. police any required options
1131
1131
 
1132
- check_required_options_(specifications, results[:options][:given], results[:missing_option_aliases], false)
1132
+ check_required_options_(specifications, results[:options][:given], results[:missing_option_aliases], false)
1133
1133
 
1134
- # 3. Check values
1134
+ # 3. Check values
1135
1135
 
1136
- check_value_constraints_(values)
1136
+ check_value_constraints_(values)
1137
1137
 
1138
1138
 
1139
1139
 
1140
- def results.flags
1140
+ def results.flags
1141
1141
 
1142
- self[:flags]
1143
- end
1142
+ self[:flags]
1143
+ end
1144
1144
 
1145
- def results.options
1145
+ def results.options
1146
1146
 
1147
- self[:options]
1148
- end
1147
+ self[:options]
1148
+ end
1149
1149
 
1150
- def results.values
1150
+ def results.values
1151
1151
 
1152
- self[:values]
1153
- end
1152
+ self[:values]
1153
+ end
1154
1154
 
1155
- results.define_singleton_method(:double_slash_index) do
1155
+ results.define_singleton_method(:double_slash_index) do
1156
1156
 
1157
- double_slash_index
1158
- end
1157
+ double_slash_index
1158
+ end
1159
1159
 
1160
- results.define_singleton_method(:argv) do
1160
+ results.define_singleton_method(:argv) do
1161
1161
 
1162
- argv
1163
- end
1162
+ argv
1163
+ end
1164
1164
 
1165
1165
 
1166
- if opts[:value_attributes] || @value_attributes
1166
+ if opts[:value_attributes] || @value_attributes
1167
1167
 
1168
- (value_names || []).each_with_index do |name, index|
1168
+ (value_names || []).each_with_index do |name, index|
1169
1169
 
1170
- name = name.gsub(/-/, '_').to_sym
1170
+ name = name.gsub(/-/, '_').to_sym
1171
1171
 
1172
- if results.respond_to? name
1172
+ if results.respond_to? name
1173
1173
 
1174
- warn "cannot create attribute `#{name}` on instance of `#{results.class}` because that name is already used"
1175
- else
1174
+ warn "cannot create attribute `#{name}` on instance of `#{results.class}` because that name is already used"
1175
+ else
1176
1176
 
1177
- value = results.values[index]
1177
+ value = results.values[index]
1178
1178
 
1179
- results.define_singleton_method(name) do
1179
+ results.define_singleton_method(name) do
1180
1180
 
1181
- value
1182
- end
1183
- end
1184
- end
1185
- end
1181
+ value
1182
+ end
1183
+ end
1184
+ end
1185
+ end
1186
1186
 
1187
1187
 
1188
- results.freeze
1188
+ results.freeze
1189
1189
 
1190
- results
1191
- end
1192
- public
1190
+ results
1191
+ end
1192
+ public
1193
1193
 
1194
- # Calls abort() with the given message prefixed by the program_name
1195
- #
1196
- # === Signature
1197
- #
1198
- # * *Parameters:*
1199
- # - +message+ (String) The message string
1200
- # - +options+ (Hash) An option hash, containing any of the following options
1201
- #
1202
- # * *Options:*
1203
- # - +:stream+ {optional} The output stream to use. Defaults to the value of the attribute +stderr+
1204
- # - +:program_name+ (String) {optional} Uses the given value rather than the +program_name+ attribute; does not prefix if the empty string
1205
- # - +:exit+ {optional} The exit code. Defaults to 1. Does not exit if +nil+ specified explicitly
1206
- #
1207
- # === Returns
1208
- # The combined message string, if <tt>exit()</tt> not called.
1209
- def abort(message, options={})
1194
+ # Calls abort() with the given message prefixed by the program_name
1195
+ #
1196
+ # === Signature
1197
+ #
1198
+ # * *Parameters:*
1199
+ # - +message+ (String) The message string
1200
+ # - +options+ (Hash) An option hash, containing any of the following options
1201
+ #
1202
+ # * *Options:*
1203
+ # - +:stream+ {optional} The output stream to use. Defaults to the value of the attribute +stderr+
1204
+ # - +:program_name+ (String) {optional} Uses the given value rather than the +program_name+ attribute; does not prefix if the empty string
1205
+ # - +:exit+ {optional} The exit code. Defaults to 1. Does not exit if +nil+ specified explicitly
1206
+ #
1207
+ # === Returns
1208
+ # The combined message string, if <tt>exit()</tt> not called.
1209
+ def abort(message, options={})
1210
1210
 
1211
- prog_name = options[:program_name]
1212
- prog_name ||= program_name
1213
- prog_name ||= ''
1211
+ prog_name = options[:program_name]
1212
+ prog_name ||= program_name
1213
+ prog_name ||= ''
1214
1214
 
1215
- stream = options[:stream]
1216
- stream ||= stderr
1217
- stream ||= $stderr
1215
+ stream = options[:stream]
1216
+ stream ||= stderr
1217
+ stream ||= $stderr
1218
1218
 
1219
- exit_code = options.has_key?(:exit) ? options[:exit] : 1
1219
+ exit_code = options.has_key?(:exit) ? options[:exit] : 1
1220
1220
 
1221
- if prog_name.empty?
1221
+ if prog_name.empty?
1222
1222
 
1223
- msg = message
1224
- else
1223
+ msg = message
1224
+ else
1225
1225
 
1226
- msg = "#{prog_name}: #{message}"
1227
- end
1226
+ msg = "#{prog_name}: #{message}"
1227
+ end
1228
1228
 
1229
1229
 
1230
- stream.puts msg
1231
-
1232
- exit(exit_code) if exit_code
1233
-
1234
- msg
1235
- end
1236
-
1237
- # Adds a flag to +specifications+
1238
- #
1239
- # === Signature
1240
- #
1241
- # * *Parameters:*
1242
- # - +name_or_flag+ (String, ::CLASP::FlagSpecification) The flag name or instance of CLASP::FlagSpecification
1243
- # - +options+ (Hash) An options hash, containing any of the following options
1244
- #
1245
- # * *Options:*
1246
- # - +:alias+ (String) A single alias
1247
- # - +:aliases+ ([String]) An array of aliases
1248
- # - +:help+ (String) Description string used when writing response to "+--help+" flag
1249
- # - +:required+ (boolean) Indicates whether the flag is required, causing #run to fail with appropriate message if the flag is not specified in the command-line arguments
1250
- #
1251
- # * *Block* An optional block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
1252
- #
1253
- # === Examples
1254
- #
1255
- # ==== Specification(s) of a flag (single statement)
1256
- #
1257
- def add_flag(name_or_flag, options={}, &blk)
1258
-
1259
- check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
1260
-
1261
- if ::CLASP::FlagSpecification === name_or_flag
1262
-
1263
- specifications << name_or_flag
1264
- else
1265
-
1266
- specifications << CLASP.Flag(name_or_flag, **options, &blk)
1267
- end
1268
- end
1269
-
1270
- # Adds an option to +specifications+
1271
- #
1272
- # === Signature
1273
- #
1274
- # * *Parameters:*
1275
- # - +name_or_option+ (String, CLASP::OptionSpecification) The option name or instance of CLASP::OptionSpecification
1276
- # - +options+ (Hash) An options hash, containing any of the following options
1277
- #
1278
- # * *Options:*
1279
- # - +:alias+ (String) A single alias
1280
- # - +:aliases+ ([String]) An array of aliases
1281
- # - +:help+ (String) Description string used when writing response to "+--help+" flag
1282
- # - +:values_range+ ([String]) An array of strings representing the valid/expected values used when writing response to "+--help+" flag. NOTE: the current version does not validate against these values, but a future version may do so
1283
- # - +:default_value+ (String) The default version used when, say, for the option +--my-opt+ the command-line contain the argument "+--my-opt=+"
1284
- #
1285
- # * *Block* An optional block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
1286
- #
1287
- def add_option(name_or_option, options={}, &blk)
1288
-
1289
- check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
1290
-
1291
- if ::CLASP::OptionSpecification === name_or_option
1292
-
1293
- specifications << name_or_option
1294
- else
1295
-
1296
- specifications << CLASP.Option(name_or_option, **options, &blk)
1297
- end
1298
- end
1299
-
1300
- # Adds an alias to +specifications+
1301
- #
1302
- # === Signature
1303
- #
1304
- # * *Parameters:*
1305
- # - +name_or_specification+ (String) The flag/option name or the valued option
1306
- # - +aliases+ (*[String]) One or more aliases
1307
- #
1308
- # === Examples
1309
- #
1310
- # ==== Specification(s) of a flag (single statement)
1311
- #
1312
- # climate.add_flag('--mark-missing', alias: '-x')
1313
- #
1314
- # climate.add_flag('--absolute-path', aliases: [ '-abs', '-p' ])
1315
- #
1316
- # ==== Specification(s) of a flag (multiple statements)
1317
- #
1318
- # climate.add_flag('--mark-missing')
1319
- # climate.add_alias('--mark-missing', '-x')
1320
- #
1321
- # climate.add_flag('--absolute-path')
1322
- # climate.add_alias('--absolute-path', '-abs', '-p')
1323
- #
1324
- # ==== Specification(s) of an option (single statement)
1325
- #
1326
- # climate.add_option('--add-patterns', alias: '-p')
1327
- #
1328
- # ==== Specification(s) of an option (multiple statements)
1329
- #
1330
- # climate.add_option('--add-patterns')
1331
- # climate.add_alias('--add-patterns', '-p')
1332
- #
1333
- # ==== Specification of a valued option (which has to be multiple statements)
1334
- #
1335
- # climate.add_option('--verbosity', values: [ 'succinct', 'verbose' ])
1336
- # climate.add_alias('--verbosity=succinct', '-s')
1337
- # climate.add_alias('--verbosity=verbose', '-v')
1338
- def add_alias(name_or_specification, *aliases)
1339
-
1340
- check_parameter name_or_specification, 'name_or_specification', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification, ::CLASP::OptionSpecification ]
1341
- raise ArgumentError, "must supply at least one alias" if aliases.empty?
1342
-
1343
- case name_or_specification
1344
- when ::CLASP::FlagSpecification
1345
-
1346
- self.specifications << name_or_specification
1347
- when ::CLASP::OptionSpecification
1348
-
1349
- self.specifications << name_or_specification
1350
- else
1351
-
1352
- self.specifications << CLASP.Alias(name_or_specification, aliases: aliases)
1353
- end
1354
- end
1355
-
1356
- # Attaches a block to an already-registered flag
1357
- #
1358
- # === Signature
1359
- #
1360
- # * *Parameters:*
1361
- # - +name_or_flag+ (String, ::CLASP::FlagSpecification) The flag name or instance of CLASP::FlagSpecification
1362
- # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1363
- #
1364
- # * *Options:*
1365
- #
1366
- # * *Block* A required block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
1367
- #
1368
- def on_flag(name_or_flag, options={}, &blk)
1369
-
1370
- check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
1371
-
1372
- raise ArgumentError, "on_flag() requires a block to be given" unless block_given?
1373
-
1374
- specifications.each do |spec|
1375
-
1376
- case spec
1377
- when CLASP::FlagSpecification
1378
-
1379
- if spec == name_or_flag
1380
-
1381
- spec.action = blk
1382
-
1383
- return true
1384
- end
1385
- end
1386
- end
1387
-
1388
- warn "The Climate instance does not contain a FlagSpecification matching '#{name_or_flag}' (#{name_or_flag.class})"
1389
-
1390
- false
1391
- end
1392
-
1393
- # Attaches a block to an already-registered option
1394
- #
1395
- # === Signature
1396
- #
1397
- # * *Parameters:*
1398
- # - +name_or_option+ (String, ::CLASP::OptionSpecification) The option name or instance of CLASP::OptionSpecification
1399
- # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1400
- #
1401
- # * *Options:*
1402
- #
1403
- # * *Block* A required block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
1404
- #
1405
- def on_option(name_or_option, options={}, &blk)
1406
-
1407
- check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
1408
-
1409
- raise ArgumentError, "on_option() requires a block to be given" unless block_given?
1410
-
1411
- specifications.each do |spec|
1412
-
1413
- case spec
1414
- when CLASP::OptionSpecification
1415
-
1416
- if spec == name_or_option
1417
-
1418
- spec.action = blk
1419
-
1420
- return true
1421
- end
1422
- end
1423
- end
1424
-
1425
- warn "The Climate instance does not contain an OptionSpecification matching '#{name_or_option}' (#{name_or_option.class})"
1230
+ stream.puts msg
1231
+
1232
+ exit(exit_code) if exit_code
1233
+
1234
+ msg
1235
+ end
1236
+
1237
+ # Adds a flag to +specifications+
1238
+ #
1239
+ # === Signature
1240
+ #
1241
+ # * *Parameters:*
1242
+ # - +name_or_flag+ (String, ::CLASP::FlagSpecification) The flag name or instance of CLASP::FlagSpecification
1243
+ # - +options+ (Hash) An options hash, containing any of the following options
1244
+ #
1245
+ # * *Options:*
1246
+ # - +:alias+ (String) A single alias
1247
+ # - +:aliases+ ([String]) An array of aliases
1248
+ # - +:help+ (String) Description string used when writing response to "+--help+" flag
1249
+ # - +:required+ (boolean) Indicates whether the flag is required, causing #run to fail with appropriate message if the flag is not specified in the command-line arguments
1250
+ #
1251
+ # * *Block* An optional block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
1252
+ #
1253
+ # === Examples
1254
+ #
1255
+ # ==== Specification(s) of a flag (single statement)
1256
+ #
1257
+ def add_flag(name_or_flag, options={}, &blk)
1258
+
1259
+ check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
1260
+
1261
+ if ::CLASP::FlagSpecification === name_or_flag
1262
+
1263
+ specifications << name_or_flag
1264
+ else
1265
+
1266
+ specifications << CLASP.Flag(name_or_flag, **options, &blk)
1267
+ end
1268
+ end
1269
+
1270
+ # Adds an option to +specifications+
1271
+ #
1272
+ # === Signature
1273
+ #
1274
+ # * *Parameters:*
1275
+ # - +name_or_option+ (String, CLASP::OptionSpecification) The option name or instance of CLASP::OptionSpecification
1276
+ # - +options+ (Hash) An options hash, containing any of the following options
1277
+ #
1278
+ # * *Options:*
1279
+ # - +:alias+ (String) A single alias
1280
+ # - +:aliases+ ([String]) An array of aliases
1281
+ # - +:help+ (String) Description string used when writing response to "+--help+" flag
1282
+ # - +:values_range+ ([String]) An array of strings representing the valid/expected values used when writing response to "+--help+" flag. NOTE: the current version does not validate against these values, but a future version may do so
1283
+ # - +:default_value+ (String) The default version used when, say, for the option +--my-opt+ the command-line contain the argument "+--my-opt=+"
1284
+ #
1285
+ # * *Block* An optional block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
1286
+ #
1287
+ def add_option(name_or_option, options={}, &blk)
1288
+
1289
+ check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
1290
+
1291
+ if ::CLASP::OptionSpecification === name_or_option
1292
+
1293
+ specifications << name_or_option
1294
+ else
1295
+
1296
+ specifications << CLASP.Option(name_or_option, **options, &blk)
1297
+ end
1298
+ end
1299
+
1300
+ # Adds an alias to +specifications+
1301
+ #
1302
+ # === Signature
1303
+ #
1304
+ # * *Parameters:*
1305
+ # - +name_or_specification+ (String) The flag/option name or the valued option
1306
+ # - +aliases+ (*[String]) One or more aliases
1307
+ #
1308
+ # === Examples
1309
+ #
1310
+ # ==== Specification(s) of a flag (single statement)
1311
+ #
1312
+ # climate.add_flag('--mark-missing', alias: '-x')
1313
+ #
1314
+ # climate.add_flag('--absolute-path', aliases: [ '-abs', '-p' ])
1315
+ #
1316
+ # ==== Specification(s) of a flag (multiple statements)
1317
+ #
1318
+ # climate.add_flag('--mark-missing')
1319
+ # climate.add_alias('--mark-missing', '-x')
1320
+ #
1321
+ # climate.add_flag('--absolute-path')
1322
+ # climate.add_alias('--absolute-path', '-abs', '-p')
1323
+ #
1324
+ # ==== Specification(s) of an option (single statement)
1325
+ #
1326
+ # climate.add_option('--add-patterns', alias: '-p')
1327
+ #
1328
+ # ==== Specification(s) of an option (multiple statements)
1329
+ #
1330
+ # climate.add_option('--add-patterns')
1331
+ # climate.add_alias('--add-patterns', '-p')
1332
+ #
1333
+ # ==== Specification of a valued option (which has to be multiple statements)
1334
+ #
1335
+ # climate.add_option('--verbosity', values: [ 'succinct', 'verbose' ])
1336
+ # climate.add_alias('--verbosity=succinct', '-s')
1337
+ # climate.add_alias('--verbosity=verbose', '-v')
1338
+ def add_alias(name_or_specification, *aliases)
1339
+
1340
+ check_parameter name_or_specification, 'name_or_specification', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification, ::CLASP::OptionSpecification ]
1341
+ raise ArgumentError, "must supply at least one alias" if aliases.empty?
1342
+
1343
+ case name_or_specification
1344
+ when ::CLASP::FlagSpecification
1345
+
1346
+ self.specifications << name_or_specification
1347
+ when ::CLASP::OptionSpecification
1348
+
1349
+ self.specifications << name_or_specification
1350
+ else
1351
+
1352
+ self.specifications << CLASP.Alias(name_or_specification, aliases: aliases)
1353
+ end
1354
+ end
1355
+
1356
+ # Attaches a block to an already-registered flag
1357
+ #
1358
+ # === Signature
1359
+ #
1360
+ # * *Parameters:*
1361
+ # - +name_or_flag+ (String, ::CLASP::FlagSpecification) The flag name or instance of CLASP::FlagSpecification
1362
+ # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1363
+ #
1364
+ # * *Options:*
1365
+ #
1366
+ # * *Block* A required block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
1367
+ #
1368
+ def on_flag(name_or_flag, options={}, &blk)
1369
+
1370
+ check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
1371
+
1372
+ raise ArgumentError, "on_flag() requires a block to be given" unless block_given?
1373
+
1374
+ specifications.each do |spec|
1375
+
1376
+ case spec
1377
+ when CLASP::FlagSpecification
1378
+
1379
+ if spec == name_or_flag
1380
+
1381
+ spec.action = blk
1382
+
1383
+ return true
1384
+ end
1385
+ end
1386
+ end
1387
+
1388
+ warn "The Climate instance does not contain a FlagSpecification matching '#{name_or_flag}' (#{name_or_flag.class})"
1389
+
1390
+ false
1391
+ end
1392
+
1393
+ # Attaches a block to an already-registered option
1394
+ #
1395
+ # === Signature
1396
+ #
1397
+ # * *Parameters:*
1398
+ # - +name_or_option+ (String, ::CLASP::OptionSpecification) The option name or instance of CLASP::OptionSpecification
1399
+ # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1400
+ #
1401
+ # * *Options:*
1402
+ #
1403
+ # * *Block* A required block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
1404
+ #
1405
+ def on_option(name_or_option, options={}, &blk)
1406
+
1407
+ check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
1408
+
1409
+ raise ArgumentError, "on_option() requires a block to be given" unless block_given?
1410
+
1411
+ specifications.each do |spec|
1412
+
1413
+ case spec
1414
+ when CLASP::OptionSpecification
1415
+
1416
+ if spec == name_or_option
1417
+
1418
+ spec.action = blk
1419
+
1420
+ return true
1421
+ end
1422
+ end
1423
+ end
1424
+
1425
+ warn "The Climate instance does not contain an OptionSpecification matching '#{name_or_option}' (#{name_or_option.class})"
1426
1426
 
1427
- false
1428
- end
1427
+ false
1428
+ end
1429
1429
  end # class Climate
1430
1430
  end # module LibCLImate
1431
1431