class HelpParser::Completion
Public Class Methods
new(hash, specs)
click to toggle source
# File lib/help_parser/completion.rb, line 3 def initialize(hash, specs) @hash,@specs = hash,specs @cache = NoDupHash.new usage or diagnose if @specs.key?(USAGE) pad if @specs.key?(TYPES) k2t = types handle_argf(k2t) if k2t.detect{|_,v|v=='ARGF'} end end
Public Instance Methods
diagnose()
click to toggle source
Diagnose user’s usage.
# File lib/help_parser/completion.rb, line 38 def diagnose dict = {} @specs.each do |section,list| next if RESERVED.include? section list.flatten.select{_1[0]=='-'}.each do |key_type| key_type.scan(/\w+/) do |key| dict[key]=true break end end end typos = @hash.keys.select{_1.is_a?(String) && !dict[_1]} raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty? raise UsageError, MATCH_USAGE end
handle_argf(k2t)
click to toggle source
Prepare ARGV for ARGF.
# File lib/help_parser/completion.rb, line 15 def handle_argf(k2t) files = @hash.select{|k,_|k2t[k]=='ARGF'}.map{|_,v|v}.flatten e = files.reject{File.exist?_1}.join(', ') raise UsageError, MSG[NOT_EXIST, e] unless e.empty? ARGV.replace files end
matches(cmd, i = 0)
click to toggle source
# File lib/help_parser/completion.rb, line 118 def matches(cmd, i = 0) keys = @hash.keys cmd.each do |token| if token.is_a?(Array) begin i = matches(token, i) rescue NoMatch # OK, NEVERMIND! end next elsif (m=FLAG_GROUP.match token) group,plus = m[:k],m[:p] key = keys[i] raise NoMatch unless key.is_a? String list = @specs[group].flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]} raise NoMatch unless list.include?(key) unless plus.nil? loop do key = keys[i+1] break unless key.is_a?(String) && list.include?(key) i+=1 end end elsif (m=VARIABLE.match(token)) key = keys[i] raise NoMatch unless key.is_a?(Integer) variable,plus = m[:k],m[:p] if plus.nil? @cache[variable] = @hash[key] else strings = [] strings.push @hash[key] loop do key = keys[i+1] break unless key.is_a?(Integer) strings.push @hash[key] i+=1 end @cache[variable] = strings end else # literal key = keys[i] raise NoMatch if key.nil? || @hash[key]!=token end i += 1 end i end
pad()
click to toggle source
# File lib/help_parser/completion.rb, line 79 def pad # Synonyms and defaults: @specs.each do |section,options| next if RESERVED.any?{section==_1} options.each do |words| next unless words.size>1 first,second,default = words[0],words[1],words[2] if first[0]=='-' if second[0]=='-' i = second.index('=') || 0 short,long = first[1],second[2..(i-1)] if @hash.key?(short) if @hash.key?(long) raise UsageError, MSG[REDUNDANT, short, long] end @hash[long] = default.nil? ? true : default elsif (value=@hash[long]) @hash[short] = true if value==true && !default.nil? @hash.delete(long) # ArgvHash reset @hash[long]=default end end else i = first.index('=') || 0 long,default = first[2..(i-1)],second value = @hash[long] if value==true @hash.delete(long) # ArgvHash reset @hash[long] = default end end else raise SoftwareError, MSG[UNEXPECTED, words] end end end end
types()
click to toggle source
# File lib/help_parser/completion.rb, line 55 def types t2r,k2t = HelpParser.t2r(@specs),HelpParser.k2t(@specs) @hash.each do |key,value| next unless key.is_a?(String) && (type=k2t[key]) regex = t2r[type] case value when String unless value=~regex raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}" end when Array value.each do |string| unless string=~regex raise UsageError, "--#{key}=#{string} !~ #{type}=#{regex.inspect}" end end else raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}" end end k2t end
usage()
click to toggle source
Which usage does the user’s command options match?
# File lib/help_parser/completion.rb, line 23 def usage @specs[USAGE].each do |cmd| i = matches(cmd) raise NoMatch unless @hash.size==i @cache.each{|k,v|@hash[k]=v} # Variables return true # Good! Found matching usage. rescue NoMatch next ensure @cache.clear end false # Bad! Did not match any of the expected usage. end