<commit_before>module Clive
  class Option
  
    # An Array of {Argument} instances.
    class ArgumentList < Array
    
      # List:  a b c d
      # Other: 1 2
      #
      # a and d are optional we want
      #    [a] [b 1] [c 2] [d]
      #
      # Check a against 1   => false
      # Check b against 1   => true
      #    Next item of other
      # Check c against 2   => true
      #    No more items therefore => false
      #
      #  [false, true, true, false]
      #
      # Fill bool array => [nil, 1, 2, nil]
      # Zip, etc...
      #
      #
      # Now Other: 1 2 3
      # And a and c match only even numbers
      # sim. b and d match only odd numbers
      # a and d still optional
      # 
      # Check a against 1  => false
      # Check b against 1  => true
      #   Next item of other
      # Check c against 2  => true
      #   Next item of other
      # Check d against 3  => true
      # 
      # this causes problems if we have another non-optional argument
      #
      # Same scenario:
      #
      #  diff = other.size - (args with optional.false?)  => 3 - 2 = 1
      #
      #  Check a against 1  => false
      #  Check b against 1  => true (mandatory so ok to add)
      #   Next item
      #  Check c against 2  => true (mandatory so ok to add)
      #   Next item
      #  Check d against 3  => true (optional but diff > 0 so ok to add)
      #   Diff -= 1
      #   End of List
      #   IT WORKED
      # 
      #
      
      def cool_zip(other)
        other = other.dup.compact
        # Find the number of 'spares'
        diff = other.size - find_all {|i| !i.optional? }.size
        r = []
        
        
        map do |arg|
          if arg.possible?(other.first)
            if arg.optional?
              if diff > 0
                [arg, other.shift]
              else
                [arg, nil]
              end
            else
              [arg, other.shift]
            end
          else
            [arg, nil]
          end
        end
      end

      def to_s
        map {|i| i.to_s }.join(' ').gsub('] [', ' ')
      end
    end
  
    class ArgumentParser
    
      attr_reader :opts, :args
      
      ARG_KEYS = {
        :args        => [:arg],
        :types       => [:type, :kind, :as],
        :matches     => [:match],
        :withins     => [:within, :in],
        :defaults    => [:default],
        :constraints => [:constraint]
      }.flip
      
      OPT_KEYS = {
        :head => [:head],
        :tail => [:tail]
      }.flip
      
      PLURAL_KEYS = {
        :args        => :arg,
        :types       => :type,
        :matches     => :match,
        :withins     => :within,
        :defaults    => :default,
        :constraints => :constraint
      }
    
      # @param [Hash]
      def initialize(options)      
        opts, hash = sort_opts(options)
        args = infer_args(args_to_hash(hash))
  
        args.map! {|arg| Clive::Argument.new(arg[:name] || 'arg', arg.without(:name)) }
        
        @opts = opts
        @args = ArgumentList.new(args)
      end
      
      protected
      
      # This does two things, it splits the options hash into two hashes as explained
      # below. AND normalises the names of the hash keys meaning they can be accessed
      # easily.
      #
      # @return [Array[Hash]] Two hashes.
      #  The first hash contains all options relevant to the Option, to be stored
      #  in +@opts+.
      #  The second hash contains all options for building the arguments and should
      #  be used in the relevant methods.
      #  Hash keys for the returned hashes will be mapped to standard names from
      #  common variations.
      def sort_opts(hash)  
        [get_and_rename_hash(hash, OPT_KEYS), get_and_rename_hash(hash, ARG_KEYS)]
      end
      
      # @param hash [Hash]
      # @param keys [Hash]
      def get_and_rename_hash(hash, keys)
        Hash[ hash.find_all {|k,v| keys.include?(k) } ].rename(keys)
      end
      
      
      # Pads +obj+ with +pad+ until it has size of +max+
      # @param obj [#size, #<<]
      # @param max [Integer]
      # @param pad [Object]
      def pad(obj, max, pad=nil)
        if obj.size < max
          (max - obj.size).times { obj << pad }
        end
        obj
      end<commit_msg>fixed bug, plural keys were not being sorted to correct hash.<commit_after>module Clive
  class Option
  
    # An Array of {Argument} instances.
    class ArgumentList < Array
    
      # List:  a b c d
      # Other: 1 2
      #
      # a and d are optional we want
      #    [a] [b 1] [c 2] [d]
      #
      # Check a against 1   => false
      # Check b against 1   => true
      #    Next item of other
      # Check c against 2   => true
      #    No more items therefore => false
      #
      #  [false, true, true, false]
      #
      # Fill bool array => [nil, 1, 2, nil]
      # Zip, etc...
      #
      #
      # Now Other: 1 2 3
      # And a and c match only even numbers
      # sim. b and d match only odd numbers
      # a and d still optional
      # 
      # Check a against 1  => false
      # Check b against 1  => true
      #   Next item of other
      # Check c against 2  => true
      #   Next item of other
      # Check d against 3  => true
      # 
      # this causes problems if we have another non-optional argument
      #
      # Same scenario:
      #
      #  diff = other.size - (args with optional.false?)  => 3 - 2 = 1
      #
      #  Check a against 1  => false
      #  Check b against 1  => true (mandatory so ok to add)
      #   Next item
      #  Check c against 2  => true (mandatory so ok to add)
      #   Next item
      #  Check d against 3  => true (optional but diff > 0 so ok to add)
      #   Diff -= 1
      #   End of List
      #   IT WORKED
      # 
      #
      
      def cool_zip(other)
        other = other.dup.compact
        # Find the number of 'spares'
        diff = other.size - find_all {|i| !i.optional? }.size
        r = []
        
        
        map do |arg|
          if arg.possible?(other.first)
            if arg.optional?
              if diff > 0
                [arg, other.shift]
              else
                [arg, nil]
              end
            else
              [arg, other.shift]
            end
          else
            [arg, nil]
          end
        end
      end

      def to_s
        map {|i| i.to_s }.join(' ').gsub('] [', ' ')
      end
    end
  
    class ArgumentParser
    
      attr_reader :opts, :args
      
      ARG_KEYS = {
        :args        => [:args, :arg],
        :types       => [:types, :type, :kind, :as],
        :matches     => [:matches, :match],
        :withins     => [:withins, :within, :in],
        :defaults    => [:defaults, :default],
        :constraints => [:constraints, :constraint]
      }.flip
      
      OPT_KEYS = {
        :head => [:head],
        :tail => [:tail]
      }.flip
      
      PLURAL_KEYS = {
        :args        => :arg,
        :types       => :type,
        :matches     => :match,
        :withins     => :within,
        :defaults    => :default,
        :constraints => :constraint
      }
    
      # @param [Hash]
      def initialize(options)      
        opts, hash = sort_opts(options)
        args = infer_args(args_to_hash(hash))
  
        args.map! {|arg| Clive::Argument.new(arg[:name] || 'arg', arg.without(:name)) }
        @opts = opts
        @args = ArgumentList.new(args)
      end
      
      protected
      
      # This does two things, it splits the options hash into two hashes as explained
      # below. AND normalises the names of the hash keys meaning they can be accessed
      # easily.
      #
      # @return [Array[Hash]] Two hashes.
      #  The first hash contains all options relevant to the Option, to be stored
      #  in +@opts+.
      #  The second hash contains all options for building the arguments and should
      #  be used in the relevant methods.
      #  Hash keys for the returned hashes will be mapped to standard names from
      #  common variations.
      def sort_opts(hash)
        [get_and_rename_hash(hash, OPT_KEYS), get_and_rename_hash(hash, ARG_KEYS)]
      end
      
      # @param hash [Hash]
      # @param keys [Hash]
      def get_and_rename_hash(hash, keys)
        Hash[ hash.find_all {|k,v| keys.include?(k) } ].rename(keys)
      end
      
      
      # Pads +obj+ with +pad+ until it has size of +max+
      # @param obj [#size, #<<]
      # @param max [Integer]
      # @param pad [Object]
      def pad(obj, max, pad=nil)
        if obj.size < max
          (max - obj.size).times { obj << pad }
        end
        obj
      end
{'fraction_non_alphanumeric': 0.10449994245597882, 'fraction_numerical': 0.005984578202324778, 'mean_word_length': 1.4212872666480914, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6797024', 'n_tokens_mistral': 2723, 'n_tokens_neox': 2642, 'n_words': 895}