ltdtemplate 0.2.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +10 -1
- data/Gemfile +2 -1
- data/RESOURCES +18 -32
- data/TEMPLATE_MANUAL.html +126 -47
- data/lib/ltdtemplate.rb +352 -242
- data/lib/ltdtemplate/code.rb +14 -87
- data/lib/ltdtemplate/code/call.rb +20 -16
- data/lib/ltdtemplate/code/parameters.rb +28 -31
- data/lib/ltdtemplate/code/sequence.rb +39 -0
- data/lib/ltdtemplate/code/subscript.rb +57 -50
- data/lib/ltdtemplate/code/variable.rb +22 -39
- data/lib/ltdtemplate/proxy.rb +26 -0
- data/lib/ltdtemplate/proxy/array.rb +258 -0
- data/lib/ltdtemplate/proxy/boolean.rb +74 -0
- data/lib/ltdtemplate/proxy/match.rb +40 -0
- data/lib/ltdtemplate/proxy/nil.rb +27 -0
- data/lib/ltdtemplate/proxy/number.rb +77 -0
- data/lib/ltdtemplate/proxy/regexp.rb +74 -0
- data/lib/ltdtemplate/proxy/string.rb +196 -0
- data/lib/ltdtemplate/value.rb +94 -0
- data/lib/ltdtemplate/value/array_splat.rb +34 -0
- data/lib/ltdtemplate/value/code_block.rb +21 -17
- data/lib/ltdtemplate/value/namespace.rb +77 -79
- data/ltdtemplate.gemspec +2 -2
- data/test/04number.rb +0 -7
- data/test/05string.rb +0 -7
- data/test/06array.rb +0 -9
- data/test/07each.rb +3 -3
- data/test/08interpolate.rb +1 -1
- data/test/10missing_meth.rb +1 -1
- data/test/11classes.rb +9 -9
- metadata +15 -13
- data/lib/ltdtemplate/code/code_block.rb +0 -30
- data/lib/ltdtemplate/value/array.rb +0 -210
- data/lib/ltdtemplate/value/boolean.rb +0 -82
- data/lib/ltdtemplate/value/nil.rb +0 -30
- data/lib/ltdtemplate/value/number.rb +0 -96
- data/lib/ltdtemplate/value/string.rb +0 -215
- data/lib/test.rb +0 -10
- data/test/03tpl_singletons.rb +0 -48
@@ -0,0 +1,34 @@
|
|
1
|
+
# For array/ or array% (similar to Ruby's *array)
|
2
|
+
|
3
|
+
require 'ltdtemplate'
|
4
|
+
|
5
|
+
module LtdTemplate::Value; end
|
6
|
+
|
7
|
+
class LtdTemplate::Value::Array_Splat
|
8
|
+
|
9
|
+
include LtdTemplate::Method_Handler
|
10
|
+
|
11
|
+
attr_reader :named, :positional
|
12
|
+
|
13
|
+
# @param positional [Array] Positional parameters
|
14
|
+
# @param named [Array] Flat array of key, value pairs
|
15
|
+
def initialize (positional, named = nil)
|
16
|
+
@positional, @named = positional, named
|
17
|
+
end
|
18
|
+
|
19
|
+
# Evaluate support array splat methods. Very little is supported,
|
20
|
+
# as these are only intended to be used in parameter and subscript
|
21
|
+
# list expansions.
|
22
|
+
def evaluate (opts = {})
|
23
|
+
case opts[:method]
|
24
|
+
when 'type' then 'array_splat'
|
25
|
+
else nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Unlike arrays, these generate no template text.
|
30
|
+
def tpl_text; ''; end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# END
|
@@ -1,17 +1,19 @@
|
|
1
|
-
# LtdTemplate::Value::Code_Block - Represents an explicit code block
|
2
|
-
# LtdTemplate
|
1
|
+
# LtdTemplate::Value::Code_Block - Represents an explicit code block
|
2
|
+
# in an LtdTemplate
|
3
3
|
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# Code blocks are wrappers around code sequences. They are essentially
|
5
|
+
# anonymous functions; they accept optional parameters and create a new
|
6
|
+
# namespace for the duration of each execution.
|
7
7
|
#
|
8
8
|
# @author Brian Katzung <briank@kappacs.com>, Kappa Computer Solutions, LLC
|
9
|
-
# @copyright 2013 Brian Katzung and Kappa Computer Solutions, LLC
|
9
|
+
# @copyright 2013-2014 Brian Katzung and Kappa Computer Solutions, LLC
|
10
10
|
# @license MIT License
|
11
11
|
|
12
|
-
require 'ltdtemplate/
|
12
|
+
require 'ltdtemplate/value'
|
13
13
|
|
14
|
-
class LtdTemplate::Value::Code_Block
|
14
|
+
class LtdTemplate::Value::Code_Block
|
15
|
+
|
16
|
+
include LtdTemplate::Value
|
15
17
|
|
16
18
|
attr_reader :code
|
17
19
|
|
@@ -20,24 +22,26 @@ class LtdTemplate::Value::Code_Block < LtdTemplate::Code
|
|
20
22
|
@code = code
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
def
|
26
|
-
|
27
|
-
def get_value (opts = {})
|
25
|
+
# Evaluate supported methods on code blocks. Most methods
|
26
|
+
# are passed to the code block.
|
27
|
+
def evaluate (opts = {})
|
28
28
|
case opts[:method]
|
29
29
|
when nil then self
|
30
|
-
when '
|
30
|
+
when 'class' then 'Code'
|
31
|
+
when 'type' then 'code'
|
31
32
|
else
|
32
33
|
@template.push_namespace opts[:method], opts[:parameters],
|
33
34
|
:target => (opts[:target] || self)
|
34
|
-
result = @code.
|
35
|
+
result = rubyversed(@code).evaluate
|
35
36
|
@template.pop_namespace
|
36
37
|
result
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
#
|
41
|
-
|
41
|
+
# In contrast to an implied code block, an uncalled explicit code
|
42
|
+
# block generates no template output.
|
43
|
+
def tpl_text; ''; end
|
42
44
|
|
43
45
|
end
|
46
|
+
|
47
|
+
# END
|
@@ -1,150 +1,148 @@
|
|
1
1
|
# LtdTemplate::Value::Namespace - Represents an LtdTemplate variable namespace
|
2
2
|
#
|
3
3
|
# @author Brian Katzung <briank@kappacs.com>, Kappa Computer Solutions, LLC
|
4
|
-
# @copyright 2013 Brian Katzung and Kappa Computer Solutions, LLC
|
4
|
+
# @copyright 2013-2014 Brian Katzung and Kappa Computer Solutions, LLC
|
5
5
|
# @license MIT License
|
6
6
|
|
7
|
-
require '
|
7
|
+
require 'sarah'
|
8
|
+
require 'xkeys'
|
9
|
+
require 'ltdtemplate/value'
|
8
10
|
|
9
|
-
class LtdTemplate::Value::Namespace <
|
11
|
+
class LtdTemplate::Value::Namespace < Sarah
|
10
12
|
|
11
|
-
|
13
|
+
include LtdTemplate::Value
|
14
|
+
include XKeys::Hash
|
15
|
+
|
16
|
+
attr_reader :tpl_method, :parameters, :parent, :root, :template
|
12
17
|
attr_accessor :target
|
13
18
|
|
14
|
-
def initialize (template,
|
19
|
+
def initialize (template, tpl_method, parameters, parent = nil)
|
15
20
|
super template
|
16
|
-
@
|
21
|
+
@tpl_method, @parameters = tpl_method, parameters
|
17
22
|
@root = parent ? parent.root : self
|
18
23
|
@parent = parent
|
19
24
|
@target = nil
|
20
|
-
clear
|
25
|
+
clear()
|
21
26
|
end
|
22
27
|
|
23
|
-
def to_native
|
24
|
-
if @sarah.rnd_size == 3 then native = []
|
25
|
-
elsif @sarah.seq_size == 0 then native = {}
|
26
|
-
else native = Sarah.new
|
27
|
-
end
|
28
|
-
@sarah.each do |key, value|
|
29
|
-
# Exclude some permanent namespace attributes
|
30
|
-
native[key] = value.to_native unless key =~ /^[_@$]$/
|
31
|
-
end
|
32
|
-
native
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
28
|
# Clear values except for permanent namespace attributes.
|
37
|
-
#
|
38
29
|
def clear
|
39
30
|
super
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
self['_'] = @parameters
|
32
|
+
self['@'] = @root
|
33
|
+
self['^'] = @parent if @parent
|
34
|
+
self['$'] = self
|
44
35
|
self
|
45
36
|
end
|
46
37
|
|
47
|
-
#
|
38
|
+
# Evaluate supported methods on namespaces.
|
39
|
+
def evaluate (opts = {})
|
40
|
+
case opts[:method]
|
41
|
+
when nil, 'call' then self
|
42
|
+
when 'array', '*' # anonymous array
|
43
|
+
opts[:parameters] ? opts[:parameters] : @template.factory(:array)
|
44
|
+
when 'class' then 'Namespace'
|
45
|
+
when 'false' then false
|
46
|
+
when 'if' then do_if opts
|
47
|
+
when 'loop' then do_loop opts
|
48
|
+
when 'method' then @tpl_method
|
49
|
+
when 'nil' then nil
|
50
|
+
when 'target' then @target
|
51
|
+
when 'true' then true
|
52
|
+
when 'type' then 'namespace'
|
53
|
+
when 'use' then do_use opts
|
54
|
+
when 'var' then do_add_names opts
|
55
|
+
else super opts
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
48
59
|
# Search for the specified item in the current namespace or above.
|
49
|
-
#
|
50
60
|
def find_item (name)
|
51
61
|
namespace = self
|
52
62
|
while namespace
|
53
|
-
break if namespace.
|
63
|
+
break if namespace.has_key? name
|
54
64
|
namespace = namespace.parent
|
55
65
|
end
|
56
66
|
namespace
|
57
67
|
end
|
58
68
|
|
59
|
-
#
|
60
|
-
|
61
|
-
#
|
62
|
-
def method_string
|
63
|
-
@method_string ||= @template.factory :string, @method
|
64
|
-
end
|
69
|
+
# Namespaces do not generate template output.
|
70
|
+
def tpl_text; ''; end
|
65
71
|
|
66
|
-
|
67
|
-
|
68
|
-
when 'array', '*' # anonymous array
|
69
|
-
opts[:parameters] ? opts[:parameters] :
|
70
|
-
@template.factory(:parameters)
|
71
|
-
when 'false' then @template.factory :boolean, false
|
72
|
-
when 'if' then do_if opts
|
73
|
-
when 'loop' then do_loop opts
|
74
|
-
when 'method' then method_string
|
75
|
-
when 'nil' then @template.nil
|
76
|
-
when 'target' then @target || @template.nil
|
77
|
-
when 'true' then @template.factory :boolean, true
|
78
|
-
when 'use' then do_use opts
|
79
|
-
when 'var' then do_add_names opts
|
80
|
-
else super
|
81
|
-
end
|
82
|
-
end
|
72
|
+
# Auto-vivicate arrays in namespaces.
|
73
|
+
def xkeys_new (*args); @template.factory :array; end
|
83
74
|
|
84
|
-
|
85
|
-
def type; :namespace; end
|
75
|
+
###################################################
|
86
76
|
|
87
|
-
# Add new namespace names with nil or specific values
|
88
|
-
#
|
77
|
+
# Add new namespace names with nil or specific values.
|
78
|
+
# $.var(name1, ..., nameN .. key1, val1, ..., keyN, valN)
|
89
79
|
def do_add_names (opts)
|
90
|
-
params = opts[:parameters]
|
91
|
-
|
92
|
-
|
93
|
-
params.positional.each { |item| set_item(item.to_native, tnil) }
|
94
|
-
end
|
95
|
-
if params.named.size
|
96
|
-
params.named.each { |item, val| set_item(item, val) }
|
80
|
+
if params = opts[:parameters]
|
81
|
+
params.each(:seq) { |idx, val| self[val] = nil }
|
82
|
+
params.each(:nsq) { |key, val| self[key] = val }
|
97
83
|
end
|
98
|
-
|
84
|
+
nil
|
99
85
|
end
|
100
86
|
|
101
87
|
# Implement conditionals
|
88
|
+
# $.if(\{test1}, \{result1}, ..., \{testN}, \{resultN}, \{else_value})
|
102
89
|
def do_if (opts)
|
103
90
|
if params = opts[:parameters]
|
104
|
-
params.
|
105
|
-
e1 =
|
91
|
+
params.values(:seq).each_slice(2) do |pair|
|
92
|
+
e1 = rubyversed(pair[0]).evaluate :method => 'call'
|
106
93
|
|
107
94
|
#
|
108
95
|
# Return the "else" value, e1, in the absence of
|
109
96
|
# a condition/result value pair.
|
110
97
|
#
|
111
|
-
return e1
|
98
|
+
return e1 if pair.size == 1
|
112
99
|
|
113
100
|
# Return the e2 result if e1 evaluates to true
|
114
|
-
|
101
|
+
if rubyversed(e1).tpl_boolean
|
102
|
+
return rubyversed(pair[1]).evaluate :method => 'call'
|
103
|
+
end
|
115
104
|
end
|
116
105
|
end
|
117
|
-
|
106
|
+
nil
|
118
107
|
end
|
119
108
|
|
109
|
+
# Implement loops
|
110
|
+
# $.loop(\{pre_test}, \{body})
|
111
|
+
# $.loop(\{pre_test}, \{body}, \{post_test})
|
120
112
|
def do_loop (opts)
|
121
113
|
results = @template.factory :array
|
122
|
-
if params = opts[:parameters]
|
123
|
-
params
|
124
|
-
|
114
|
+
if (params = opts[:parameters]) && params.size(:seq) > 1
|
115
|
+
while rubyversed(params[0]).evaluate(:method => 'call').
|
116
|
+
in_rubyverse(@template).tpl_boolean
|
117
|
+
# RESOURCE iterations: Total loop iterations
|
125
118
|
@template.use :iterations
|
126
|
-
results.
|
127
|
-
break if params[2]
|
128
|
-
|
119
|
+
results.push rubyversed(params[1]).evaluate :method => 'call'
|
120
|
+
break if params.size(:seq) > 2 && !rubyversed(params[2]).
|
121
|
+
evaluate(:method => 'call').in_rubyverse(@template).
|
122
|
+
tpl_boolean
|
129
123
|
end
|
130
124
|
end
|
131
125
|
results
|
132
126
|
end
|
133
127
|
|
128
|
+
# Load external resources
|
134
129
|
def do_use (opts)
|
135
130
|
tpl = @template
|
136
|
-
if loader = tpl.options[:loader]
|
137
|
-
params
|
138
|
-
name = params
|
131
|
+
if (loader = tpl.options[:loader]) && (params = opts[:parameters]) &&
|
132
|
+
params.size(:seq) > 0
|
133
|
+
name = params[0]
|
139
134
|
if !tpl.used[name]
|
135
|
+
# RESOURCE use: Total $.use invocations
|
140
136
|
tpl.use :use
|
141
137
|
tpl.used[name] = true
|
142
138
|
result = loader.call(tpl, name)
|
143
|
-
tpl.parse_template(tpl.get_tokens result).
|
139
|
+
tpl.parse_template(tpl.get_tokens result).evaluate if
|
144
140
|
result.kind_of? String
|
145
141
|
end
|
146
142
|
end
|
147
|
-
|
143
|
+
nil
|
148
144
|
end
|
149
145
|
|
150
146
|
end
|
147
|
+
|
148
|
+
# END
|
data/ltdtemplate.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "ltdtemplate"
|
3
|
-
s.version = "0.
|
4
|
-
s.date = "2014-
|
3
|
+
s.version = "1.0.0"
|
4
|
+
s.date = "2014-05-20"
|
5
5
|
s.authors = ["Brian Katzung"]
|
6
6
|
s.email = ["briank@kappacs.com"]
|
7
7
|
s.homepage = "http://rubygems.org/gems/ltdtemplate"
|
data/test/04number.rb
CHANGED
@@ -7,13 +7,6 @@ class TestLtdTemplate_04 < MiniTest::Unit::TestCase
|
|
7
7
|
@tpl = LtdTemplate.new
|
8
8
|
end
|
9
9
|
|
10
|
-
def test_imethods
|
11
|
-
num = @tpl.factory :number
|
12
|
-
[
|
13
|
-
:get_value, :to_boolean, :to_native, :to_text
|
14
|
-
].each { |method| assert_respond_to num, method }
|
15
|
-
end
|
16
|
-
|
17
10
|
def test_basic
|
18
11
|
@tpl.parse '<<1>>'
|
19
12
|
assert_equal("1", @tpl.render, "literal")
|
data/test/05string.rb
CHANGED
@@ -7,13 +7,6 @@ class TestLtdTemplate_05 < MiniTest::Unit::TestCase
|
|
7
7
|
@tpl = LtdTemplate.new
|
8
8
|
end
|
9
9
|
|
10
|
-
def test_imethods
|
11
|
-
num = @tpl.factory :string, ''
|
12
|
-
[
|
13
|
-
:get_value, :to_boolean, :to_native, :to_text
|
14
|
-
].each { |method| assert_respond_to num, method }
|
15
|
-
end
|
16
|
-
|
17
10
|
def test_basic
|
18
11
|
@tpl.parse '<<"str">>'
|
19
12
|
assert_equal("str", @tpl.render, "literal")
|
data/test/06array.rb
CHANGED
@@ -7,15 +7,6 @@ class TestLtdTemplate_06 < MiniTest::Unit::TestCase
|
|
7
7
|
@tpl = LtdTemplate.new
|
8
8
|
end
|
9
9
|
|
10
|
-
def test_imethods
|
11
|
-
ary = @tpl.factory :array
|
12
|
-
[
|
13
|
-
:clear, :get_item, :get_value, :has_item?, :named, :positional,
|
14
|
-
:scalar?, :set_from_array, :set_from_hash, :set_item, :set_value,
|
15
|
-
:to_boolean, :to_native, :to_text
|
16
|
-
].each { |method| assert_respond_to ary, method }
|
17
|
-
end
|
18
|
-
|
19
10
|
def test_create
|
20
11
|
@tpl.parse '<<a=a.type" "a.size>>'
|
21
12
|
assert_equal 'array 0', @tpl.render
|
data/test/07each.rb
CHANGED
@@ -10,7 +10,7 @@ class TestLtdTemplate_07 < MiniTest::Unit::TestCase
|
|
10
10
|
def test_each
|
11
11
|
@tpl.parse <<'TPL'
|
12
12
|
<<a=(1,2,3..'four,4,'five,5,'six,6,7,7)
|
13
|
-
a.each({ $.*($.method
|
13
|
+
a.each({ $.*($.method,_[0].type,_[0],_[1]).join(",") }).join(";")
|
14
14
|
.>>
|
15
15
|
TPL
|
16
16
|
expected = {}
|
@@ -31,7 +31,7 @@ TPL
|
|
31
31
|
def test_each_rnd
|
32
32
|
@tpl.parse <<'TPL'
|
33
33
|
<<a=(1,2,3..'four,4,'five,5,'six,6,7,7)
|
34
|
-
a.each_rnd({ $.*($.method
|
34
|
+
a.each_rnd({ $.*($.method,_[0].type,_[0],_[1]).join(",") }).join(";")
|
35
35
|
.>>
|
36
36
|
TPL
|
37
37
|
expected = {}
|
@@ -49,7 +49,7 @@ TPL
|
|
49
49
|
def test_each_seq
|
50
50
|
@tpl.parse <<'TPL'
|
51
51
|
<<a=(1,2,3..'four,4,'five,5,'six,6,7,7)
|
52
|
-
a.each_seq({ $.*($.method
|
52
|
+
a.each_seq({ $.*($.method,_[0].type,_[0],_[1]).join(",") }).join(";")
|
53
53
|
.>>
|
54
54
|
TPL
|
55
55
|
expected = {}
|
data/test/08interpolate.rb
CHANGED
@@ -27,7 +27,7 @@ class TestLtdTemplate_08 < MiniTest::Unit::TestCase
|
|
27
27
|
c=('c, 'c, 'x, 'c, 'y, 'c) d=(1, a/, 4, b/, 7, c%, 8 .. 'd, 'd, 'y, 'd) >>
|
28
28
|
TPL
|
29
29
|
@tpl.render
|
30
|
-
d = @tpl.namespace
|
30
|
+
d = @tpl.namespace[?d]
|
31
31
|
assert_equal [1, 2, 3, 4, 5, 6, 7, 8], d.seq, "d (sequential)"
|
32
32
|
assert_equal({ ?a => ?a, ?b => ?b, ?c => ?c, ?d => ?d,
|
33
33
|
?x => ?c, ?y => ?d }, d.rnd, "d (random-access)")
|
data/test/10missing_meth.rb
CHANGED
@@ -5,7 +5,7 @@ class TestLtdTemplate_10 < MiniTest::Unit::TestCase
|
|
5
5
|
|
6
6
|
def test_missing_meth1
|
7
7
|
miss_meth = Proc.new do |tpl, obj, opt|
|
8
|
-
|
8
|
+
"#{obj.evaluate :method => 'type'}.#{opt[:method]};"
|
9
9
|
end
|
10
10
|
tpl = LtdTemplate.new :missing_method => miss_meth
|
11
11
|
tpl.parse "<<$.*.abc 1.def '.ghi>>"
|
data/test/11classes.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'ltdtemplate'
|
3
|
-
require 'ltdtemplate/
|
3
|
+
require 'ltdtemplate/proxy/nil'
|
4
4
|
|
5
5
|
class TestLtdTemplate_11 < MiniTest::Unit::TestCase
|
6
6
|
|
7
7
|
def test_classes1
|
8
|
-
LtdTemplate.set_classes :
|
8
|
+
LtdTemplate.set_classes :nil_proxy => Nil1
|
9
9
|
tpl = LtdTemplate.new
|
10
10
|
tpl.parse '<<$.nil.type>>'
|
11
11
|
assert_equal 'nil1', tpl.render, 'nil type after class class change'
|
12
12
|
|
13
13
|
tpl = LtdTemplate.new
|
14
|
-
tpl.set_classes :
|
14
|
+
tpl.set_classes :nil_proxy => Nil2
|
15
15
|
tpl.parse '<<$.nil.type>>'
|
16
16
|
assert_equal 'nil2', tpl.render, 'nil type after instance class change'
|
17
17
|
|
@@ -22,22 +22,22 @@ class TestLtdTemplate_11 < MiniTest::Unit::TestCase
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
-
class Nil1 < LtdTemplate::
|
25
|
+
class Nil1 < LtdTemplate::Proxy::Nil
|
26
26
|
|
27
|
-
def
|
27
|
+
def evaluate (opts = {})
|
28
28
|
case opts[:method]
|
29
|
-
when 'type' then
|
29
|
+
when 'type' then 'nil1'
|
30
30
|
else super
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
35
35
|
|
36
|
-
class Nil2 < LtdTemplate::
|
36
|
+
class Nil2 < LtdTemplate::Proxy::Nil
|
37
37
|
|
38
|
-
def
|
38
|
+
def evaluate (opts = {})
|
39
39
|
case opts[:method]
|
40
|
-
when 'type' then
|
40
|
+
when 'type' then 'nil2'
|
41
41
|
else super
|
42
42
|
end
|
43
43
|
end
|