libclimate-ruby 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b097608f416fda5a16bf34588903e669cd37abc259c8e971c65087de88dbd1e
4
- data.tar.gz: 3dd3938b2ea4fc8f8b2d632787b048d8c8a75fd575a1df4262c60007fea989fb
3
+ metadata.gz: 6c5040323c276e22e2dcf86fbebf1e66bf159904d9a28e764ff913aed1d9a508
4
+ data.tar.gz: 9551c44bc9ca7bb1f69783d8c6b1e5ae0288548140dcd86023cd80df6fa98c14
5
5
  SHA512:
6
- metadata.gz: 23fa6d636ea3bc4bae684ab3adaae3abb12ea3c6dc634c48fd69098016f7fad816b87e07c50291a136e0ea4e9bb4ec41d816f7a155428ae6a213db184cd45705
7
- data.tar.gz: 17ae81db2053520808553a12cabf97c96369ffbf027039bc53c689ea05c1933ec4aff888b957f262432209cd980f6da3c28557c24874cb759d29c31a5a8a3c8d
6
+ metadata.gz: 158c64020110e066c1f57be6c4820e9519bed9fccee5883b903dd8d8f4c49d91f971bcfef8e2ff3fd416e6074be0149562098305b56a7cd705aa2619199c7620
7
+ data.tar.gz: 7672ba94c8724a7504f12d589ff20e703b31eb5ae5e27e6f1878ba8136a8ab2f0749e307b5d00ef11cfca277641c3c3479808c0a2d2406be1247abe887ae3f93
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # examples/flag_and_option_specifications.from_DATA.rb
4
+
5
+
6
+ # requires
7
+
8
+ require 'libclimate'
9
+
10
+
11
+ # constants
12
+
13
+ PROGRAM_VERSION = '0.0.1'
14
+
15
+
16
+ # Specify aliases, parse, and checking standard flags
17
+
18
+ options = {}
19
+ climate = LibCLImate::Climate.load DATA do |cl|
20
+
21
+ cl.on_flag('--debug') { options[:debug] = true }
22
+
23
+ cl.on_option('--verbosity') { |o, a| options[:verbosity] = o.value }
24
+ end
25
+
26
+ r = climate.run ARGV
27
+
28
+
29
+ # Program-specific processing of flags/options
30
+
31
+ if options[:verbosity]
32
+
33
+ $stdout.puts "verbosity is specified as: #{options[:verbosity]}"
34
+ end
35
+
36
+ if options[:debug]
37
+
38
+ $stdout.puts 'Debug mode is specified'
39
+ end
40
+
41
+
42
+ __END__
43
+ ---
44
+ libclimate:
45
+ clasp:
46
+ specifications:
47
+ - flag:
48
+ name: --debug
49
+ alias: -d
50
+ help: runs in Debug mode
51
+ required: false
52
+ - option:
53
+ name: --verbosity
54
+ help: specifies the verbosity
55
+ values:
56
+ - silent
57
+ - quiet
58
+ - terse
59
+ - chatty
60
+ - verbose
61
+ - alias:
62
+ resolved: --verbosity=chatty
63
+ aliases:
64
+ - --chatty
65
+ - -c
66
+ constrain_values: !ruby/range 1..2
67
+ exit_on_missing: true
68
+ flags_and_options: "[... flags/options ...]"
69
+ usage_values: "<directory-1> [ <directory-2> ]"
70
+ value_names:
71
+ - directory-1
72
+ - directory-2
73
+ info_lines:
74
+ - libCLImate.Ruby examples
75
+ - :version
76
+ - Illustrates use of libCLImate.Ruby's specification of flags, options, and aliases, from DATA
77
+ -
78
+ version:
79
+ - 0
80
+ - 3
81
+ - "4"
82
+
@@ -44,6 +44,8 @@ require 'clasp'
44
44
  require 'xqsr3/extensions/io'
45
45
  require 'xqsr3/quality/parameter_checking'
46
46
 
47
+ require 'yaml'
48
+
47
49
  =begin
48
50
  =end
49
51
 
@@ -166,6 +168,11 @@ class Climate
166
168
  #:stopdoc:
167
169
 
168
170
  private
171
+ module Climate_Constants_
172
+
173
+ GIVEN_SPECS_ = "_Given_Specs_01B59422_8407_4c89_9432_8160C52BD5AD"
174
+ end # module Climate_Constants_
175
+
169
176
  def show_usage_
170
177
 
171
178
  options = {}
@@ -262,10 +269,166 @@ class Climate
262
269
 
263
270
  nil
264
271
  end
272
+
273
+ def self.check_type_(v, types)
274
+
275
+ return true if v.nil?
276
+
277
+ types = [ types ] unless Array === types
278
+
279
+ return true if types.empty?
280
+
281
+ types.each do |type|
282
+
283
+ if false
284
+
285
+ ;
286
+ elsif :boolean == type
287
+
288
+ return true if [ TrueClass, FalseClass ].include? v.class
289
+ elsif type.is_a?(Class)
290
+
291
+ return true if v.is_a?(type)
292
+ elsif type.is_a?(Array)
293
+
294
+ t0 = type[0]
295
+
296
+ if t0
297
+
298
+ #return true if v.is_a?
299
+ else
300
+
301
+ # Can be array of anything
302
+
303
+ return true if v.is_a?(Array)
304
+ end
305
+ else
306
+
307
+ warn "Cannot validate type of '#{v}' (#{v.class}) against type specification '#{type}'"
308
+ end
309
+ end
310
+
311
+ false
312
+ end
313
+
314
+ def self.lookup_element_(h, types, name, path)
315
+
316
+ if h.has_key?(name)
317
+
318
+ r = h[name]
319
+
320
+ unless self.check_type_(r, types)
321
+
322
+ raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
323
+ end
324
+
325
+ return r
326
+ end
327
+
328
+ nil
329
+ end
330
+
331
+ def self.require_element_(h, types, name, path)
332
+
333
+ unless h.has_key?(name)
334
+
335
+ if (path || '').empty?
336
+
337
+ raise ArgumentError, "missing top-level element '#{name}' in load configuration"
338
+ else
339
+
340
+ raise ArgumentError, "missing element '#{path}/#{name}' in load configuration"
341
+ end
342
+ else
343
+
344
+ r = h[name]
345
+
346
+ unless self.check_type_(r, types)
347
+
348
+ raise TypeError, "element '#{name}' is of type '#{r.class}' and '#{types}' is required"
349
+ end
350
+
351
+ return r
352
+ end
353
+ end
265
354
  #:startdoc:
266
355
 
267
356
  public
268
357
 
358
+ # Loads an instance of the class, as specified by +source+, according to the given parameters
359
+ #
360
+ # === Signature
361
+ #
362
+ # * *Parameters:*
363
+ # - +source+:: (+Hash+, +IO+) The arguments specification, either as a Hash or an instance of an IO-implementing type containing a YAML specification
364
+ # - +options+:: An options hash, containing any of the following options
365
+ #
366
+ # * *Options:*
367
+ # - +:no_help_flag+ (boolean) Prevents the use of the +CLASP::Flag.Help+ flag-specification
368
+ # - +:no_version_flag+ (boolean) Prevents the use of the +CLASP::Flag.Version+ flag-specification
369
+ # - +:program_name+ (::String) An explicit program-name, which is inferred from +$0+ if this is +nil+
370
+ # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
371
+ # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
372
+ #
373
+ # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
374
+ def self.load source, options = (options_defaulted_ = {}), &blk
375
+
376
+ check_parameter options, 'options', allow_nil: true, type: ::Hash
377
+
378
+ options ||= {}
379
+
380
+ h = nil
381
+
382
+ case source
383
+ when ::IO
384
+
385
+ h = YAML.load source.read
386
+ when ::Hash
387
+
388
+ h = source
389
+ else
390
+
391
+ if source.respond_to?(:to_hash)
392
+
393
+ h = source.to_hash
394
+ else
395
+
396
+ raise TypeError, "#{self}.#{__method__}() 'source' argument must be a #{::Hash}, or an object implementing #{::IO}, or a type implementing 'to_hash'"
397
+ end
398
+ end
399
+
400
+ _libclimate = require_element_(h, Hash, 'libclimate', nil)
401
+ _exit_on_missing = lookup_element_(_libclimate, :boolean, 'exit_on_missing', 'libclimate')
402
+ _ignore_unknown = lookup_element_(_libclimate, :boolean, 'ignore_unknown', 'libclimate')
403
+ _exit_on_unknown = lookup_element_(_libclimate, :boolean, 'exit_on_unknown', 'libclimate')
404
+ _exit_on_usage = lookup_element_(_libclimate, :boolean, 'exit_on_usage', 'libclimate')
405
+ _info_lines = lookup_element_(_libclimate, Array, 'info_lines', 'libclimate')
406
+ _program_name = lookup_element_(_libclimate, String, 'program_name', 'libclimate')
407
+ _constrain_values = lookup_element_(_libclimate, [ Integer, Range ], 'constrain_values', 'libclimate')
408
+ _flags_and_options = lookup_element_(_libclimate, String, 'flags_and_options', 'libclimate')
409
+ _usage_values = lookup_element_(_libclimate, String, 'usage_values', 'libclimate')
410
+ _value_names = lookup_element_(_libclimate, Array, 'value_names', 'libclimate')
411
+ _version = lookup_element_(_libclimate, [ String, [] ], 'version', 'libclimate')
412
+
413
+ specs = CLASP::Arguments.load_specifications _libclimate, options
414
+
415
+ cl = Climate.new(options.merge(Climate_Constants_::GIVEN_SPECS_ => specs), &blk)
416
+
417
+ cl.exit_on_missing = _exit_on_missing unless _exit_on_missing.nil?
418
+ cl.ignore_unknown = _ignore_unknown unless _ignore_unknown.nil?
419
+ cl.exit_on_unknown = _exit_on_unknown unless _exit_on_unknown.nil?
420
+ cl.exit_on_usage = _exit_on_usage unless _exit_on_usage.nil?
421
+ cl.info_lines = _info_lines unless _info_lines.nil?
422
+ cl.program_name = _program_name unless _program_name.nil?
423
+ cl.constrain_values = _constrain_values unless _constrain_values.nil?
424
+ cl.flags_and_options = _flags_and_options unless _flags_and_options.nil?
425
+ cl.usage_values = _usage_values unless _usage_values.nil?
426
+ cl.value_names = _value_names unless _value_names.nil?
427
+ cl.version = _version unless _version.nil?
428
+
429
+ cl
430
+ end
431
+
269
432
  # Creates an instance of the Climate class.
270
433
  #
271
434
  # === Signature
@@ -280,8 +443,8 @@ class Climate
280
443
  # - +:version+ (String, [Integer], [String]) A version specification. If not specified, this is inferred
281
444
  # - +:version_context+ Object or class that defines a context for searching the version. Ignored if +:version+ is specified
282
445
  #
283
- # * *Block* An optional block which receives the constructing instance, allowing the user to modify the attributes.
284
- def initialize(options={}) # :yields: climate
446
+ # * *Block* An optional block that receives the initialising Climate instance, allowing the user to modify the attributes.
447
+ def initialize(options={}, &blk) # :yields: climate
285
448
 
286
449
  check_parameter options, 'options', allow_nil: true, type: ::Hash
287
450
 
@@ -299,6 +462,8 @@ class Climate
299
462
  pr_name = (pr_name =~ /\.(?:bat|cmd|rb|sh)$/) ? "#$`(#$&)" : pr_name
300
463
  end
301
464
 
465
+ given_specs = options[Climate_Constants_::GIVEN_SPECS_]
466
+
302
467
  @specifications = []
303
468
  @ignore_unknown = false
304
469
  @exit_on_unknown = true
@@ -318,6 +483,8 @@ class Climate
318
483
  @specifications << CLASP::Flag.Help(handle: proc { show_usage_ }) unless options[:no_help_flag]
319
484
  @specifications << CLASP::Flag.Version(handle: proc { show_version_ }) unless options[:no_version_flag]
320
485
 
486
+ @specifications = @specifications + given_specs if given_specs
487
+
321
488
  yield self if block_given?
322
489
  end
323
490
 
@@ -386,6 +553,13 @@ class Climate
386
553
  raise ArgumentError, "argv may not be nil" if argv.nil?
387
554
 
388
555
  arguments = CLASP::Arguments.new argv, specifications
556
+
557
+ run_ argv, arguments
558
+ end
559
+
560
+ private
561
+ def run_ argv, arguments # :nodoc:
562
+
389
563
  flags = arguments.flags
390
564
  options = arguments.options
391
565
  values = arguments.values.to_a
@@ -594,7 +768,7 @@ class Climate
594
768
  message = "wrong number of values: #{values.size} given, #{values_constraint} required; use --help for usage"
595
769
  end
596
770
 
597
- if exit_on_unknown
771
+ if exit_on_missing
598
772
 
599
773
  self.abort message
600
774
  else
@@ -619,7 +793,7 @@ class Climate
619
793
  message = "wrong number of values: #{values.size} givens, #{values_constraint.begin} - #{values_constraint.end - (values_constraint.exclude_end? ? 1 : 0)} required; use --help for usage"
620
794
  end
621
795
 
622
- if exit_on_unknown
796
+ if exit_on_missing
623
797
 
624
798
  self.abort message
625
799
  else
@@ -661,6 +835,7 @@ class Climate
661
835
 
662
836
  results
663
837
  end
838
+ public
664
839
 
665
840
  # Calls abort() with the given message prefixed by the program_name
666
841
  #
@@ -719,20 +894,22 @@ class Climate
719
894
  # - +:help+ (String) Description string used when writing response to "+--help+" flag
720
895
  # - +: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
721
896
  #
897
+ # * *Block* An optional block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
898
+ #
722
899
  # === Examples
723
900
  #
724
901
  # ==== Specification(s) of a flag (single statement)
725
902
  #
726
- def add_flag(name_or_flag, options={}, &block)
903
+ def add_flag(name_or_flag, options={}, &blk)
727
904
 
728
- check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::Flag ]
905
+ check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
729
906
 
730
907
  if ::CLASP::Flag === name_or_flag
731
908
 
732
909
  specifications << name_or_flag
733
910
  else
734
911
 
735
- specifications << CLASP.Flag(name_or_flag, **options, &block)
912
+ specifications << CLASP.Flag(name_or_flag, **options, &blk)
736
913
  end
737
914
  end
738
915
 
@@ -750,16 +927,19 @@ class Climate
750
927
  # - +:help+ (String) Description string used when writing response to "+--help+" flag
751
928
  # - +: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
752
929
  # - +:default_value+ (String) The default version used when, say, for the option +--my-opt+ the command-line contain the argument "+--my-opt=+"
753
- def add_option(name_or_option, options={}, &block)
930
+ #
931
+ # * *Block* An optional block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
932
+ #
933
+ def add_option(name_or_option, options={}, &blk)
754
934
 
755
- check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::Option ]
935
+ check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
756
936
 
757
937
  if ::CLASP::Option === name_or_option
758
938
 
759
939
  specifications << name_or_option
760
940
  else
761
941
 
762
- specifications << CLASP.Option(name_or_option, **options, &block)
942
+ specifications << CLASP.Option(name_or_option, **options, &blk)
763
943
  end
764
944
  end
765
945
 
@@ -803,7 +983,7 @@ class Climate
803
983
  # climate.add_alias('--verbosity=verbose', '-v')
804
984
  def add_alias(name_or_specification, *aliases)
805
985
 
806
- check_parameter name_or_specification, 'name_or_specification', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::Flag, ::CLASP::Option ]
986
+ check_parameter name_or_specification, 'name_or_specification', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification, ::CLASP::OptionSpecification ]
807
987
  raise ArgumentError, "must supply at least one alias" if aliases.empty?
808
988
 
809
989
  case name_or_specification
@@ -818,6 +998,80 @@ class Climate
818
998
  self.specifications << CLASP.Alias(name_or_specification, aliases: aliases)
819
999
  end
820
1000
  end
1001
+
1002
+ # Attaches a block to an already-registered flag
1003
+ #
1004
+ # === Signature
1005
+ #
1006
+ # * *Parameters:*
1007
+ # - +name_or_flag+ (String, ::CLASP::FlagSpecification) The flag name or instance of CLASP::FlagSpecification
1008
+ # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1009
+ #
1010
+ # * *Options:*
1011
+ #
1012
+ # * *Block* A required block that is invoked when the parsed command-line contains the given flag, receiving the argument and the alias
1013
+ #
1014
+ def on_flag(name_or_flag, options={}, &blk)
1015
+
1016
+ check_parameter name_or_flag, 'name_or_flag', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::FlagSpecification ]
1017
+
1018
+ raise ArgumentError, "on_flag() requires a block to be given" unless block_given?
1019
+
1020
+ specifications.each do |spec|
1021
+
1022
+ case spec
1023
+ when CLASP::FlagSpecification
1024
+
1025
+ if spec == name_or_flag
1026
+
1027
+ spec.action = blk
1028
+
1029
+ return true
1030
+ end
1031
+ end
1032
+ end
1033
+
1034
+ warn "The Climate instance does not contain a FlagSpecification matching '#{name_or_flag}' (#{name_or_flag.class})"
1035
+
1036
+ false
1037
+ end
1038
+
1039
+ # Attaches a block to an already-registered option
1040
+ #
1041
+ # === Signature
1042
+ #
1043
+ # * *Parameters:*
1044
+ # - +name_or_option+ (String, ::CLASP::OptionSpecification) The option name or instance of CLASP::OptionSpecification
1045
+ # - +options+ (Hash) An options hash, containing any of the following options. No options are recognised currently
1046
+ #
1047
+ # * *Options:*
1048
+ #
1049
+ # * *Block* A required block that is invoked when the parsed command-line contains the given option, receiving the argument and the alias
1050
+ #
1051
+ def on_option(name_or_option, options={}, &blk)
1052
+
1053
+ check_parameter name_or_option, 'name_or_option', allow_nil: false, types: [ ::String, ::Symbol, ::CLASP::OptionSpecification ]
1054
+
1055
+ raise ArgumentError, "on_option() requires a block to be given" unless block_given?
1056
+
1057
+ specifications.each do |spec|
1058
+
1059
+ case spec
1060
+ when CLASP::OptionSpecification
1061
+
1062
+ if spec == name_or_option
1063
+
1064
+ spec.action = blk
1065
+
1066
+ return true
1067
+ end
1068
+ end
1069
+ end
1070
+
1071
+ warn "The Climate instance does not contain an OptionSpecification matching '#{name_or_option}' (#{name_or_option.class})"
1072
+
1073
+ false
1074
+ end
821
1075
  end # class Climate
822
1076
  end # module LibCLImate
823
1077
 
@@ -43,7 +43,7 @@
43
43
  module LibCLImate
44
44
 
45
45
  # Current version of the libCLImate.Ruby library
46
- VERSION = '0.12.2'
46
+ VERSION = '0.13.0'
47
47
 
48
48
  private
49
49
  VERSION_PARTS_ = VERSION.split(/[.]/).collect { |n| n.to_i } # :nodoc:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libclimate-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wilson
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.18'
19
+ version: '0.19'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.18'
26
+ version: '0.19'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: xqsr3
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -46,6 +46,7 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - LICENSE
48
48
  - README.md
49
+ - examples/flag_and_option_specifications.from_DATA.rb
49
50
  - examples/flag_and_option_specifications.md
50
51
  - examples/flag_and_option_specifications.rb
51
52
  - examples/show_usage_and_version.md