# Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com># # Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:# # The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN# THE SOFTWARE.require_relative'flags'moduleSamovarclassOptiondefinitialize(flags,description,key: nil,default: nil,value: nil,type: nil,&block)@flags=Flags.new(flags)@description=descriptionifkey@key=keyelse@key=@flags.first.keyend@default=default# If the value is given, it overrides the user specified input.@value=value@value||=trueif@flags.boolean?@type=type@block=blockendattr:flagsattr:descriptionattr:typeattr:defaultattr:keydefcoerce_type(result)if@type==IntegerInteger(result)elsif@type==FloatFloat(result)elsif@type==Symbolresult.to_symelsif@type.respond_to?:call@type.call(result)elsif@type.respond_to?:new@type.new(result)endenddefcoerce(result)if@typeresult=coerce_type(result)endif@blockresult=@block.call(result)endreturnresultenddefparse(input,default=@default)ifresult=@flags.parse(input)@value.nil??coerce(result):@valueend||defaultenddefto_s@flagsenddefto_aunless@default.nil?[@flags,@description,"Default: #{@default}"]else[@flags,@description]endendendclassOptionsdefself.parse(*args,**options,&block)options=self.new(*args,**options)options.instance_eval(&block)ifblock_given?returnoptionsenddefinitialize(title="Options",key: :options)@title=title@ordered=[]# We use this flag to option cache to improve parsing performance:@keyed={}@key=key@defaults={}endattr:keyattr:defaultsdefoption(*args,**options,&block)self<<Option.new(*args,**options,&block)enddef<<option@ordered<<optionoption.flags.eachdo|flag|@keyed[flag.prefix]=optionflag.alternatives.eachdo|alternative|@keyed[alternative]=optionendendifdefault=option.default@defaults[option.key]=option.defaultendenddefparse(input,default)values=(default||@defaults).dupwhileoption=@keyed[input.first]ifresult=option.parse(input)values[option.key]=resultendendreturnvaluesenddefto_s@ordered.collect(&:to_s).join(' ')enddefusage(rows)@ordered.eachdo|option|rows<<optionendendendend