<commit_before># coding: utf-8
require 'argparser/tools'
require 'argparser/option'

class ArgParser
  include Tools

  # Output messages used in the #terminate method
  OUT_VERSION = '%s%s %s'
  OUT_COPYRIGHT = 'Copyright (C) %s'
  OUT_LICENSE = 'License: %s'
  OUT_HOMEPAGE = '%s home page: %s'
  OUT_BUGS = 'Report bugs to: %s'
  OUT_MANIFEST_EXPECTED = 'Property expected through the manifest: %s'
  OUT_MULTIPLE_INPUTS = 'Multiple input argument not allowed in the middle: %s'
  OUT_MULTIPLE_NAMES = 'Multiple names for the input argument: %s'
  OUT_OPTION_NULL = 'Empty name for option'
  OUT_REQUIRED = 'Required input argument after optional one: %s'
  OUT_REQUIRED_DEFAULT = 'Required option has default value: %s'
  OUT_UNEXPECTED_ARGUMENT = 'Unexpected argument: %s'
  OUT_UNKNOWN_OPTION = 'Unknown option: %s'
  OUT_OPTION_ARGUMENT_EXPECTED = 'Expected argument for the option: %s'
  OUT_SINGLE_OPTION = 'Multiple options not allowed: %s'
  OUT_OPTION_EXPECTED = 'Expected option: %s'
  OUT_ARGUMENT_EXPECTED = 'Expected argument: %s'
  OUT_UNIQUE_NAME = 'Option name should be unique: %s'
  OUT_INVALID_OPTION = 'Invalid value for option: %s'
  OPT_ENOUGH  = '--'

  # These options don't display their synopsis and given for free unless
  # explicitly specified in the manifest.
  OPT_HELP    = 'help'
  OPT_VERSION = 'version'
  OPTS_RESERVED = [OPT_HELP, OPT_VERSION]

  attr_reader :program    # Program name, REQUIRED
  attr_reader :package    # Set to nil if there's no package
  attr_reader :version    # Follow semantic versioning rules, REQUIRED
  attr_reader :copyright  # '2015 Somebody, Inc.',
  attr_reader :license    # Give license headline
  attr_reader :info       # Set additional lines that would follow license
  attr_reader :bugs       # Address to post bug reports
  attr_reader :homepage   # Package or, if absent, program's home page
  attr_reader :synopsis   # Print this if present or construct from options
  attr_reader :help       # Print this if present or construct from options
  attr_reader :options    # Array of options,
                          # see ArgParser::Option class' attr_readers

  # Returns option by any of its names given
  def [](name)
    options.find{|o| o.names.include?(name)}
  end

  # Returns array of input args in order
  def inputs
    options.select{|o| o.input}
  end

  def initialize(manifest)
    manifest = (safe_return('$config.manifest') || {}).merge(manifest)
    hash2vars!(manifest)
    @options = (manifest[:options] || manifest['options'] || []).
      map {|o| o.kind_of?(Option) ? o : Option.new(o)}
    if !self['help']
      options << Option.new(:names    => OPT_HELP,
                            :help     => 'Print this help and exit.',
                            :validate => (lambda { |o, p|
                              return true if o.count < 1
                              p.terminate(0, p.printed_help) }))
    end
    if !self['version']
      options << Option.new(:names    => OPT_VERSION,
                            :help     => 'Print version and exit.',
                            :validate => (lambda { |o, p|
                              return true if o.count < 1
                              p.terminate(0, p.printed_version) }))
    end
  end

  # Uses ARGV by default, but you may supply your own arguments
  # It exits if bad arguments given or they aren't validated.
  def parse!(arguments = ARGV)
    @options.each(&:reset!)

    {:program => @program, :version => @version}.each do |k, v|
      if !v || v.to_s.strip.empty?
        terminate(2, OUT_MANIFEST_EXPECTED % k)
      end
    end

    is = inputs
    is.each_with_index do |i, index|
      if index < is.length-1 and i.multiple
        terminate(2, OUT_MULTIPLE_INPUTS % i.name)
      end
      if i.names.size > 1
        terminate(2, OUT_MULTIPLE_NAMES % i.name)
      end
    end
    first_optional = is.index{|i| !i.required} || is.size
    last_required  = is.rindex{|i| i.required} || 0
    if last_required > first_optional
      terminate(2, OUT_REQUIRED % is[last_required].name)
    end

    names = {}
    options.each do |option|
      option.names.each do |name|
        if name.empty?
          terminate(2, OUT_OPTION_NULL)
        end
        if names.has_key?(name)
          terminate(2, OUT_UNIQUE_NAME % name)
        end
        names[name] = option
      end
      if option.required && option.default
        terminate(2, OUT_REQUIRED_DEFAULT % option.name)
      end
    end

    OPTS_RESERVED.each { |o|
      next unless arguments.include?("--#{o}")
      o = self[o]
      o.set_value(nil)
      o.validate!(self)
    }

    args = arguments.dup
    enough = false
    while (a = args.shift)
      if a == OPT_ENOUGH
        enough = true
      elsif enough || (a =~ /^[^-]/) || (a == '-') # input argument
        if (input = inputs.find{|i| !i.value || i.multiple})
          input.set_value(a)
        else
          terminate(2, OUT_UNEXPECTED_ARGUMENT % a)
        end
      elsif a =~ /^--(.+)/ # long option<commit_msg>reset reserved option if validated<commit_after># coding: utf-8
require 'argparser/tools'
require 'argparser/option'

class ArgParser
  include Tools

  # Output messages used in the #terminate method
  OUT_VERSION = '%s%s %s'
  OUT_COPYRIGHT = 'Copyright (C) %s'
  OUT_LICENSE = 'License: %s'
  OUT_HOMEPAGE = '%s home page: %s'
  OUT_BUGS = 'Report bugs to: %s'
  OUT_MANIFEST_EXPECTED = 'Property expected through the manifest: %s'
  OUT_MULTIPLE_INPUTS = 'Multiple input argument not allowed in the middle: %s'
  OUT_MULTIPLE_NAMES = 'Multiple names for the input argument: %s'
  OUT_OPTION_NULL = 'Empty name for option'
  OUT_REQUIRED = 'Required input argument after optional one: %s'
  OUT_REQUIRED_DEFAULT = 'Required option has default value: %s'
  OUT_UNEXPECTED_ARGUMENT = 'Unexpected argument: %s'
  OUT_UNKNOWN_OPTION = 'Unknown option: %s'
  OUT_OPTION_ARGUMENT_EXPECTED = 'Expected argument for the option: %s'
  OUT_SINGLE_OPTION = 'Multiple options not allowed: %s'
  OUT_OPTION_EXPECTED = 'Expected option: %s'
  OUT_ARGUMENT_EXPECTED = 'Expected argument: %s'
  OUT_UNIQUE_NAME = 'Option name should be unique: %s'
  OUT_INVALID_OPTION = 'Invalid value for option: %s'
  OPT_ENOUGH  = '--'

  # These options don't display their synopsis and given for free unless
  # explicitly specified in the manifest.
  OPT_HELP    = 'help'
  OPT_VERSION = 'version'
  OPTS_RESERVED = [OPT_HELP, OPT_VERSION]

  attr_reader :program    # Program name, REQUIRED
  attr_reader :package    # Set to nil if there's no package
  attr_reader :version    # Follow semantic versioning rules, REQUIRED
  attr_reader :copyright  # '2015 Somebody, Inc.',
  attr_reader :license    # Give license headline
  attr_reader :info       # Set additional lines that would follow license
  attr_reader :bugs       # Address to post bug reports
  attr_reader :homepage   # Package or, if absent, program's home page
  attr_reader :synopsis   # Print this if present or construct from options
  attr_reader :help       # Print this if present or construct from options
  attr_reader :options    # Array of options,
                          # see ArgParser::Option class' attr_readers

  # Returns option by any of its names given
  def [](name)
    options.find{|o| o.names.include?(name)}
  end

  # Returns array of input args in order
  def inputs
    options.select{|o| o.input}
  end

  def initialize(manifest)
    manifest = (safe_return('$config.manifest') || {}).merge(manifest)
    hash2vars!(manifest)
    @options = (manifest[:options] || manifest['options'] || []).
      map {|o| o.kind_of?(Option) ? o : Option.new(o)}
    if !self['help']
      options << Option.new(:names    => OPT_HELP,
                            :help     => 'Print this help and exit.',
                            :validate => (lambda { |o, p|
                              return true if o.count < 1
                              p.terminate(0, p.printed_help) }))
    end
    if !self['version']
      options << Option.new(:names    => OPT_VERSION,
                            :help     => 'Print version and exit.',
                            :validate => (lambda { |o, p|
                              return true if o.count < 1
                              p.terminate(0, p.printed_version) }))
    end
  end

  # Uses ARGV by default, but you may supply your own arguments
  # It exits if bad arguments given or they aren't validated.
  def parse!(arguments = ARGV)
    @options.each(&:reset!)

    {:program => @program, :version => @version}.each do |k, v|
      if !v || v.to_s.strip.empty?
        terminate(2, OUT_MANIFEST_EXPECTED % k)
      end
    end

    is = inputs
    is.each_with_index do |i, index|
      if index < is.length-1 and i.multiple
        terminate(2, OUT_MULTIPLE_INPUTS % i.name)
      end
      if i.names.size > 1
        terminate(2, OUT_MULTIPLE_NAMES % i.name)
      end
    end
    first_optional = is.index{|i| !i.required} || is.size
    last_required  = is.rindex{|i| i.required} || 0
    if last_required > first_optional
      terminate(2, OUT_REQUIRED % is[last_required].name)
    end

    names = {}
    options.each do |option|
      option.names.each do |name|
        if name.empty?
          terminate(2, OUT_OPTION_NULL)
        end
        if names.has_key?(name)
          terminate(2, OUT_UNIQUE_NAME % name)
        end
        names[name] = option
      end
      if option.required && option.default
        terminate(2, OUT_REQUIRED_DEFAULT % option.name)
      end
    end

    OPTS_RESERVED.each { |o|
      next unless arguments.include?("--#{o}")
      o = self[o]
      o.set_value(nil)
      o.validate!(self)
      o.reset! # If it didn't terminate while validating
    }

    args = arguments.dup
    enough = false
    while (a = args.shift)
      if a == OPT_ENOUGH
        enough = true
      elsif enough || (a =~ /^[^-]/) || (a == '-') # input argument
        if (input = inputs.find{|i| !i.value || i.multiple})
          input.set_value(a)
        else
          terminate(2, OUT_UNEXPECTED_ARGUMENT % a)
        end
      elsif a =~ /^--(.+)/ # long option
{'fraction_non_alphanumeric': 0.1057919621749409, 'fraction_numerical': 0.004137115839243499, 'mean_word_length': 2.46518771331058, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 23, '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': '4354390', 'n_tokens_mistral': 3233, 'n_tokens_neox': 3177, 'n_words': 946}