blob: b203337e12633ba95e31fffa0f5fd8a9b58ed821 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
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) : String
raise_missing if @has_keys
# return literal string
@string
end
def run(
args : Hash(String, String) = {} of String => String,
) : String
if @has_keys
# check template args
raise_missing if args.size == 0
# build result
String.build do |r|
@tokens.each do |t|
r << t.get(args)
end
end
else
# no keys, return literal string
@string
end
end
private def raise_missing
raise "missing template args: %s" % [@tokens.select { |t|
t.type == :key
}.map { |t|
t.value
}.sort.join(", ")]
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
|