diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/guff/template-cache.cr | 12 | ||||
| -rw-r--r-- | src/guff/template-token.cr | 21 | ||||
| -rw-r--r-- | src/guff/template.cr | 66 | 
3 files changed, 99 insertions, 0 deletions
diff --git a/src/guff/template-cache.cr b/src/guff/template-cache.cr new file mode 100644 index 0000000..7a20179 --- /dev/null +++ b/src/guff/template-cache.cr @@ -0,0 +1,12 @@ +module Guff +  class TemplateCache +    def initialize(@templates : Hash(Symbol, String)) +      @cache = {} of Symbol => Template +    end + +    def [](key : Symbol) : Template +      raise "unknown template: #{key}" unless @templates[key]? +      @cache[key] ||= Template.new(@templates[key]) +    end +  end +end diff --git a/src/guff/template-token.cr b/src/guff/template-token.cr new file mode 100644 index 0000000..04e8f11 --- /dev/null +++ b/src/guff/template-token.cr @@ -0,0 +1,21 @@ +module Guff +  class TemplateToken +    getter :type + +    def initialize(@type : Symbol, @val : String) +    end + +    def get(args : Hash(String, String)) +      case @type +      when :key +        raise "missing key: #{@val}" unless args.has_key?(@val) +        args[@val] +      when :val +        @val +      else +        # never reached +        raise "unknown token type: #{@type}" +      end +    end +  end +end diff --git a/src/guff/template.cr b/src/guff/template.cr new file mode 100644 index 0000000..01a4c86 --- /dev/null +++ b/src/guff/template.cr @@ -0,0 +1,66 @@ +module Guff +  class Template +    getter :string + +    def initialize(@string : String) +      @tokens = scan(@string) +      @has_keys = @tokens.select { |t| t.type == :key }.size > 0 +    end + +    def run(args = nil : Hash(String, String)?) : String +      if @has_keys +        # check template args +        if args || args.size == 0 +          raise "missing template args: %s" % [@tokens.select { |t|  +            t.type == :key +          }.join(", ")] +        end + +        # build result +        String.builder do |r| +          @tokens.each do |t| +            r << t.get(args) +          end +        end +      else +        # no keys, return literal string +        @string +      end +    end + +    SCAN_RE = %r{ +      # match key +      (?:%\{(?<key>[^\}]+)\}) + +      | + +      # match literal value +      (?<val>[^%]+) + +      | + +      # match literal percent +      (?<pct>%) +    }mx + +    private def scan(s : String) +      r = [] of TemplateToken + +      s.scan(SCAN_RE) do |md| +        if md["key"]? +          r << TemplateToken.new(:key, md["key"].strip) +        elsif md["val"]? +          r << TemplateToken.new(:val, md["val"]) +        elsif md["pct"]? +          r << TemplateToken.new(:val, "%") +        else +          # never reached +          raise "unknown match: #{md}" +        end +      end + +      # return result +      r +    end +  end +end  | 
