<commit_before>require 'pathname'
require 'nm/template'

module Nm

  class Source

    attr_reader :root, :ext, :cache, :template_class

    def initialize(root, opts = nil)
      opts ||= {}
      @root  = Pathname.new(root.to_s)
      @ext   = opts[:ext] ? ".#{opts[:ext]}" : nil
      @cache = opts[:cache] ? Hash.new : NullCache.new

      @template_class = Class.new(Template) do
        (opts[:locals] || {}).each{ |key, value| define_method(key){ value } }
      end
    end

    def inspect
      "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @root=#{@root.inspect}>"
    end

    def data(file_path)
      @cache[file_path] ||= begin
        File.send(File.respond_to?(:binread) ? :binread : :read, file_path)
      end
    end

    def render(template_name, locals = nil)
      if (filename = source_file_path(template_name)).nil?
        template_desc = "a template file named #{template_name.inspect}"
        if !@ext.nil?
          template_desc += " that ends in #{@ext.inspect}"
        end
        raise ArgumentError, "#{template_desc} does not exist"
      end
      @template_class.new(self, filename, locals || {}).__data__
    end

    alias_method :partial, :render

    private

    def source_file_path(name)
      Dir.glob(self.root.join(name.end_with?(@ext) ? name : "#{name}*#{@ext}")).first
    end

    class NullCache
      def [](template_name);         end
      def []=(template_name, value); end
      def keys; [];                  end
    end

  end

  class DefaultSource < Source

    def initialize
      super('/')<commit_msg>(hotfix) fix Source file globbing to work in newer ruby versions<commit_after>require 'pathname'
require 'nm/template'

module Nm

  class Source

    attr_reader :root, :ext, :cache, :template_class

    def initialize(root, opts = nil)
      opts ||= {}
      @root  = Pathname.new(root.to_s)
      @ext   = opts[:ext] ? ".#{opts[:ext]}" : nil
      @cache = opts[:cache] ? Hash.new : NullCache.new

      @template_class = Class.new(Template) do
        (opts[:locals] || {}).each{ |key, value| define_method(key){ value } }
      end
    end

    def inspect
      "#<#{self.class}:#{'0x0%x' % (object_id << 1)} @root=#{@root.inspect}>"
    end

    def data(file_path)
      @cache[file_path] ||= begin
        File.send(File.respond_to?(:binread) ? :binread : :read, file_path)
      end
    end

    def render(template_name, locals = nil)
      if (filename = source_file_path(template_name)).nil?
        template_desc = "a template file named #{template_name.inspect}"
        if !@ext.nil?
          template_desc += " that ends in #{@ext.inspect}"
        end
        raise ArgumentError, "#{template_desc} does not exist"
      end
      @template_class.new(self, filename, locals || {}).__data__
    end

    alias_method :partial, :render

    private

    def source_file_path(name)
      Dir.glob(self.root.join(source_file_glob_string(name))).first
    end

    def source_file_glob_string(name)
      !@ext.nil? && name.end_with?(@ext) ? name : "#{name}*#{@ext}"
    end

    class NullCache
      def [](template_name);         end
      def []=(template_name, value); end
      def keys; [];                  end
    end

  end

  class DefaultSource < Source

    def initialize
      super('/')
{'fraction_non_alphanumeric': 0.14242239805234327, 'fraction_numerical': 0.0018259281801582471, 'mean_word_length': 2.568946796959826, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, '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': '5676242', 'n_tokens_mistral': 1093, 'n_tokens_neox': 1066, 'n_words': 252}