<commit_before>require 'palletjack'
require 'fileutils'
require 'optparse'
require 'singleton'
require 'rugged'

class PalletJack

  # Superclass for PalletJack tool implementations
  #
  # Provides convenience methods for option parsing, file generation,
  # and warehouse structure management.
  #
  # Example:
  #   require 'palletjack/tool'
  #
  #   class MyTool < PalletJack::Tool
  #     def parse_options(parser)
  #       parser.on('-o DIR', '--output DIR',
  #                 'output directory',
  #                 String) {|dir| options[:output] = dir }
  #
  #       required_option :output
  #     end
  #   end
  #
  #   MyTool.run do
  #     jack['system'].each do |sys|
  #        config_dir :output, sys.name
  #        config_file :output, sys.name, "dump.yaml" do |file|
  #          file << sys.to_yaml
  #        end
  #     end
  #   end

  class Tool
    include Singleton

    # Run the +block+ given in the context of the tool singleton instance
    # as convenience for simple tools.
    #
    # More complex tools probably want to override parse_options to
    # add option parsing, and split functionality into multiple methods.
    #
    # Example:
    #
    #   MyTool.run { jack['system'].each {|sys| puts sys.to_yaml } }

    def self.run(&block)
      instance.instance_eval(&block)
    end

    # Initialize the singleton instance
    #
    # Default initialization will add options for --warehouse and --help
    # to the OptionParser, and set the banner to something useful.
    #
    # Any exceptions raised during option parsing will abort execution
    # with usage information.

    def initialize
      @parser = OptionParser.new
      @options = {}
      @option_checks = []

      @parser.banner = "Usage: #{$PROGRAM_NAME} -w <warehouse> [options]"
      @parser.separator ''
      @parser.on('-w DIR', '--warehouse DIR',
                 'warehouse directory', String) {|dir|
        @options[:warehouse] = dir }
      @parser.on_tail('-h', '--help', 'display usage information') {
        raise ArgumentError }

      parse_options(@parser)

      @parser.parse!
      @option_checks.each {|check| check.call }
    rescue
      abort(usage)
    end

    # Additional option parsing
    #
    # Implementations needing more options than the default --warehouse and
    # -- help should override this empty default

    def parse_options(parser)
    end

    # Require presence of one of the given options
    # Raises ArgumentError if none exist in options[]

    def required_option(*opts)
      @option_checks << lambda do
        raise ArgumentError unless opts.any? {|opt| options[opt]}
      end
    end

    # Require presence of no more than one of the given options
    # Raises ArgumentError if more than one exist in options[]

    def exclusive_options(*opts)
      @option_checks << lambda do
        raise ArgumentError if opts.count {|opt| options[opt]} > 1
      end
    end

    # Usage information from option parser
    #
    # Example:
    #
    #   abort(usage) unless options[:warehouse]

    def usage<commit_msg>Clarify rdoc for option parsing methods<commit_after>require 'palletjack'
require 'fileutils'
require 'optparse'
require 'singleton'
require 'rugged'

class PalletJack

  # Superclass for PalletJack tool implementations
  #
  # Provides convenience methods for option parsing, file generation,
  # and warehouse structure management.
  #
  # Example:
  #   require 'palletjack/tool'
  #
  #   class MyTool < PalletJack::Tool
  #     def parse_options(parser)
  #       parser.on('-o DIR', '--output DIR',
  #                 'output directory',
  #                 String) {|dir| options[:output] = dir }
  #
  #       required_option :output
  #     end
  #   end
  #
  #   MyTool.run do
  #     jack['system'].each do |sys|
  #        config_dir :output, sys.name
  #        config_file :output, sys.name, "dump.yaml" do |file|
  #          file << sys.to_yaml
  #        end
  #     end
  #   end

  class Tool
    include Singleton

    # Run the +block+ given in the context of the tool singleton instance
    # as convenience for simple tools.
    #
    # More complex tools probably want to override parse_options to
    # add option parsing, and split functionality into multiple methods.
    #
    # Example:
    #
    #   MyTool.run { jack['system'].each {|sys| puts sys.to_yaml } }

    def self.run(&block)
      instance.instance_eval(&block)
    end

    # Initialize the singleton instance
    #
    # Default initialization will add options for --warehouse and --help
    # to the OptionParser, and set the banner to something useful.
    #
    # Any exceptions raised during option parsing will abort execution
    # with usage information.

    def initialize
      @parser = OptionParser.new
      @options = {}
      @option_checks = []

      @parser.banner = "Usage: #{$PROGRAM_NAME} -w <warehouse> [options]"
      @parser.separator ''
      @parser.on('-w DIR', '--warehouse DIR',
                 'warehouse directory', String) {|dir|
        @options[:warehouse] = dir }
      @parser.on_tail('-h', '--help', 'display usage information') {
        raise ArgumentError }

      parse_options(@parser)

      @parser.parse!
      @option_checks.each {|check| check.call }
    rescue
      abort(usage)
    end

    # Additional option parsing
    #
    # The default instance initalization will add option parsing for
    # <tt>-w</tt>/<tt>--warehouse</tt> and <tt>-h</tt>/<tt>--help</tt>,
    # and a simple banner string.
    #
    # Implementations needing more options than the default, a more
    # informative banner, or requirement checks for parsed options should
    # override this empty method.
    #
    # Any exceptions raised will abort execution with usage information.
    #
    # Example:
    #
    #   class MyTool < PalletJack::Tool
    #     def parse_options(parser)
    #       parser.on('-o DIR', '--output DIR',
    #                 'output directory',
    #                 String) {|dir| options[:output] = dir }
    #
    #       required_option :output
    #     end
    #   end

    def parse_options(parser)
    end

    # Require the presence of one of the given options.
    #
    # Must not be called outside the scope of the parse_options method.
    #
    # Raises ArgumentError if none exist in options[]
    #
    # Example:
    #
    #   def parse_options(parser)
    #     ...
    #     required_option :output
    #   end

    def required_option(*opts)
      @option_checks << lambda do
        raise ArgumentError unless opts.any? {|opt| options[opt]}
      end
    end

    # Require the presence of no more than one of the given options.
    #
    # Must not be called outside the scope of the parse_options method.
    #
    # Raises ArgumentError if more than one exist in options[]
    #
    # Example:
    #
    #   def parse_options(parse)
    #     ...
    #     required_option :output_file, :output_stdout
    #     exclusive_options :output_file, :output_stdout
    #   end

    def exclusive_options(*opts)
      @option_checks << lambda do
        raise ArgumentError if opts.count {|opt| options[opt]} > 1
      end
    end

    # Usage information from option parser
    #
    # Example:
    #
    #   abort(usage) unless options[:warehouse]

    def usage
{'fraction_non_alphanumeric': 0.09659789588741631, 'fraction_numerical': 0.00027326137450471376, 'mean_word_length': 2.3152173913043477, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 15, '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': '317708', 'n_tokens_mistral': 2159, 'n_tokens_neox': 2086, 'n_words': 669}