lokar 0.1.0 → 0.2.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/lokar.rb +90 -74
- metadata +16 -5
data/lokar.rb
CHANGED
@@ -2,133 +2,149 @@ require 'strscan'
|
|
2
2
|
|
3
3
|
module Lokar
|
4
4
|
def self.render(string, filename = '<Lokar>', binding = nil)
|
5
|
-
|
6
|
-
|
7
|
-
eval(output.join, binding, filename).join
|
5
|
+
eval("__output__ = []#{parse(string, filename).join}; __output__", binding, filename).join
|
8
6
|
end
|
9
7
|
|
10
8
|
def self.compile(string, filename = '<Lokar>', binding = nil)
|
11
|
-
|
12
|
-
|
13
|
-
eval output.join, binding, filename
|
9
|
+
eval "Proc.new do __output__ = []#{parse(string, filename).join}; __output__ end", binding, filename
|
14
10
|
end
|
15
11
|
|
16
12
|
def self.parse(string, filename)
|
17
13
|
scanner = StringScanner.new(string)
|
18
|
-
output = []
|
19
14
|
prev_text = false
|
20
15
|
prev_output = true
|
16
|
+
output = []
|
17
|
+
line = 1
|
18
|
+
flushed = 1
|
21
19
|
|
22
20
|
while true
|
23
|
-
match = scanner.scan_until(/(?=<\?r[ \t]
|
21
|
+
match = scanner.scan_until(/(?=<\?r(?:[ \t]|$)|\#?\#{|^[ \t]*%|(?:\r\n?|\n))/m)
|
24
22
|
if match
|
25
23
|
# Add the text before the match
|
26
|
-
|
27
|
-
output.insert(-1, match.inspect)
|
28
|
-
else
|
24
|
+
unless prev_text
|
29
25
|
if prev_output
|
30
|
-
output << "
|
26
|
+
output << "<<"
|
31
27
|
else
|
32
|
-
output << "
|
28
|
+
output << ";__output__<<"
|
33
29
|
prev_output = true
|
34
30
|
end
|
35
|
-
output << match.inspect
|
36
31
|
prev_text = true
|
37
32
|
end
|
33
|
+
output << match.inspect
|
38
34
|
|
39
35
|
case # Find out what of the regular expression matched
|
40
|
-
when scanner.
|
36
|
+
when match = scanner.scan(/\r\n?|\n/) # Parse newlines
|
37
|
+
unless prev_text
|
38
|
+
if prev_output
|
39
|
+
output << "<<"
|
40
|
+
else
|
41
|
+
output << ";__output__<<"
|
42
|
+
prev_output = true
|
43
|
+
end
|
44
|
+
prev_text = true
|
45
|
+
end
|
46
|
+
output << match.inspect
|
47
|
+
line += 1
|
48
|
+
|
49
|
+
when scanner.match?(/</) # Parse <?r?> tags
|
41
50
|
scanner.pos += 3
|
42
51
|
result = scanner.scan_until(/(?=\?>)/m)
|
43
|
-
raise "#{filename}: Unterminated
|
44
|
-
|
45
|
-
output << "\n"
|
46
|
-
output << result
|
52
|
+
raise "#{filename}:#{line}: Unterminated <\?r ?> tag" unless result
|
47
53
|
|
54
|
+
output << ("\n" * (line - flushed)) << ";" << result
|
55
|
+
flushed = line
|
48
56
|
prev_text = false
|
49
57
|
prev_output = false
|
50
58
|
|
51
59
|
scanner.pos += 2
|
52
60
|
|
53
|
-
when scanner.
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
when scanner.skip(/\#/) # Parse #{ } tags
|
62
|
+
if scanner.skip(/\#/)
|
63
|
+
unless prev_text
|
64
|
+
if prev_output
|
65
|
+
output << "<<"
|
66
|
+
else
|
67
|
+
output << ";__output__<<"
|
68
|
+
prev_output = true
|
69
|
+
end
|
70
|
+
prev_text = true
|
71
|
+
end
|
72
|
+
output << '#'.inspect
|
59
73
|
else
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
index = 1
|
75
|
+
scanner.pos += 1
|
76
|
+
|
77
|
+
if prev_output
|
78
|
+
output << "<<" << ("\n" * (line - flushed)) << "("
|
79
|
+
else
|
80
|
+
output << ("\n" * (line - flushed)) << ";__output__<<("
|
81
|
+
prev_output = true
|
82
|
+
end
|
83
|
+
flushed = line
|
84
|
+
prev_text = false
|
85
|
+
|
86
|
+
while true
|
87
|
+
result = scanner.scan_until(/(?=}|{)/m)
|
88
|
+
raise "#{filename}:#{line}: Unterminated \#\{ } tag" unless result
|
89
|
+
output << result
|
90
|
+
case
|
91
|
+
when scanner.skip(/{/)
|
92
|
+
index += 1
|
93
|
+
output << '{'
|
94
|
+
|
95
|
+
when scanner.skip(/}/)
|
96
|
+
index -= 1
|
97
|
+
break if index == 0
|
98
|
+
output << '}'
|
99
|
+
end
|
77
100
|
end
|
101
|
+
|
102
|
+
output << ")"
|
78
103
|
end
|
79
|
-
|
80
|
-
output << ")"
|
81
|
-
|
82
|
-
prev_output = true
|
83
|
-
prev_text = false
|
84
104
|
|
85
105
|
else # Parse %, %% and %= lines
|
86
106
|
result = scanner.scan(/[ \t]*%/)
|
87
|
-
if scanner.
|
88
|
-
|
89
|
-
if prev_text
|
90
|
-
output << result
|
91
|
-
else
|
107
|
+
if scanner.skip(/%/)
|
108
|
+
unless prev_text
|
92
109
|
if prev_output
|
93
|
-
output << "
|
110
|
+
output << "<<"
|
94
111
|
else
|
95
|
-
output << "
|
112
|
+
output << ";__output__<<"
|
96
113
|
prev_output = true
|
97
114
|
end
|
98
|
-
output << result
|
99
115
|
prev_text = true
|
100
116
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
else
|
106
|
-
output << "\n__output__ << ("
|
107
|
-
prev_output = true
|
108
|
-
end
|
109
|
-
output << scanner.scan_until(/(\r\n|\n|\Z)/)
|
110
|
-
output << ")"
|
117
|
+
output << result.inspect
|
118
|
+
elsif scanner.skip(/=/)
|
119
|
+
if prev_output
|
120
|
+
output << "<<" << ("\n" * (line - flushed)) << "("
|
111
121
|
else
|
112
|
-
output << "\n"
|
113
|
-
|
114
|
-
prev_output = false
|
122
|
+
output << ("\n" * (line - flushed)) << ";__output__<<("
|
123
|
+
prev_output = true
|
115
124
|
end
|
125
|
+
flushed = line
|
126
|
+
prev_text = false
|
127
|
+
output << scanner.scan_until(/(?=\r\n|\n|\Z)/) << ")"
|
128
|
+
else
|
129
|
+
output << ("\n" * (line - flushed)) << ";" << scanner.scan_until(/\r\n|\n|\Z/)
|
130
|
+
flushed = line
|
116
131
|
prev_text = false
|
132
|
+
prev_output = false
|
117
133
|
end
|
118
134
|
end
|
119
135
|
else # End of file
|
120
136
|
unless scanner.eos?
|
121
137
|
# Add the pending text
|
122
|
-
|
123
|
-
output << scanner.rest.inspect
|
124
|
-
else
|
138
|
+
unless prev_text
|
125
139
|
if prev_output
|
126
|
-
output << "
|
140
|
+
output << "<<"
|
127
141
|
else
|
128
|
-
output << "
|
142
|
+
output << ";__output__<<"
|
143
|
+
prev_output = true
|
129
144
|
end
|
130
|
-
|
145
|
+
prev_text = true
|
131
146
|
end
|
147
|
+
output << scanner.rest.inspect
|
132
148
|
end
|
133
149
|
break
|
134
150
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lokar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Zoxc
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-09-20 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -34,21 +39,27 @@ rdoc_options: []
|
|
34
39
|
require_paths:
|
35
40
|
- .
|
36
41
|
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
37
43
|
requirements:
|
38
44
|
- - ">="
|
39
45
|
- !ruby/object:Gem::Version
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 9
|
49
|
+
- 0
|
40
50
|
version: 1.9.0
|
41
|
-
version:
|
42
51
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
43
53
|
requirements:
|
44
54
|
- - ">="
|
45
55
|
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
46
58
|
version: "0"
|
47
|
-
version:
|
48
59
|
requirements: []
|
49
60
|
|
50
61
|
rubyforge_project:
|
51
|
-
rubygems_version: 1.3.
|
62
|
+
rubygems_version: 1.3.7
|
52
63
|
signing_key:
|
53
64
|
specification_version: 3
|
54
65
|
summary: Lokar is a simple fast template engine.
|