cli-dispatcher 1.1.12 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/structured.rb +101 -56
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 850d024672db8785ec7d329961a30baf9e8d4f1724189f6cf6250472cc17e5e8
|
4
|
+
data.tar.gz: 11e2ab38ddd9cc99d7ec2b66bf4b97d229a470ded4295ef2e7ecddca99bca74e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f5a3f85f1f64785b526df560efe2ef2ee94b031d0ef9bd47d43fd6500eaf4faba0b70a6230d1ccbc49db4d9a8d0681a1ba17edd847c105ab0b8d106568ccb2f
|
7
|
+
data.tar.gz: e6c3a31bd0825b3ae234dd68b6432e5a5b7f0fe4daf76a9494545018d264615630f89368b1c352d950be23a66be76e36fa5a3059bb38ad411d37f91912480f5a
|
data/lib/structured.rb
CHANGED
@@ -172,7 +172,8 @@ module Structured
|
|
172
172
|
# raises an error, but classes may override this method to use the undefined
|
173
173
|
# elements.
|
174
174
|
#
|
175
|
-
# @param element The unknown element name,
|
175
|
+
# @param element The unknown element name. For a YAML file, this is typically
|
176
|
+
# a string.
|
176
177
|
#
|
177
178
|
# @param val The value associated with the unknown element.
|
178
179
|
#
|
@@ -212,6 +213,7 @@ module Structured
|
|
212
213
|
def reset_elements
|
213
214
|
@elements = {}
|
214
215
|
@default_element = nil
|
216
|
+
@default_key = nil
|
215
217
|
@class_description = nil
|
216
218
|
end
|
217
219
|
|
@@ -266,14 +268,32 @@ module Structured
|
|
266
268
|
|
267
269
|
#
|
268
270
|
# Accepts a default element for this class. The arguments are the same as
|
269
|
-
# those for element_data.
|
271
|
+
# those for element_data except as noted below.
|
270
272
|
#
|
271
|
-
#
|
272
|
-
#
|
273
|
+
# If this method is called, then for any keys found in an input hash that
|
274
|
+
# have no corresponding #element declaration in the Structured class, the
|
275
|
+
# method receive_any will be invoked. The value from the input hash
|
276
|
+
# will be processed based on any type declaration, `preproc`, and `check`
|
277
|
+
# given to default_element.
|
278
|
+
#
|
279
|
+
# The default element keys can be processed based on the argument `key`,
|
280
|
+
# which should be a hash corresponding to the element_data arguments plus
|
281
|
+
# the key :type with the default key's expected type. If `key` is not given,
|
282
|
+
# then the key must be and is automatically converted to a Symbol.
|
283
|
+
#
|
284
|
+
# **Caution**: The `type` argument should almost always be a single class,
|
285
|
+
# and not a hash. This is because the default arguments are automatically
|
273
286
|
# treated like a hash, with the otherwise-undefined element names being the
|
274
287
|
# keys of the hash.
|
275
288
|
#
|
276
289
|
def default_element(*args, **params)
|
290
|
+
if (key_params = params.delete(:key))
|
291
|
+
@default_key = element_data(
|
292
|
+
key_params.delete(:type) || Object, key_params
|
293
|
+
)
|
294
|
+
else
|
295
|
+
@default_key = element_data(Symbol, preproc: proc { |s| s.to_sym })
|
296
|
+
end
|
277
297
|
@default_element = element_data(*args, **params)
|
278
298
|
end
|
279
299
|
|
@@ -384,47 +404,28 @@ module Structured
|
|
384
404
|
input_err("Initializer is not a Hash") unless hash.is_a?(Hash)
|
385
405
|
hash = try_read_file(hash)
|
386
406
|
|
387
|
-
@elements.each do |
|
388
|
-
Structured.trace(
|
389
|
-
val = hash[
|
390
|
-
|
391
|
-
|
392
|
-
if data[:preproc]
|
393
|
-
val = try_run(data[:preproc], obj, val, "preproc")
|
394
|
-
next if process_nil_val(obj, elt, val, data)
|
395
|
-
end
|
396
|
-
|
397
|
-
cval = convert_item(val, data[:type], obj)
|
398
|
-
|
399
|
-
# Check for validity after preproc and conversion are run
|
400
|
-
if data[:check] && !try_run(data[:check], obj, cval, "check")
|
401
|
-
input_err "Value #{cval} failed check for #{elt}"
|
402
|
-
end
|
403
|
-
|
404
|
-
# Use the converted value
|
405
|
-
apply_val(obj, elt, cval)
|
407
|
+
@elements.each do |key, data|
|
408
|
+
Structured.trace(key.to_s) do
|
409
|
+
val = hash[key] || hash[key.to_s]
|
410
|
+
cval = process_value(obj, val, data)
|
411
|
+
apply_val(obj, key, cval) if cval
|
406
412
|
end
|
407
413
|
end
|
408
414
|
|
409
415
|
# Process unknown elements
|
410
|
-
|
411
|
-
return if
|
416
|
+
unknown_keys = hash.keys.reject { |k| @elements.include?(k.to_sym) }
|
417
|
+
return if unknown_keys.empty?
|
412
418
|
unless @default_element
|
413
|
-
input_err("Unexpected element(s): #{
|
419
|
+
input_err("Unexpected element(s): #{unknown_keys.join(', ')}")
|
414
420
|
end
|
415
|
-
|
416
|
-
Structured.trace(
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
if de[:check] && !try_run(de[:check], obj, item, "check")
|
424
|
-
input_err "Value #{item} failed default element check"
|
425
|
-
end
|
426
|
-
item.receive_key(elt) if item.is_a?(Structured)
|
427
|
-
obj.receive_any(elt, item)
|
421
|
+
unknown_keys.each do |key|
|
422
|
+
Structured.trace(key.to_s) do
|
423
|
+
val = hash[key]
|
424
|
+
ckey = process_value(obj, key, @default_key)
|
425
|
+
cval = process_value(obj, val, @default_element)
|
426
|
+
next unless cval
|
427
|
+
cval.receive_key(ckey) if cval.is_a?(Structured)
|
428
|
+
obj.receive_any(ckey, cval)
|
428
429
|
end
|
429
430
|
end
|
430
431
|
end
|
@@ -450,24 +451,53 @@ module Structured
|
|
450
451
|
end
|
451
452
|
end
|
452
453
|
|
453
|
-
|
454
|
-
#
|
454
|
+
|
455
|
+
#
|
456
|
+
# Given an element value and an #element_data hash of processing tools
|
457
|
+
# element, applies those processing tools. Namely, apply any preproc, check
|
458
|
+
# the type and perform other checks, and perform any conversions. The return
|
459
|
+
# value should be usable as the received value for the corresponding
|
460
|
+
# element.
|
455
461
|
#
|
456
|
-
#
|
462
|
+
# If this method returns nil, then there is no element to process. This
|
463
|
+
# method may also raise an InputError.
|
464
|
+
#
|
465
|
+
def process_value(obj, val, data)
|
466
|
+
val, ret = process_nil_val(val, data)
|
467
|
+
return val if ret
|
468
|
+
if data[:preproc]
|
469
|
+
val = try_run(data[:preproc], obj, val, "preproc")
|
470
|
+
val, ret = process_nil_val(val, data)
|
471
|
+
return val if ret
|
472
|
+
end
|
473
|
+
|
474
|
+
cval = convert_item(val, data[:type], obj)
|
475
|
+
if data[:check] && !try_run(data[:check], obj, cval, "check")
|
476
|
+
input_err "Value #{cval} failed check"
|
477
|
+
end
|
478
|
+
return cval
|
479
|
+
end
|
480
|
+
|
481
|
+
#
|
482
|
+
# Performs processing of an element value to deal with the possibility that
|
483
|
+
# the value is nil. This method returns [ the new value, boolean of whether
|
484
|
+
# to stop processing ] according to the following rules:
|
485
|
+
#
|
486
|
+
# * If val is non-nil, then this method returns val itself, and processing
|
487
|
+
# should not stop.
|
457
488
|
# * If val is nil and this element is non-optional, then this method raises
|
458
489
|
# an error.
|
459
|
-
# * If val is nil and the element is optional,
|
460
|
-
#
|
461
|
-
#
|
462
|
-
#
|
463
|
-
#
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
return true
|
490
|
+
# * If val is nil and the element is optional, then the object's default
|
491
|
+
# value is returned, and processing should stop.
|
492
|
+
# * If there is no default value for an optional element, then nil is
|
493
|
+
# returned, and processing should also stop.
|
494
|
+
#
|
495
|
+
def process_nil_val(val, data)
|
496
|
+
return [ val, false ] if val
|
497
|
+
unless data[:optional]
|
498
|
+
input_err("Required element is missing (or was deleted by a preproc)")
|
499
|
+
end
|
500
|
+
return [ data[:default], true ]
|
471
501
|
end
|
472
502
|
|
473
503
|
# Applies a value to an element for an object, after all processing for the
|
@@ -542,12 +572,22 @@ module Structured
|
|
542
572
|
end
|
543
573
|
end
|
544
574
|
|
575
|
+
#
|
576
|
+
# Several types can be automatically converted:
|
577
|
+
#
|
578
|
+
# * Symbol into String
|
579
|
+
# * String into Regexp
|
580
|
+
#
|
545
581
|
def try_autoconvert(type, item)
|
546
582
|
|
547
583
|
if type == String && item.is_a?(Symbol)
|
548
584
|
return item.to_s
|
549
585
|
end
|
550
586
|
|
587
|
+
if type == Symbol && item.is_a?(String)
|
588
|
+
return item.to_sym
|
589
|
+
end
|
590
|
+
|
551
591
|
# Special case in which strings will be converted to Regexps
|
552
592
|
if type == Regexp && item.is_a?(String)
|
553
593
|
begin
|
@@ -563,7 +603,11 @@ module Structured
|
|
563
603
|
# Receive hash values that are to be converted to Structured objects
|
564
604
|
def convert_structured(item, type, parent)
|
565
605
|
unless item.is_a?(Hash)
|
566
|
-
|
606
|
+
if type.include?(Structured)
|
607
|
+
input_err("#{item.inspect} not a Structured hash for #{type}")
|
608
|
+
else
|
609
|
+
input_err("#{item.inspect} not a #{type}")
|
610
|
+
end
|
567
611
|
end
|
568
612
|
|
569
613
|
unless type.include?(Structured) || type.include?(StructuredPolymorphic)
|
@@ -604,7 +648,8 @@ module Structured
|
|
604
648
|
|
605
649
|
if @default_element
|
606
650
|
io.puts(
|
607
|
-
" All other elements: #{describe_type(@
|
651
|
+
" All other elements: #{describe_type(@default_key[:type])} => " \
|
652
|
+
"#{describe_type(@default_element[:type])}"
|
608
653
|
)
|
609
654
|
if @default_element[:description]
|
610
655
|
io.puts(TextTools.line_break(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cli-dispatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Duan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
Library for creating command-line programs that accept commands. Also
|