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 (?:%\{(?[^\}]+)\}) | # match literal value (?[^%]+) | # match literal percent (?%) }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