aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/guff/template-cache.cr12
-rw-r--r--src/guff/template-token.cr21
-rw-r--r--src/guff/template.cr66
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