138 lines
2.9 KiB
Ruby
138 lines
2.9 KiB
Ruby
module Jasn1
|
|
module Options
|
|
class NoKeyError < StandardError
|
|
end
|
|
|
|
class AmbiguousTypeError < StandardError
|
|
end
|
|
|
|
class TypeValueMismatchError < StandardError
|
|
end
|
|
|
|
class DefaultTypeMismatchError < StandardError
|
|
end
|
|
|
|
class UnrecognizedFlagError < StandardError
|
|
end
|
|
|
|
class NoValueError < StandardError
|
|
end
|
|
|
|
class UnsupportedValueError < StandardError
|
|
end
|
|
|
|
class Option
|
|
attr_reader :type, :values
|
|
attr_accessor :value
|
|
|
|
def initialize(type, values, default)
|
|
@type = type
|
|
@values = values
|
|
@value = default
|
|
end
|
|
end
|
|
|
|
class OptionsManager
|
|
attr_reader :opts
|
|
|
|
def initialize
|
|
@opts = { }
|
|
@strict = false
|
|
end
|
|
|
|
def arg(key: "", type: nil, values: [], default: nil)
|
|
if key.empty?
|
|
raise NoKeyError
|
|
end
|
|
|
|
if default.nil? and not values.empty?
|
|
default = values.first
|
|
end
|
|
|
|
if type.nil?
|
|
if not default.nil?
|
|
type = default.class
|
|
elsif not values.empty?
|
|
type = values.first.class
|
|
else
|
|
raise AmbiguousTypeError
|
|
end
|
|
else
|
|
bad_values = values.filter do |value|
|
|
not value.is_a?(type)
|
|
end
|
|
|
|
if not bad_values.empty?
|
|
raise TypeValueMismatchError
|
|
elsif not default.nil? and not default.is_a?(type)
|
|
raise DefaultTypeMismatchError
|
|
end
|
|
end
|
|
|
|
@opts[key] = Option.new(type, values, default)
|
|
end
|
|
|
|
def boolean?(key)
|
|
[TrueClass, FalseClass].include? @opts[key].type
|
|
end
|
|
end
|
|
|
|
class Options
|
|
attr_reader :args
|
|
|
|
def initialize(args=ARGV)
|
|
if not block_given?
|
|
return
|
|
end
|
|
|
|
scanning = true
|
|
@args = args.clone
|
|
@mgr = OptionsManager.new
|
|
yield @mgr
|
|
|
|
while not @args.empty? and scanning
|
|
if @args.first == "--"
|
|
@args.shift
|
|
scanning = false
|
|
elsif @args.first[0] != "-"
|
|
scanning = false
|
|
end
|
|
|
|
if scanning
|
|
opt = @args.shift[1..]
|
|
flip = false
|
|
|
|
if opt.start_with?("no-")
|
|
opt = opt[3..]
|
|
flip = true
|
|
end
|
|
|
|
key, val = opt.split("=", 2)
|
|
|
|
if not @mgr.opts.key? key
|
|
raise UnrecognizedFlagError
|
|
end
|
|
|
|
if @mgr.boolean? key
|
|
@mgr.opts[key].value = if val.nil?
|
|
!flip
|
|
else
|
|
somehow_convert_to_boolean val
|
|
end
|
|
elsif val.nil?
|
|
raise NoValueError
|
|
elsif not @mgr.opts[key].values.include? val
|
|
raise UnsupportedValueError
|
|
else
|
|
@mgr.opts[key].value = @mgr.opts[key].type.new(val)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def [](key)
|
|
@mgr.opts[key].value
|
|
end
|
|
end
|
|
end
|
|
end
|