<commit_before>module Temple
  # An engine is simply a chain of compilers (that often includes a parser,
  # some filters and a generator).
  #
  #   class MyEngine < Temple::Engine
  #     # First run MyParser, passing the :strict option
  #     use MyParser, :strict
  #
  #     # Then a custom filter
  #     use MyFilter
  #
  #     # Then some general optimizations filters
  #     filter :MultiFlattener
  #     filter :StaticMerger
  #     filter :DynamicInliner
  #
  #     # Finally the generator
  #     generator :ArrayBuffer, :buffer
  #   end
  #
  #   engine = MyEngine.new(:strict => "For MyParser")
  #   engine.compile(something)
  #
  class Engine
    include Mixins::Options

    def self.filters
      @filters ||= []
    end

    def self.use(filter, *options, &block)
      filters << [filter, options, block]
    end

    # Shortcut for <tt>use Temple::Filters::parser</tt>
    def self.filter(filter, *options, &block)
      use(Temple::Filters.const_get(filter), *options, &block)
    end

    # Shortcut for <tt>use Temple::Generators::parser</tt>
    def self.generator(compiler, *options, &block)
      use(Temple::Generators.const_get(compiler), *options, &block)
    end

    def initialize(opts = {})
      super

      @chain = self.class.filters.map do |filter, opt, block|
        result = {}
        opt.each do |key|
          result[key] = options[key] if options.has_key?(key)
        end
        filter.new(result, &block)
      end
    end

    def compile(thing)
      @chain.inject(thing) { |m, e| e.compile(m) }
    end
  end
end<commit_msg>more flexible chain building<commit_after>module Temple
  # An engine is simply a chain of compilers (that often includes a parser,
  # some filters and a generator).
  #
  #   class MyEngine < Temple::Engine
  #     # First run MyParser, passing the :strict option
  #     use MyParser, :strict
  #
  #     # Then a custom filter
  #     use MyFilter
  #
  #     # Then some general optimizations filters
  #     filter :MultiFlattener
  #     filter :StaticMerger
  #     filter :DynamicInliner
  #
  #     # Finally the generator
  #     generator :ArrayBuffer, :buffer
  #   end
  #
  #   engine = MyEngine.new(:strict => "For MyParser")
  #   engine.compile(something)
  #
  class Engine
    include Mixins::Options

    def self.chain
      @chain ||= []
    end

    def self.use(filter, *options, &block)
      chain << proc do |opts|
        filter.new(Hash[*opts.select {|k,v| options.include?(k) }.flatten], &block)
      end
    end

    # Shortcut for <tt>use Temple::Filters::parser</tt>
    def self.filter(filter, *options, &block)
      use(Temple::Filters.const_get(filter), *options, &block)
    end

    # Shortcut for <tt>use Temple::Generators::parser</tt>
    def self.generator(compiler, *options, &block)
      use(Temple::Generators.const_get(compiler), *options, &block)
    end

    def initialize(opts = {})
      super
      @chain = self.class.chain.map { |f| f.call(options) }
    end

    def compile(thing)
      @chain.inject(thing) { |m, e| e.compile(m) }
    end
  end
end
{'fraction_non_alphanumeric': 0.11897833818299386, 'fraction_numerical': 0.0, 'mean_word_length': 2.614485981308411, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 13, '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': '6233284', 'n_tokens_mistral': 994, 'n_tokens_neox': 981, 'n_words': 262}