diff options
-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 |